.nornir/assets/consolidation-jera-embed.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 620" font-family="'DejaVu Sans', 'Segoe UI', sans-serif">
<defs>
<linearGradient id="board" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0b1c2e"/>
<stop offset="1" stop-color="#06111d"/>
</linearGradient>
<linearGradient id="chip" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#14384f"/>
<stop offset="1" stop-color="#0e2a3e"/>
</linearGradient>
<linearGradient id="rail" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#173d57"/>
<stop offset="1" stop-color="#0c2438"/>
</linearGradient>
<marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto">
<path d="M0 0 L7 3 L0 6 Z" fill="#6fd3f5"/>
</marker>
</defs>
<rect x="0" y="0" width="1180" height="620" fill="url(#board)"/>
<text x="40" y="46" fill="#bfe6f7" font-size="24" font-weight="700">holger consolidation — jera job ledger + the facett-holger / holger-embed pane</text>
<text x="40" y="72" fill="#6f9bb5" font-size="14">Additive: the durable ledger records real work; the pane is one shared component, hosted natively (no wasm).</text>
<!-- ── Part 1: jera job ledger for promotions ───────────────────────────── -->
<text x="40" y="120" fill="#8fd0ea" font-size="16" font-weight="700">1 · durable job ledger (jera) — every promotion is a tracked job</text>
<rect x="40" y="140" width="210" height="70" rx="10" fill="url(#chip)" stroke="#2b5d7c"/>
<text x="145" y="170" fill="#dff1fb" font-size="15" text-anchor="middle" font-weight="600">gRPC promote</text>
<text x="145" y="190" fill="#8fb6cc" font-size="12" text-anchor="middle">Promotion RPC (server/lib)</text>
<rect x="330" y="140" width="230" height="70" rx="10" fill="url(#rail)" stroke="#2b5d7c"/>
<text x="445" y="168" fill="#dff1fb" font-size="15" text-anchor="middle" font-weight="600">PromotionEngine::seal</text>
<text x="445" y="188" fill="#8fb6cc" font-size="12" text-anchor="middle">blake3 · blob · exclusive ref</text>
<rect x="640" y="140" width="230" height="70" rx="10" fill="url(#chip)" stroke="#3a7fae"/>
<text x="755" y="168" fill="#dff1fb" font-size="15" text-anchor="middle" font-weight="600">jera::jobs::JobStore</text>
<text x="755" y="188" fill="#8fb6cc" font-size="12" text-anchor="middle">running → done | failed</text>
<rect x="950" y="140" width="190" height="70" rx="10" fill="url(#rail)" stroke="#2b5d7c"/>
<text x="1045" y="168" fill="#dff1fb" font-size="15" text-anchor="middle" font-weight="600">jobs.redb</text>
<text x="1045" y="188" fill="#8fb6cc" font-size="12" text-anchor="middle">one durable ledger, listable</text>
<line x1="250" y1="175" x2="326" y2="175" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<line x1="560" y1="175" x2="636" y2="175" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<line x1="870" y1="175" x2="946" y2="175" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<text x="455" y="230" fill="#6f9bb5" font-size="11" text-anchor="middle">seal_inner (unchanged) wrapped by a start()/finish()/fail() job — additive, no ledger ⇒ old behaviour</text>
<!-- ── Part 2: the shared pane + the embed adapter ──────────────────────── -->
<text x="40" y="300" fill="#8fd0ea" font-size="16" font-weight="700">2 · one component, two hosts — facett-holger via the holger-embed adapter (native, no wasm)</text>
<!-- component -->
<rect x="470" y="330" width="240" height="90" rx="12" fill="url(#chip)" stroke="#3a7fae" stroke-width="2"/>
<text x="590" y="362" fill="#dff1fb" font-size="16" text-anchor="middle" font-weight="700">facett-holger</text>
<text x="590" y="384" fill="#9fcbe2" font-size="12" text-anchor="middle">RegistryBrowser : Facet</text>
<text x="590" y="402" fill="#8fb6cc" font-size="11" text-anchor="middle">title · ui · state_json (backend-agnostic)</text>
<!-- adapter -->
<rect x="470" y="470" width="240" height="80" rx="12" fill="url(#rail)" stroke="#2b5d7c"/>
<text x="590" y="500" fill="#dff1fb" font-size="15" text-anchor="middle" font-weight="600">holger-embed</text>
<text x="590" y="522" fill="#8fb6cc" font-size="12" text-anchor="middle">panel(source) → Box<dyn Facet></text>
<text x="590" y="540" fill="#8fb6cc" font-size="11" text-anchor="middle">read_model (in-proc) · Model (thin gRPC) · Fixture</text>
<line x1="590" y1="470" x2="590" y2="424" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<!-- host A: holger's own demo -->
<rect x="120" y="350" width="230" height="70" rx="10" fill="url(#chip)" stroke="#2b5d7c"/>
<text x="235" y="378" fill="#dff1fb" font-size="15" text-anchor="middle" font-weight="600">holger-demo</text>
<text x="235" y="398" fill="#8fb6cc" font-size="12" text-anchor="middle">mounts it native + wasm</text>
<line x1="470" y1="375" x2="352" y2="378" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<!-- host B: nornir Holger tab -->
<rect x="830" y="350" width="230" height="70" rx="10" fill="url(#chip)" stroke="#2b5d7c"/>
<text x="945" y="378" fill="#dff1fb" font-size="15" text-anchor="middle" font-weight="600">nornir — Holger tab</text>
<text x="945" y="398" fill="#8fb6cc" font-size="12" text-anchor="middle">hosts the pane cross-app</text>
<line x1="710" y1="375" x2="828" y2="378" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<!-- data source -->
<rect x="120" y="480" width="290" height="70" rx="10" fill="url(#rail)" stroke="#2b5d7c"/>
<text x="265" y="508" fill="#dff1fb" font-size="14" text-anchor="middle" font-weight="600">holger functional read (in-process)</text>
<text x="265" y="528" fill="#8fb6cc" font-size="11" text-anchor="middle">dev_pair_ron → instantiate_backends → list</text>
<line x1="470" y1="512" x2="412" y2="512" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<rect x="770" y="480" width="290" height="70" rx="10" fill="url(#rail)" stroke="#2b5d7c"/>
<text x="915" y="508" fill="#dff1fb" font-size="14" text-anchor="middle" font-weight="600">thin gRPC read (remote holger)</text>
<text x="915" y="528" fill="#8fb6cc" font-size="11" text-anchor="middle">caller assembles RegistryModel</text>
<line x1="770" y1="512" x2="712" y2="512" stroke="#6fd3f5" stroke-width="2" marker-end="url(#arr)"/>
<text x="590" y="596" fill="#6f9bb5" font-size="11" text-anchor="middle">The guest's ui runs directly in the host's egui frame — full native perf, no serialize boundary, no wasm.</text>
</svg>