.nornir/assets/flow_push.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 560" 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>
<marker id="arrd" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto">
<path d="M0 0 L7 3 L0 6 Z" fill="#7fb0cc"/>
</marker>
</defs>
<rect x="0" y="0" width="1180" height="560" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1">
<line x1="0" y1="74" x2="1180" y2="74"/>
<line x1="0" y1="520" x2="1180" y2="520"/>
</g>
<g fill="#16415c">
<circle cx="40" cy="40" r="2"/><circle cx="1140" cy="40" r="2"/>
<circle cx="40" cy="540" r="2"/><circle cx="1140" cy="540" r="2"/>
</g>
<!-- title -->
<text x="40" y="44" fill="#eaf6ff" font-size="22" font-weight="700">Push — an artifact enters holger</text>
<text x="430" y="44" fill="#9fc9e0" font-size="14.5">agent uploads → auth → route by repo name → backend stores → serve from index</text>
<!-- legend -->
<g font-size="12">
<line x1="836" y1="60" x2="872" y2="60" stroke="#6fd3f5" stroke-width="3"/>
<text x="880" y="64" fill="#cfe6f5">request path</text>
<line x1="996" y1="60" x2="1032" y2="60" stroke="#7fb0cc" stroke-width="2.5" stroke-dasharray="5 4"/>
<text x="1040" y="64" fill="#cfe6f5">rejected</text>
</g>
<!-- client -->
<rect x="40" y="222" width="150" height="96" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="115" y="258" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">holger agent</text>
<text x="115" y="278" fill="#9fc9e0" font-size="11.5" text-anchor="middle">put_artifact()</text>
<text x="115" y="296" fill="#86b3cc" font-size="10.5" text-anchor="middle">gRPC / direct call</text>
<!-- auth -->
<rect x="258" y="206" width="178" height="128" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="347" y="236" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">auth gate</text>
<text x="347" y="258" fill="#9fc9e0" font-size="11" text-anchor="middle">validate_request()</text>
<text x="347" y="278" fill="#86b3cc" font-size="10.5" text-anchor="middle">mTLS CN • OIDC bearer</text>
<text x="347" y="296" fill="#86b3cc" font-size="10.5" text-anchor="middle">→ AuthIdentity</text>
<text x="347" y="318" fill="#86b3cc" font-size="10" text-anchor="middle">empty cfg = open access</text>
<!-- router -->
<rect x="504" y="206" width="186" height="128" rx="10" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="597" y="236" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">FastRoutes.lookup</text>
<text x="597" y="258" fill="#9fc9e0" font-size="11" text-anchor="middle">by repository name</text>
<text x="597" y="278" fill="#86b3cc" font-size="10.5" text-anchor="middle">first-byte index → bucket</text>
<text x="597" y="298" fill="#86b3cc" font-size="10.5" text-anchor="middle">O(1) → Arc<dyn Backend></text>
<text x="597" y="320" fill="#86b3cc" font-size="10" text-anchor="middle">writable? else PermissionDenied</text>
<!-- backend -->
<rect x="758" y="206" width="172" height="128" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="844" y="236" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">backend.put()</text>
<text x="844" y="258" fill="#9fc9e0" font-size="11" text-anchor="middle">RepositoryBackendTrait</text>
<text x="844" y="278" fill="#86b3cc" font-size="10.5" text-anchor="middle">id → path layout</text>
<text x="844" y="296" fill="#86b3cc" font-size="10.5" text-anchor="middle">per-ecosystem mapping</text>
<text x="844" y="318" fill="#86b3cc" font-size="10" text-anchor="middle">file-rust writes; znippy = RO</text>
<!-- storage -->
<rect x="998" y="206" width="146" height="128" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="1071" y="236" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">storage</text>
<text x="1071" y="258" fill="#9fc9e0" font-size="11" text-anchor="middle">StorageEndpoint</text>
<text x="1071" y="278" fill="#86b3cc" font-size="10.5" text-anchor="middle">znippy archive</text>
<text x="1071" y="296" fill="#86b3cc" font-size="10.5" text-anchor="middle">or {repo}/{path} tree</text>
<text x="1071" y="316" fill="#86b3cc" font-size="10" text-anchor="middle">blake3 content-addressed</text>
<!-- request arrows -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M190 270 H256" marker-end="url(#arr)"/>
<path d="M436 270 H502" marker-end="url(#arr)"/>
<path d="M690 270 H756" marker-end="url(#arr)"/>
<path d="M930 270 H996" marker-end="url(#arr)"/>
</g>
<!-- rejected (auth) -->
<path d="M347 334 V392 H180 V336" stroke="#7fb0cc" stroke-width="2.5" fill="none" stroke-dasharray="6 4" marker-end="url(#arrd)"/>
<text x="300" y="410" fill="#86b3cc" font-size="11" text-anchor="middle">401 Unauthorized</text>
<!-- index/serve rail -->
<rect x="258" y="450" width="672" height="56" rx="10" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<text x="284" y="478" fill="#dff1ff" font-size="15" font-weight="700">index</text>
<text x="350" y="476" fill="#bcd9ec" font-size="12">archive contents become the registry index on demand —</text>
<text x="350" y="495" fill="#7fa8c4" font-size="10.5" font-family="'DejaVu Sans Mono', monospace">index.yaml · packument · PEP 503 · v3 service index · @v/list … generated by handle_http2_request()</text>
<path d="M844 334 V450" stroke="#6fd3f5" stroke-width="3" fill="none" marker-end="url(#arr)"/>
<text x="900" y="396" fill="#86b3cc" font-size="11">stored → indexable</text>
</svg>