.nornir/assets/holger-marriage.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 600" 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>
<linearGradient id="slot" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#123448"/><stop offset="1" stop-color="#0a2032"/>
</linearGradient>
<marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0 0 L10 5 L0 10 z" fill="#6fd3f5"/>
</marker>
</defs>
<rect x="0" y="0" width="1180" height="600" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1"><line x1="0" y1="78" x2="1180" y2="78"/><line x1="0" y1="552" x2="1180" y2="552"/></g>
<g fill="#16415c"><circle cx="40" cy="40" r="2"/><circle cx="1140" cy="40" r="2"/><circle cx="40" cy="572" r="2"/><circle cx="1140" cy="572" r="2"/></g>
<text x="40" y="40" fill="#eaf6ff" font-size="22" font-weight="700">the holger marriage</text>
<text x="40" y="62" fill="#9fc9e0" font-size="15"><tspan fill="#bfe6ff" font-weight="700">holger-server-lib</tspan> linked IN-PROCESS (feature <tspan font-family="'DejaVu Sans Mono', monospace">embed-holger</tspan>, on by default) — no subprocess to orchestrate</text>
<g font-size="12.5">
<line x1="880" y1="58" x2="920" y2="58" stroke="#6fd3f5" stroke-width="3" marker-end="url(#arr)"/>
<text x="928" y="62" fill="#cfe6f5">in-process call / serve</text>
</g>
<!-- nornir process -->
<rect x="36" y="108" width="262" height="380" rx="12" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="167" y="136" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">the nornir process</text>
<text x="167" y="155" fill="#9fc9e0" font-size="10.5" text-anchor="middle">one binary, no orchestration</text>
<rect x="56" y="174" width="222" height="40" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="167" y="191" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">nornir cache up</text>
<text x="167" y="205" fill="#9fc9e0" font-size="9" text-anchor="middle">point cargo at /cache for offline builds</text>
<rect x="56" y="222" width="222" height="40" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="167" y="239" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">release stage --execute</text>
<text x="167" y="253" fill="#9fc9e0" font-size="9" text-anchor="middle">the rehearsal publishes into /sparring</text>
<rect x="56" y="270" width="222" height="40" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="167" y="287" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">nornir-server (NORNIR_HOLGER=1)</text>
<text x="167" y="301" fill="#9fc9e0" font-size="9" text-anchor="middle">daemon hosts it at boot</text>
<text x="167" y="334" fill="#86b3cc" font-size="10" text-anchor="middle">EmbeddedHolger::start writes the dev-pair</text>
<text x="167" y="348" fill="#86b3cc" font-size="10" text-anchor="middle">RON, wires routes, start()s listeners on an</text>
<text x="167" y="362" fill="#86b3cc" font-size="10" text-anchor="middle">owned tokio runtime; drop = stop</text>
<text x="167" y="386" fill="#a9d8ee" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">src/holger_embed.rs</text>
<text x="167" y="404" fill="#ffcf6f" font-size="9.5" text-anchor="middle">--no-default-features → lean client;</text>
<text x="167" y="418" fill="#ffcf6f" font-size="9.5" text-anchor="middle">same call sites spawn a subprocess instead</text>
<text x="167" y="446" fill="#7fa8c4" font-size="9.5" text-anchor="middle">HTTP :18464 · gRPC :18465</text>
<text x="167" y="464" fill="#7fa8c4" font-size="9.5" text-anchor="middle">📦 viz reads via holger's functional API</text>
<rect x="298" y="180" width="6" height="8" fill="#6fd3f5"/>
<rect x="298" y="370" width="6" height="8" fill="#6fd3f5"/>
<!-- two gateways -->
<line x1="304" y1="184" x2="430" y2="220" stroke="#6fd3f5" stroke-width="3" marker-end="url(#arr)"/>
<line x1="304" y1="374" x2="430" y2="392" stroke="#6fd3f5" stroke-width="3" marker-end="url(#arr)"/>
<!-- /cache -->
<rect x="436" y="180" width="300" height="146" rx="11" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="586" y="208" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">/cache</text>
<text x="586" y="227" fill="#9fc9e0" font-size="10.5" text-anchor="middle">transparent crates.io mirror / proxy</text>
<rect x="458" y="240" width="256" height="34" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="586" y="261" fill="#bfe6ff" font-size="10" text-anchor="middle">miss → fetch upstream once → local znippy archive</text>
<text x="586" y="296" fill="#86b3cc" font-size="10" text-anchor="middle">point [source.crates-io] here; next build is offline-fast</text>
<text x="586" y="312" fill="#7fa8c4" font-size="9.5" text-anchor="middle">used by: cache up · builds</text>
<!-- /sparring -->
<rect x="436" y="342" width="300" height="146" rx="11" fill="url(#rail)" stroke="#7CFFB2" stroke-width="2.5"/>
<text x="586" y="370" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">/sparring</text>
<text x="586" y="389" fill="#7CFFB2" font-size="10.5" text-anchor="middle">writable fake crates.io (rehearsal registry)</text>
<rect x="458" y="402" width="256" height="34" rx="5" fill="url(#slot)" stroke="#7CFFB2" stroke-width="1.4"/>
<text x="586" y="423" fill="#bfe6ff" font-size="10" text-anchor="middle">source-REPLACES crates.io; you publish your own crates IN</text>
<text x="586" y="458" fill="#86b3cc" font-size="10" text-anchor="middle">also mirrors upstream → a published name must be unique</text>
<text x="586" y="474" fill="#7fa8c4" font-size="9.5" text-anchor="middle">used by: the release rehearsal</text>
<!-- upstream crates.io -->
<line x1="736" y1="253" x2="820" y2="320" stroke="#7fb0cc" stroke-width="2.5" stroke-dasharray="6 4" fill="none" marker-end="url(#arr)"/>
<line x1="736" y1="419" x2="820" y2="350" stroke="#7fb0cc" stroke-width="2.5" stroke-dasharray="6 4" fill="none" marker-end="url(#arr)"/>
<rect x="826" y="296" width="300" height="80" rx="11" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2"/>
<text x="976" y="324" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">crates.io (upstream)</text>
<text x="976" y="344" fill="#9fc9e0" font-size="10.5" text-anchor="middle">both gateways fall through to the real index</text>
<text x="976" y="362" fill="#7fa8c4" font-size="10" text-anchor="middle">misses fetched once, then cached locally</text>
<!-- ground -->
<rect x="36" y="500" width="1090" height="40" rx="10" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<text x="60" y="525" fill="#bcd9ec" font-size="11.5">one HTTP port serves both gateways · three consumers share the embedded pair: <tspan font-family="'DejaVu Sans Mono', monospace" fill="#bfe6ff">cache up</tspan> · the release rehearsal · the <tspan font-family="'DejaVu Sans Mono', monospace" fill="#bfe6ff">nornir-server</tspan> daemon</text>
</svg>