<!doctype html>
<html lang="en">
<head><base href="about:srcdoc"><script>(function(){function n(){parent.postMessage({t:'share:hash',h:location.hash},'*')}addEventListener('hashchange',n);addEventListener('message',function(e){if(e.source!==parent)return;var d=e.data||{};if(d.t==='share:setHash'&&typeof d.h==='string'&&d.h!==location.hash){location.hash=d.h}});addEventListener('DOMContentLoaded',function(){parent.postMessage({t:'share:ready',h:location.hash},'*')});})();</script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bhutan ePhyto Hub — Implementation plan (in eR terms)</title>
  <script type="module">
    import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
    mermaid.initialize({ startOnLoad: true, theme: 'base', themeVariables: { primaryColor: '#eef5fc', primaryBorderColor: '#0b5cab', primaryTextColor: '#122033', lineColor: '#536173', fontSize: '14px', fontFamily: 'Segoe UI, Arial, sans-serif' } });
  </script>
  <style>
    :root{--bg:#f7f9fc;--paper:#fff;--ink:#122033;--muted:#536173;--line:#d9e1ea;--accent:#0b5cab;--soft:#eef5fc;--ok:#0f7a3a;--warn:#a45c00;--ok-bg:#e8f5ee;--warn-bg:#fff8ee;--bad-bg:#f7ebea;--bad:#a8201a}
    *{box-sizing:border-box}
    body{margin:0;background:linear-gradient(180deg,#f3f7fb,#eef4f9 35%,#f7f9fc);color:var(--ink);font:17px/1.55 "Segoe UI",Arial,sans-serif}
    .wrap{max-width:1020px;margin:0 auto;padding:32px 24px 56px}
    .hero,.card{background:var(--paper);border:1px solid var(--line);border-radius:18px;box-shadow:0 12px 36px rgba(18,32,51,.06)}
    .hero{padding:28px 30px 22px;margin-bottom:18px}
    .eyebrow{margin:0 0 8px;color:var(--accent);font:700 12px/1.2 Arial,sans-serif;letter-spacing:.12em;text-transform:uppercase}
    h1,h2{font-family:Georgia,"Times New Roman",serif}
    h1{margin:0 0 12px;font-size:32px;line-height:1.1}
    h2{margin:0 0 14px;font-size:22px}
    .lede{margin:0;color:var(--muted)}
    .card{padding:22px 26px;margin-bottom:14px}
    .card p{margin:0 0 12px}
    .diagram{padding:24px;background:#fafbfd;border:1px solid var(--line);border-radius:14px;text-align:center;overflow:auto}
    table{width:100%;border-collapse:collapse;margin:10px 0 0;font-size:15px}
    th,td{padding:11px 12px;vertical-align:top;border-top:1px solid var(--line);text-align:left}
    th{border-top:0;color:var(--accent);font-size:12px;letter-spacing:.06em;text-transform:uppercase;background:#fafbfd}
    .step{padding:14px 16px;border-radius:10px;background:var(--soft);border:1px solid #cfe0f1;margin:10px 0;font-size:15px}
    .step strong{display:block;color:var(--accent);margin-bottom:4px;font-size:13px;letter-spacing:.04em;text-transform:uppercase}
    .step.risk{background:var(--warn-bg);border-color:#f0d9b5}
    .step.risk strong{color:var(--warn)}
    .who{display:inline-block;padding:2px 9px;border-radius:999px;font-size:12px;font-weight:600;background:#fff;border:1px solid var(--line);margin-left:6px;color:var(--muted)}
    .who.us{background:var(--ok-bg);color:var(--ok);border-color:#b7d9c2}
    .who.bafra{background:var(--warn-bg);color:var(--warn);border-color:#f0d9b5}
    .who.ippc{background:#f3edfb;color:#5b3a99;border-color:#dbcdf2}
    .who.devops{background:var(--bad-bg);color:var(--bad);border-color:#e2c2bf}
    a{color:var(--accent)} a:hover{text-decoration:underline}
    .links{margin-top:14px;font-size:14px;color:var(--muted)}
    .glossary{display:grid;grid-template-columns:180px 1fr;gap:8px 18px;font-size:14px}
    .glossary dt{font-weight:600;color:var(--accent)}
    .glossary dd{margin:0;color:var(--ink)}
    @media(max-width:720px){.wrap{padding:18px 14px 40px}.hero,.card{border-radius:14px;padding:18px}.glossary{grid-template-columns:1fr;gap:4px}}
  </style>
</head>
<body>
  <div class="wrap">

    <section class="hero">
      <p class="eyebrow">Bhutan • IPPC ePhyto Hub • Implementation plan (in eR terms)</p>
      <h1>How Bhutan's certificates reach the Hub, in eR vocabulary</h1>
      <p class="lede">
        We add one new <strong>BotRole</strong> at the end of the certificate journey, containing one new <strong>Bot</strong> (data type).
        The Bot calls a new <strong>external service</strong> registered in Mule, which is backed by a small Python bridge program
        sitting next to the Bhutan eR instance. The bridge handles the IPPC Hub's secure connection and XML generation
        (too heavy for a Bot to do directly).
      </p>
      <p class="links">
        Companion docs:
        <a href="https://share.eregistrations.dev/d/XH50eSFgFG">decisions for BAFRA</a>
        &middot;
        <a href="https://share.eregistrations.dev/d/dRySn4JoyO">adversarial review with citations</a>
      </p>
    </section>

    <section class="card">
      <h2>The sequence inside the eR service</h2>
      <div class="diagram">
        <pre class="mermaid">
flowchart TD
  Insp["Human role:<br/>Inspector approves"]:::existing
  Gen["BotRole:<br/>Generate certificate<br/>(existing)"]:::existing
  Sub["BotRole:<br/>Submit to IPPC Hub"]:::new
  GDB[(GDB-EXPORT)]:::existing
  Hub["IPPC ePhyto Hub"]:::external

  Insp --> Gen
  Gen -. writes certificate data .-> GDB
  Gen --"new: #4"--> Sub
  Sub --"powered by #1 + #2 + #3"--> Hub
  Hub -."saves into #5".-> Insp

  classDef existing fill:#eef5fc,stroke:#0b5cab,color:#122033
  classDef new fill:#e8f5ee,stroke:#0f7a3a,color:#122033,stroke-width:2px
  classDef external fill:#f3edfb,stroke:#5b3a99,color:#122033
        </pre>
      </div>
      <p style="margin-top:14px;font-size:14px;color:var(--muted)">
        Green = the new BotRole we add. Numbers on the arrows are the eR objects (from the table that follows): <strong>#4</strong> is created when the new BotRole is added; <strong>#1, #2, #3</strong> are what powers its call to the Hub; <strong>#5</strong> are the new form fields the tracking ID lands in.
      </p>

      <h3 style="font-family:Georgia,serif;font-size:18px;margin:24px 0 8px;color:var(--ink)">Step 1 &mdash; Inspector approves <span style="font-size:13px;color:var(--muted);font-weight:normal;letter-spacing:0;text-transform:none">(existing &mdash; nothing new from us)</span></h3>
      <p style="font-size:15px;color:var(--muted);margin:0">The inspector's existing human role &mdash; no changes.</p>

      <h3 style="font-family:Georgia,serif;font-size:18px;margin:24px 0 8px;color:var(--ink)">Step 2 &mdash; Generate certificate <span style="font-size:13px;color:var(--muted);font-weight:normal;letter-spacing:0;text-transform:none">(existing &mdash; nothing new from us)</span></h3>
      <p style="font-size:15px;color:var(--muted);margin:0">The existing BotRole. Its existing data Bot (<em>PHYTOSANITARY DB create</em>) writes the certificate to GDB-EXPORT via the GDB-generated external service.</p>

      <h3 style="font-family:Georgia,serif;font-size:18px;margin:24px 0 8px;color:var(--accent)">Step 3 &mdash; Submit to IPPC Hub <span style="font-size:13px;color:var(--ok);font-weight:normal;letter-spacing:0;text-transform:none">(NEW &mdash; built from four eR objects below)</span></h3>
      <p style="margin:0 0 10px;font-size:15px">From the operator's point of view, the certificate lands at the Hub. To make that happen, we build four eR objects (each one is required for the next):</p>
      <table>
        <thead><tr><th>#</th><th>eR object</th><th>What it is, in eR terms</th><th>How we create it</th></tr></thead>
        <tbody>
          <tr><td>1</td><td><strong>Bridge program</strong></td><td>Outside BPA. A small Python web service that exposes one OpenAPI operation &mdash; <code>submit-to-ippc-hub</code> &mdash; taking a file ID and returning the Hub's tracking ID. Holds Bhutan's IPPC X.509 certificate. Does the SOAP + XML work the Hub requires.</td><td>We write the code in <code>3 - Projects/ephyto-hub-bridge/</code>. Deploy next to Bhutan eR.</td></tr>
          <tr><td>2</td><td><strong>External service entry in Mule</strong></td><td>One new line in Mule's operation catalog so BPA Bots can call <code>submit-to-ippc-hub</code>. Same kind of entry as <code>GDB.GDB-EXPORT(5.5)-create</code>, except the OpenAPI source is our bridge instead of GDB.</td><td>Add the bridge's OpenAPI URL to Mule's environment configuration on the Bhutan instance and restart Mule. No MCP tool &mdash; see the prompt to the UNCTAD colleague further down.</td></tr>
          <tr><td>3</td><td><strong>Bot &mdash; "IPPC HUB submit"</strong></td><td>Data Bot, <code>bot_service_id = submit-to-ippc-hub</code>. Input mappings carry the file ID into the bridge. Output mappings save the Hub tracking ID + status back into form fields (those fields are object #5 below).</td><td>BPA MCP: <code>bot_create</code>, <code>bot_update</code>, <code>bot_input_mapping_save_all</code>, <code>bot_output_mapping_save_all</code>.</td></tr>
          <tr><td>4</td><td><strong>BotRole &mdash; "Submit to IPPC Hub"</strong></td><td>This step itself: the new automated workflow step, placed right after "Generate certificate". Contains the Bot above as its single action.</td><td>BPA MCP: <code>role_create</code>, <code>roleinstitution_create</code>, <code>roleregistration_create</code>, <code>botrolebots_save</code>.</td></tr>
        </tbody>
      </table>

      <h3 style="font-family:Georgia,serif;font-size:18px;margin:24px 0 8px;color:var(--accent)">Step 4 &mdash; Tracking ID saved into the eR file <span style="font-size:13px;color:var(--ok);font-weight:normal;letter-spacing:0;text-transform:none">(NEW &mdash; one more eR object)</span></h3>
      <p style="margin:0 0 10px;font-size:15px">The Bot's output mappings (sub-part of object #3) write the Hub's response into form fields. Those fields don't exist yet, so we add them:</p>
      <table>
        <thead><tr><th>#</th><th>eR object</th><th>What it is, in eR terms</th><th>How we create it</th></tr></thead>
        <tbody>
          <tr><td>5</td><td><strong>Form fields for the Hub response</strong></td><td>Two or three small read-only fields in the existing certificate form to hold the tracking ID, the submission timestamp, and the Hub status &mdash; so officers can see "Submitted to Hub: TRACK-XYZ" the next time they open the file.</td><td>BPA MCP: <code>form_component_add</code>.</td></tr>
        </tbody>
      </table>
    </section>

    <section class="card">
      <h2>The plan, in eR-correct execution order</h2>

      <div class="step">
        <strong>Step 0 &mdash; ISO-2 codes on the importing-country classification <span class="who us">us</span></strong>
        Walk through the existing "Importing country" classification entries and tag each with the ISO 3166-1 alpha-2 code. BPA MCP: <code>classification_apply_country_codes</code> (or per-entry <code>classification_entry_set_*</code>). Done inside BPA, no Mule involvement. ~30-60 min.
      </div>

      <div class="step">
        <strong>Step 1 &mdash; Set up the bridge program <span class="who us">us</span></strong>
        Create the project folder under <code>3 - Projects/ephyto-hub-bridge/</code>. Pick the Python tools. Get a minimal web service running locally with one test operation. ~30 min.
      </div>

      <div class="step">
        <strong>Step 2 &mdash; Read from GDB-EXPORT <span class="who us">us</span></strong>
        Inside the bridge, add the part that fetches a structured certificate record from GDB-EXPORT given a file ID. Test against Bhutan staging. ~1 hour.
      </div>

      <div class="step">
        <strong>Step 3 &mdash; Build the certificate XML <span class="who us">us</span></strong>
        Inside the bridge, add the part that turns a GDB-EXPORT record into the Hub's UN/CEFACT certificate format. Hardcode the constants (851, 70, ZZZ, statement 1). Test against IPPC sample certificates. ~2-3 hours.
      </div>

      <div class="step">
        <strong>Step 4 &mdash; Publish the bridge's OpenAPI spec <span class="who us">us</span></strong>
        The bridge serves its own OpenAPI spec at a well-known URL (e.g. <code>/openapi.json</code>). Operation name: <code>submit-to-ippc-hub</code>. Input: <code>fileId</code>. Output: <code>hubTxId</code>, <code>hubStatus</code>, <code>submittedAt</code>. ~30 min.
      </div>

      <div class="step">
        <strong>Step 5 &mdash; Register the bridge as a Mule external service <span class="who us">us</span></strong>
        Add the bridge's OpenAPI URL to Mule's environment configuration on the Bhutan instance (likely the <code>BOT_SWAGGER_URLS</code> env var or equivalent) and restart Mule. Confirm via <code>muleservice_list</code> that <code>submit-to-ippc-hub</code> appears. No MCP tool for this step &mdash; done either directly on the Mule container, or via a short request to the UNCTAD colleague who maintains the Bhutan instance (see prompt below). ~30 min.
      </div>

      <div class="step">
        <strong>Step 6 &mdash; Wait for Bhutan's IPPC X.509 certificate <span class="who ippc">IPPC</span> <span class="who bafra">BAFRA</span></strong>
        IPPC issues Bhutan's X.509 certificate once BAFRA completes Hub registration. Does not block Steps 0-5 or 7-11 (all can proceed in parallel); only blocks live Hub testing.
      </div>

      <div class="step">
        <strong>Step 7 &mdash; Install the IPPC certificate on the bridge <span class="who us">us</span></strong>
        Place Bhutan's X.509 certificate + private key on the Bhutan eR server. Configure the bridge to use them for the secure connection to the Hub. ~30 min.
      </div>

      <div class="step">
        <strong>Step 8 &mdash; Test the bridge against the Hub UAT <span class="who us">us</span></strong>
        IPPC provides a UAT (test) Hub address. Submit synthetic certificates from the bridge directly. Confirm Hub accepts and at least one connected destination country receives them. ~1-2 hours.
      </div>

      <div class="step">
        <strong>Step 9 &mdash; Create the new Bot in BPA <span class="who us">us</span></strong>
        BPA MCP: <code>bot_create</code> (data Bot, category "other" or "create", name "IPPC HUB submit") → <code>bot_update</code> with <code>bot_service_id="submit-to-ippc-hub"</code> → <code>bot_input_mapping_save_all</code> (fileId) → <code>bot_output_mapping_save_all</code> (hubTxId, hubStatus, submittedAt). ~30 min.
      </div>

      <div class="step">
        <strong>Step 10 &mdash; Create the new BotRole and wire the Bot <span class="who us">us</span></strong>
        BPA MCP: <code>role_create</code> (BotRole "Submit to IPPC Hub") → <code>roleinstitution_create</code> + <code>roleregistration_create</code> (copy from the existing PHYTOSANITARY DB create role) → <code>botrolebots_save</code> to wire the new Bot as its single action. Place it after "Generate certificate" in the workflow. ~30 min.
      </div>

      <div class="step">
        <strong>Step 11 &mdash; Add the response fields + publish <span class="who us">us</span></strong>
        BPA MCP: <code>form_component_add</code> for the three read-only Hub-response fields. Then <code>service_publish</code>. Mule picks up the new flow on its next config refresh (instant or restart-bound depending on Mule version). ~30 min.
      </div>

      <div class="step">
        <strong>Step 12 &mdash; End-to-end test on Bhutan staging <span class="who us">us</span></strong>
        Fill a test file, approve as inspector, watch the new BotRole fire, watch Mule call the bridge, watch the bridge submit to Hub UAT, watch the tracking ID appear in the form fields. ~1 hour.
      </div>

      <div class="step">
        <strong>Step 13 &mdash; Go live <span class="who us">us</span> <span class="who bafra">BAFRA</span></strong>
        Switch the bridge from Hub UAT to Hub production. BAFRA approves. Move the bridge, the Mule external-service entry, the new Bot, the new BotRole, the new form fields to Bhutan production. Monitor first submissions. ~1 hour plus monitoring.
      </div>
    </section>

    <section class="card">
      <h2>What we need from others</h2>
      <table>
        <thead><tr><th>From</th><th>What</th><th>Blocks</th></tr></thead>
        <tbody>
          <tr><td><span class="who bafra">BAFRA</span></td><td>Signatory decision (Inspector or OIC)</td><td>Step 9 (so the Bot's input mapping pulls the right field)</td></tr>
          <tr><td><span class="who bafra">BAFRA</span></td><td>(Light) confirm our ISO-2 tagging of the importing-country list before go-live</td><td>Step 13</td></tr>
          <tr><td><span class="who bafra">BAFRA</span></td><td>Complete IPPC Hub registration, receive the X.509 certificate</td><td>Steps 7-8</td></tr>
          <tr><td><span class="who ippc">IPPC</span></td><td>X.509 certificate for Bhutan + UAT and production Hub addresses</td><td>Steps 7-8 and 13</td></tr>
          <tr><td><span class="who us">UNCTAD colleague (Bhutan instance maintainer)</span></td><td>The exact env var name + restart procedure for the Bhutan Mule, OR direct access to make the change ourselves. See the prompt below.</td><td>Step 5 (then unblocks Steps 11-13)</td></tr>
        </tbody>
      </table>
    </section>

    <section class="card">
      <h2>Prompt to send to the UNCTAD colleague who maintains the Bhutan instance</h2>
      <p>Copy-paste-ready. Sent once early so Step 5 isn't blocked when the bridge is ready.</p>
      <blockquote style="margin:8px 0;padding:14px 18px;background:#fafbfd;border-left:3px solid var(--accent);border-radius:0 8px 8px 0;font-family:'Segoe UI',Arial,sans-serif;font-style:normal;color:var(--ink);font-size:15px">
        <p style="margin:0 0 10px">Hi &mdash; working on the Bhutan ePhyto Hub integration. I need to register one new external service in Mule on the <strong>Bhutan staging</strong> instance (eventually production too) so a BPA Bot can call it.</p>
        <p style="margin:0 0 10px">Three short answers needed:</p>
        <ol style="margin:0 0 10px;padding-left:22px">
          <li><strong>Where do I add a new OpenAPI/Swagger URL</strong> for Mule to pick up? Specifically, is it the <code>BOT_SWAGGER_URLS</code> env var on the Mule container, a sibling env var, or a config file? Please share the exact name and the current value so I can append correctly.</li>
          <li><strong>How do I reload Mule</strong> after the change &mdash; full container restart, or a hot-reload endpoint?</li>
          <li><strong>Preferred workflow:</strong> would you rather (a) grant me access to make the change myself, or (b) have me send you the OpenAPI URL and you make it?</li>
        </ol>
        <p style="margin:0">Context: the new service is a small Python bridge that submits phytosanitary certificates to the IPPC ePhyto Hub. OpenAPI spec will be at <code>https://&lt;bridge-host&gt;/openapi.json</code>, exposing one operation <code>submit-to-ippc-hub</code>. Bridge will be deployed next to Bhutan eR for production &mdash; on a UNCTAD dev server while we build. No urgency on the change itself; I just need the procedure so I can plan the integration test. Thanks!</p>
      </blockquote>
    </section>

    <section class="card">
      <h2>What we can start today</h2>
      <p>
        <strong>Steps 0, 1, 2, 3, 4 are all unblocked.</strong> We can have ISO-2 codes tagged, a working bridge that
        reads GDB-EXPORT and produces valid Hub-format XML, and its OpenAPI spec published, all before IPPC issues
        the X.509 cert. Step 5 (Mule registration) needs us to ask the Bhutan instance maintainer where to plug in the
        OpenAPI URL — can be asked in parallel.
      </p>
    </section>

    <section class="card">
      <h2>eR vocabulary glossary (for non-eR readers)</h2>
      <dl class="glossary">
        <dt>Applicant role</dt><dd>A Part B workflow step performed by the citizen filling the form. Data model: <code>role_type=UserRole</code> with <code>assigned_to=applicant</code> (or related applicant variants).</dd>
        <dt>Human role / officer role</dt><dd>A Part A workflow step performed by institution staff (inspector, OIC). Data model: <code>role_type=UserRole</code> with <code>assigned_to=processing</code> or <code>revision</code>. The same JSON type as the applicant role, but the designer vocabulary distinguishes the two by the journey they belong to. <strong>Never write "UserRole" in prose</strong> &mdash; it's a technical key.</dd>
        <dt>BotRole</dt><dd>An automated workflow step. Contains one or more Bots. No <code>assigned_to</code>.</dd>
        <dt>Bot</dt><dd>The unit of automated work inside a BotRole. Data Bot writes/reads data; Document Bot generates a PDF; Message Bot sends an email; etc.</dd>
        <dt>External service</dt><dd>A registered API operation that a Bot can call. Identified by a <code>bot_service_id</code>. Two kinds: GDB-generated (e.g. <code>GDB.GDB-EXPORT(5.5)-create</code>) or non-GDB (registered via OpenAPI to Mule).</dd>
        <dt>Mule</dt><dd>The integration runtime sitting between BPA Bots and external services. Reads each Bot's input mappings, calls the external service, applies output mappings.</dd>
        <dt>Classification</dt><dd>A code-list catalog (countries, ports, units…). Entries can carry secondary codes — e.g. the ISO-2 code we'll attach to each country in the importing-country classification.</dd>
      </dl>
    </section>

    <!-- ai-data
    service_id: ca6a7213-4113-4033-91ab-b9e4f650cf1f
    registration_id: 5c170e35-0b8c-4a9e-88cb-a8c7ba9c5521
    gdb_export_bot_id: 287cbbd3-3744-4f6f-ab5a-1eaf1b4fa0c4
    plan_date: 2026-05-22
    plan_version: 2 (eR vocabulary)
    new_bot_service_id_proposed: submit-to-ippc-hub
    new_botrole_name_proposed: Submit to IPPC Hub
    new_bot_name_proposed: IPPC HUB submit
    companion_docs:
      decisions_v2: https://share.eregistrations.dev/d/XH50eSFgFG
      adversarial_review: https://share.eregistrations.dev/d/dRySn4JoyO
    -->
  </div>
</body>
</html>