Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

docs/v2/img/setup-fetch.svg

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 560" width="1180" height="560" role="img" aria-label="Setup A — fetch" font-family="'DejaVu Sans','Segoe UI',system-ui,sans-serif">
<style>
  .rule{stroke:#143a52;stroke-width:1}
  .dot{fill:#16415c}
  .title{fill:#eaf6ff;font-size:21px;font-weight:700}
  .sub{fill:#9fc9e0;font-size:12.5px}
  .bandlabel{fill:#7fa8c4;font-size:11px;letter-spacing:.06em}
  .zone{fill:none;stroke:#1d4560;stroke-width:1;stroke-dasharray:3 5}
  .band{fill:#0d2235;stroke:#1d4560;stroke-width:1}
  .card{stroke-width:1.6}
  .card.repo{fill:url(#chip);stroke:#5aa6cf}
  .card.storage{fill:url(#slot);stroke:#4f8fae}
  .card.source{fill:url(#rail);stroke:#c9a86f;stroke-width:2}
  .card.gate{fill:url(#slot);stroke:#e0b453;stroke-width:1.8;stroke-dasharray:6 3}
  .card.console{fill:url(#rail);stroke:#8fb8ff}
  .card.main{fill:url(#chip);stroke:#6fd3f5;stroke-width:2.6}
  .card.downstream{fill:url(#rail);stroke:#8ef0b4;stroke-width:2.2}
  .card.consumer{fill:url(#slot);stroke:#7fb0cc;stroke-dasharray:4 4}
  .card.step{fill:url(#chip);stroke:#7fb0cc}
  .card.held{fill:url(#slot);stroke:#e0b453;stroke-width:2}
  .card.refused{fill:url(#slot);stroke:#f08c8c;stroke-width:2}
  .card.intel{fill:url(#rail);stroke:#d9a0ff;stroke-width:2}
  .card.apps{fill:url(#chip);stroke:#ffd166;stroke-width:2.2}
  .name{fill:#eaf6ff;font-size:14.5px;font-weight:700}
  .kindword{fill:#6f9fbb;font-size:9px;letter-spacing:.11em}
  .detail{fill:#9fc9e0;font-size:10.5px;font-family:'DejaVu Sans Mono',ui-monospace,SFMono-Regular,Menlo,monospace}
  .rowlabel{fill:#86b3cc;font-size:10.5px}
  .factvalue{fill:#bfe6ff;font-size:10.5px;font-family:'DejaVu Sans Mono',ui-monospace,SFMono-Regular,Menlo,monospace}
  .edge{fill:none;stroke:#7fb0cc;stroke-width:1.6}
  .edge.promote{stroke:#6fd3f5;stroke-width:3}
  .edge.feeds{stroke:#c9a86f;stroke-width:2.4}
  .edge.syncs{stroke:#8ef0b4;stroke-width:3}
  .edge.ingests{stroke:#4f8fae;stroke-width:1.6;stroke-dasharray:8 3}
  .edge.serves{stroke:#4f8fae;stroke-width:1.6}
  .edge.consoleedge{stroke:#8fb8ff;stroke-width:1.6}
  .edge.oneway{stroke:#e0b453;stroke-width:3}
  .edge.carried{stroke:#c9a86f;stroke-width:2;stroke-dasharray:6 4}
  .edge.intel{stroke:#d9a0ff;stroke-width:2.2}
  .edge.graph{stroke:#ffd166;stroke-width:2.2}
  .edge.tells{stroke:#f08c8c;stroke-width:2;stroke-dasharray:2 4}
  .edge.held{stroke:#e0b453;stroke-width:2;stroke-dasharray:4 4}
  .edge.refuses{stroke:#f08c8c;stroke-width:2.2}
  .edgelabel{fill:#cfe6f5;font-size:10px}
  .head.promote{fill:#6fd3f5}
  .head.feeds,.head.carried{fill:#c9a86f}
  .head.syncs{fill:#8ef0b4}
  .head.ingests,.head.serves{fill:#4f8fae}
  .head.consoleedge{fill:#8fb8ff}
  .head.oneway,.head.held{fill:#e0b453}
  .head.intel{fill:#d9a0ff}
  .head.graph{fill:#ffd166}
  .head.tells,.head.refuses{fill:#f08c8c}
  .legendtext{fill:#cfe6f5;font-size:11px}
  .pill{fill:#0b1c2e;stroke:#1d4560;stroke-width:1}
  .lamp{stroke:#06111d;stroke-width:1.5}
  .lamp.red{fill:#ff5c5c}
  .lamp.yellow{fill:#ffd166}
  .lamp.none{fill:#8ef0b4}
  .lamp.unknown{fill:#6f9fbb}
  .note{fill:#9fc9e0;font-size:11px}
</style>
<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="head-promote" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head promote" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-feeds" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head feeds" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-syncs" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head syncs" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-ingests" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head ingests" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-serves" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head serves" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-consoleedge" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head consoleedge" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-oneway" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head oneway" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-carried" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head carried" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-intel" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head intel" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-graph" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head graph" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-tells" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head tells" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-held" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head held" d="M0 0 L8 4 L0 8 z"/></marker>
<marker id="head-refuses" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path class="head refuses" d="M0 0 L8 4 L0 8 z"/></marker>
</defs>
<rect x="0" y="0" width="1180" height="560" fill="url(#board)"/>
<line class="rule" x1="0" y1="92" x2="1180" y2="92"/>
<circle class="dot" cx="12" cy="12" r="2"/>
<circle class="dot" cx="1168" cy="12" r="2"/>
<circle class="dot" cx="12" cy="548" r="2"/>
<circle class="dot" cx="1168" cy="548" r="2"/>
<text class="title" x="28" y="36">Setup A — fetch</text>
<text class="sub" x="28" y="56">the Holger server checks and approves; the downstream fetches signed bundles, or imports them from a USB stick</text>
<path class="edge feeds" d="M28.0 76 L58.0 76" marker-end="url(#head-feeds)"/>
<text class="legendtext" x="66.0" y="80">pulls from a source</text>
<path class="edge promote" d="M196.1 76 L226.1 76" marker-end="url(#head-promote)"/>
<text class="legendtext" x="234.1" y="80">promotes (intake step)</text>
<path class="edge syncs" d="M381.9 76 L411.9 76" marker-end="url(#head-syncs)"/>
<text class="legendtext" x="419.9" y="80">fetch: signed bundles</text>
<path class="edge ingests" d="M561.8 76 L591.8 76" marker-end="url(#head-ingests)"/>
<text class="legendtext" x="599.8" y="80">export / import</text>
<path class="edge serves" d="M706.3 76 L736.3 76" marker-end="url(#head-serves)"/>
<text class="legendtext" x="744.3" y="80">serves</text>
<path class="edge consoleedge" d="M797.7 76 L827.7 76" marker-end="url(#head-consoleedge)"/>
<text class="legendtext" x="835.7" y="80">console (gRPC)</text>
<rect class="zone" x="28.0" y="112.0" width="500.0" height="420.0" rx="14"/>
<text class="bandlabel" x="42.0" y="132.0">INTERNET · holger (server) + holger-ui</text>
<rect class="zone" x="760.0" y="112.0" width="392.0" height="420.0" rx="14"/>
<text class="bandlabel" x="774.0" y="132.0">ON-PREM · holger-downstream</text>
<path class="edge feeds" data-edge="sources-&gt;incoming" d="M238.0 181.0 C278.0 181.0 278.0 168.0 318.0 168.0" marker-end="url(#head-feeds)"/>
<path class="edge promote" data-edge="incoming-&gt;quarantine" d="M413.0 194.0 C413.0 224.0 413.0 192.0 413.0 222.0" marker-end="url(#head-promote)"/>
<path class="edge promote" data-edge="quarantine-&gt;approved" d="M413.0 274.0 C413.0 304.0 413.0 272.0 413.0 302.0" marker-end="url(#head-promote)"/>
<path class="edge promote" data-edge="approved-&gt;production" d="M413.0 354.0 C413.0 384.0 413.0 352.0 413.0 382.0" marker-end="url(#head-promote)"/>
<path class="edge consoleedge" data-edge="ui-&gt;approved" d="M238.0 391.0 C278.0 391.0 278.0 328.0 318.0 328.0" marker-end="url(#head-consoleedge)"/>
<path class="edge syncs" data-edge="production-&gt;down" d="M508.0 402.8 C649.0 402.8 649.0 241.2 790.0 241.2" marker-end="url(#head-syncs)"/>
<path class="edge ingests" data-edge="production-&gt;usb" d="M413.0 434.0 L413.0 471.0 L565.0 471.0" marker-end="url(#head-ingests)"/>
<path class="edge ingests" data-edge="usb-&gt;down" d="M735.0 471.0 C765.0 471.0 760.0 291.6 790.0 291.6" marker-end="url(#head-ingests)"/>
<path class="edge serves" data-edge="down-&gt;builds" d="M955.0 314.0 C955.0 363.0 955.0 363.0 955.0 412.0" marker-end="url(#head-serves)"/>
<g data-node="sources" data-kind="source">
<rect class="card source" x="48.0" y="152.0" width="190.0" height="58.0" rx="10"/>
<text class="kindword" x="61.0" y="169.0">SOURCES</text>
<text class="name" x="61.0" y="187.0">PyPI · npm · Maven</text>
<text class="detail" x="61.0" y="201.0">crates.io · OCI · Go · APK</text>
</g>
<g data-node="ui" data-kind="console">
<rect class="card console" x="48.0" y="362.0" width="190.0" height="58.0" rx="10"/>
<text class="kindword" x="61.0" y="379.0">CONSOLE</text>
<text class="name" x="61.0" y="397.0">holger-ui</text>
<text class="detail" x="61.0" y="411.0">approvals · board · audit</text>
</g>
<g data-node="incoming" data-kind="repo">
<rect class="card repo" x="318.0" y="142.0" width="190.0" height="52.0" rx="10"/>
<text class="kindword" x="331.0" y="159.0">REPOSITORY · INGESTED</text>
<text class="name" x="331.0" y="177.0">incoming</text>
</g>
<g data-node="quarantine" data-kind="repo">
<rect class="card repo" x="318.0" y="222.0" width="190.0" height="52.0" rx="10"/>
<text class="kindword" x="331.0" y="239.0">REPOSITORY · SCANNED</text>
<text class="name" x="331.0" y="257.0">quarantine</text>
</g>
<g data-node="approved" data-kind="repo">
<rect class="card repo" x="318.0" y="302.0" width="190.0" height="52.0" rx="10"/>
<text class="kindword" x="331.0" y="319.0">REPOSITORY · APPROVED</text>
<text class="name" x="331.0" y="337.0">approved</text>
</g>
<g data-node="production" data-kind="main">
<rect class="card main" x="318.0" y="382.0" width="190.0" height="52.0" rx="10"/>
<text class="kindword" x="331.0" y="399.0">REPOSITORY · AVAILABLE</text>
<text class="name" x="331.0" y="417.0">production</text>
</g>
<g data-node="usb" data-kind="storage">
<rect class="card storage" x="565.0" y="442.0" width="170.0" height="58.0" rx="10"/>
<text class="kindword" x="578.0" y="459.0">USB STICK</text>
<text class="name" x="578.0" y="477.0">signed bundle</text>
<text class="detail" x="578.0" y="491.0">.holger.znippy</text>
</g>
<g data-node="down" data-kind="downstream">
<rect class="card downstream" x="790.0" y="202.0" width="330.0" height="112.0" rx="10"/>
<text class="kindword" x="803.0" y="219.0">DOWNSTREAM</text>
<text class="name" x="803.0" y="237.0">holger-downstream</text>
<text class="detail" x="803.0" y="251.0">--features downstream,fetch</text>
<text class="rowlabel" x="803.0" y="270.0">dials</text>
<text class="factvalue" x="1107.0" y="270.0" text-anchor="end">its upstream only</text>
<text class="rowlabel" x="803.0" y="286.0">inbox</text>
<text class="factvalue" x="1107.0" y="286.0" text-anchor="end">&lt;data&gt;/bundle.inbox</text>
<text class="rowlabel" x="803.0" y="302.0">checks</text>
<text class="factvalue" x="1107.0" y="302.0" text-anchor="end">signatures · hashes · DSSE</text>
</g>
<g data-node="builds" data-kind="consumer">
<rect class="card consumer" x="790.0" y="412.0" width="330.0" height="58.0" rx="10"/>
<text class="kindword" x="803.0" y="429.0">BUILD SYSTEMS</text>
<text class="name" x="803.0" y="447.0">mvn · cargo · pip/uv</text>
<text class="detail" x="803.0" y="461.0">docker/skopeo · go</text>
</g>
<rect class="pill" x="260.8" y="153.0" width="34.4" height="15" rx="4"/>
<text class="edgelabel" x="278.0" y="164.0" text-anchor="middle">pull</text>
<rect class="pill" x="252.4" y="363.0" width="51.2" height="15" rx="4"/>
<text class="edgelabel" x="278.0" y="374.0" text-anchor="middle">approve</text>
<rect class="pill" x="547.2" y="269.0" width="185.6" height="15" rx="4"/>
<text class="edgelabel" x="640.0" y="280.0" text-anchor="middle">fetched by the downstream: mTLS</text>
<rect class="pill" x="555.6" y="285.0" width="168.8" height="15" rx="4"/>
<text class="edgelabel" x="640.0" y="296.0" text-anchor="middle">or WireGuard udp/51830 + PSK</text>
<rect class="pill" x="377.6" y="481.0" width="84.8" height="15" rx="4"/>
<text class="edgelabel" x="420.0" y="492.0" text-anchor="middle">holger export</text>
<rect class="pill" x="633.6" y="413.0" width="112.8" height="15" rx="4"/>
<text class="edgelabel" x="690.0" y="424.0" text-anchor="middle">import, no network</text>
</svg>