.nornir/assets/install-tree.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 860 360" font-family="-apple-system,Segoe UI,Roboto,sans-serif" font-size="13">
<defs>
<marker id="a" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto">
<path d="M0,0 L7,3 L0,6 Z" fill="#555"/>
</marker>
</defs>
<text x="24" y="28" font-weight="700" font-size="16">The install tree — one ServiceSpec, many init systems</text>
<!-- ComponentSpec -->
<rect x="24" y="52" width="180" height="52" rx="8" fill="#eef3fb" stroke="#2b5fb3" stroke-width="1.5"/>
<text x="114" y="74" text-anchor="middle" font-weight="600">ComponentSpec</text>
<text x="114" y="92" text-anchor="middle" fill="#555" font-size="11">the airgap install unit</text>
<!-- ServiceSpec -->
<rect x="24" y="132" width="180" height="60" rx="8" fill="#eef3fb" stroke="#2b5fb3" stroke-width="1.5"/>
<text x="114" y="156" text-anchor="middle" font-weight="600">ServiceSpec</text>
<text x="114" y="174" text-anchor="middle" fill="#555" font-size="11">exec·user·scope·env</text>
<text x="114" y="188" text-anchor="middle" fill="#555" font-size="11">after·needs·restart·sockets</text>
<path d="M114,104 L114,132" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<text x="124" y="122" fill="#888" font-size="10">to_service_spec(layout, backend)</text>
<!-- ServiceRenderer trait -->
<rect x="290" y="132" width="180" height="60" rx="8" fill="#eefaf0" stroke="#2f8f4e" stroke-width="1.5"/>
<text x="380" y="156" text-anchor="middle" font-weight="600">ServiceRenderer</text>
<text x="380" y="174" text-anchor="middle" fill="#555" font-size="11">render(&spec)</text>
<text x="380" y="188" text-anchor="middle" fill="#555" font-size="11">renderer_for(b) → Option</text>
<path d="M204,162 L290,162" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<!-- leaves -->
<rect x="540" y="48" width="300" height="46" rx="6" fill="#eefaf0" stroke="#2f8f4e" stroke-width="1.3"/>
<text x="690" y="72" text-anchor="middle" font-weight="600" font-size="11">systemd-system · systemd-user · OpenRC · SysV</text>
<text x="690" y="87" text-anchor="middle" font-weight="600" font-size="11">runit · s6-rc · dinit · k8s · OCI · quadlet · windows</text>
<text x="547" y="62" fill="#2f8f4e" font-size="10">implemented (11 of 11 — complete)</text>
<rect x="540" y="100" width="300" height="40" rx="6" fill="#eefaf0" stroke="#2f8f4e" stroke-width="1.3"/>
<text x="690" y="125" text-anchor="middle" fill="#2f8f4e" font-weight="600" font-size="11">✓ full coverage</text>
<text x="547" y="114" fill="#2f8f4e" font-size="10">every backend renders — renderer_for never None</text>
<path d="M470,150 C505,120 510,90 540,78" fill="none" stroke="#555" stroke-width="1.3" marker-end="url(#a)"/>
<path d="M470,168 C505,150 510,130 540,120" fill="none" stroke="#2f8f4e" stroke-width="1.3" marker-end="url(#a)"/>
<!-- RenderedService -->
<rect x="290" y="232" width="250" height="66" rx="8" fill="#fdf2ec" stroke="#c26a2b" stroke-width="1.5"/>
<text x="415" y="256" text-anchor="middle" font-weight="600">RenderedService</text>
<text x="415" y="274" text-anchor="middle" fill="#555" font-size="11">files: Vec<RenderedFile></text>
<text x="415" y="290" text-anchor="middle" fill="#555" font-size="11">verbs (DATA): enable·start·status·stop</text>
<path d="M380,192 L400,232" fill="none" stroke="#555" stroke-width="1.5" marker-end="url(#a)"/>
<!-- apply -->
<rect x="600" y="240" width="200" height="52" rx="8" fill="#f6eefb" stroke="#7a3fb3" stroke-width="1.5"/>
<text x="700" y="262" text-anchor="middle" font-weight="600">install::apply</text>
<text x="700" y="280" text-anchor="middle" fill="#555" font-size="11">runs verbs (systemd → D-Bus)</text>
<path d="M540,266 L600,266" fill="none" stroke="#7a3fb3" stroke-width="1.5" marker-end="url(#a)"/>
<text x="24" y="330" fill="#888" font-size="11">Verbs are DATA, not side effects — the whole tree is unit-testable at zero privilege; one thin driver executes them.</text>
<text x="24" y="348" fill="#888" font-size="11">Lifecycle: install [enable,start] · update [stop,start] · uninstall [stop,disable] — verbs-as-data per InstallOutcome.</text>
</svg>