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

nordisk/knut

.nornir/assets/knut-systemmap-whats-alive.svg

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1010" 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>
    <linearGradient id="lanefree" x1="0" y1="0" x2="0" y2="1">
      <stop offset="0" stop-color="#0d2436"/>
      <stop offset="1" stop-color="#081a29"/>
    </linearGradient>
    <marker id="flow" markerWidth="9" markerHeight="9" refX="7" refY="4" orient="auto">
      <path d="M0 0 L8 4 L0 8 Z" fill="#6fd3f5"/>
    </marker>
    <marker id="flowg" markerWidth="9" markerHeight="9" refX="7" refY="4" orient="auto">
      <path d="M0 0 L8 4 L0 8 Z" fill="#7CFFB2"/>
    </marker>
    <marker id="flowo" markerWidth="9" markerHeight="9" refX="7" refY="4" orient="auto">
      <path d="M0 0 L8 4 L0 8 Z" fill="#7fb0cc"/>
    </marker>
  </defs>

  <!-- PCB substrate -->
  <rect x="0" y="0" width="1200" height="1010" fill="url(#board)"/>
  <g stroke="#143a52" stroke-width="1">
    <line x1="0" y1="76" x2="1200" y2="76"/>
    <line x1="0" y1="962" x2="1200" y2="962"/>
  </g>
  <g fill="#16415c">
    <circle cx="40" cy="40" r="2"/><circle cx="1160" cy="40" r="2"/>
    <circle cx="40" cy="982" r="2"/><circle cx="1160" cy="982" r="2"/>
  </g>

  <!-- title -->
  <text x="40" y="44" fill="#eaf6ff" font-size="22" font-weight="700">knut &#8212; what has to be alive</text>
  <text x="410" y="44" fill="#9fc9e0" font-size="15">four paths, ranked by how much you must <tspan fill="#bfe6ff" font-weight="700">start first</tspan></text>

  <!-- ===================== LEGEND BAR ===================== -->
  <rect x="36" y="92" width="1128" height="46" rx="10" fill="url(#rail)" stroke="#3c6a86" stroke-width="1.4"/>
  <text x="56" y="121" fill="#dff1ff" font-size="12.5" font-weight="700">legend</text>

  <rect x="128" y="104" width="86" height="22" rx="11" fill="#0a2032" stroke="#7CFFB2" stroke-width="1.4"/>
  <text x="171" y="119" fill="#7CFFB2" font-size="10" font-weight="700" text-anchor="middle">EMBEDDED</text>
  <text x="222" y="119" fill="#bcd9ec" font-size="11">library / file on disk &#8212; <tspan fill="#7CFFB2" font-weight="700">nothing to start</tspan></text>

  <rect x="470" y="104" width="66" height="22" rx="11" fill="#0a2032" stroke="#6fd3f5" stroke-width="1.4"/>
  <text x="503" y="119" fill="#6fd3f5" font-size="10" font-weight="700" text-anchor="middle">PROCESS</text>
  <text x="544" y="119" fill="#bcd9ec" font-size="11">your binary / job &#8212; you run it</text>

  <rect x="768" y="104" width="66" height="22" rx="11" fill="#0a2032" stroke="#ffcf6f" stroke-width="1.4"/>
  <text x="801" y="119" fill="#ffcf6f" font-size="10" font-weight="700" text-anchor="middle">SERVICE</text>
  <text x="842" y="119" fill="#bcd9ec" font-size="11">must be running first</text>

  <rect x="1000" y="104" width="60" height="22" rx="11" fill="#0a2032" stroke="#5f7f93" stroke-width="1.3" stroke-dasharray="3 3"/>
  <text x="1030" y="119" fill="#8fb2c6" font-size="10" font-weight="700" text-anchor="middle">OPT</text>
  <text x="1068" y="119" fill="#bcd9ec" font-size="11">optional</text>

  <!-- ==================================================================== -->
  <!-- LANE A — Iceberg READ, Spark-free.  NOTHING RUNNING.                 -->
  <!-- ==================================================================== -->
  <rect x="36" y="156" width="1128" height="164" rx="12" fill="url(#lanefree)" stroke="#7CFFB2" stroke-width="2"/>
  <text x="54" y="184" fill="#7CFFB2" font-size="15" font-weight="700">&#9733; A &#183; Iceberg read</text>
  <text x="54" y="204" fill="#eaf6ff" font-size="11.5" font-weight="700">Spark-free, pure Rust</text>
  <text x="54" y="222" fill="#9fc9e0" font-size="10">read a lake table into</text>
  <text x="54" y="237" fill="#9fc9e0" font-size="10">Arrow RecordBatch</text>
  <text x="54" y="258" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">bifrost/source.rs:452</text>
  <text x="54" y="273" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">--features skade</text>

  <!-- A1 warehouse -->
  <rect x="216" y="186" width="152" height="106" rx="10" fill="url(#chip)" stroke="#7CFFB2" stroke-width="2"/>
  <rect x="255" y="176" width="74" height="19" rx="9.5" fill="#0a2032" stroke="#7CFFB2" stroke-width="1.2"/>
  <text x="292" y="190" fill="#7CFFB2" font-size="9" font-weight="700" text-anchor="middle">EMBEDDED</text>
  <text x="292" y="226" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">warehouse dir</text>
  <text x="292" y="245" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">catalog.redb</text>
  <text x="292" y="259" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">warehouse/</text>
  <text x="292" y="278" fill="#86b3cc" font-size="9.5" text-anchor="middle">a folder, not a server</text>

  <path d="M368 239 H404" stroke="#7CFFB2" stroke-width="3" fill="none" marker-end="url(#flowg)"/>

  <!-- A2 skade -->
  <rect x="410" y="186" width="152" height="106" rx="10" fill="url(#chip)" stroke="#7CFFB2" stroke-width="2"/>
  <rect x="449" y="176" width="74" height="19" rx="9.5" fill="#0a2032" stroke="#7CFFB2" stroke-width="1.2"/>
  <text x="486" y="190" fill="#7CFFB2" font-size="9" font-weight="700" text-anchor="middle">EMBEDDED</text>
  <text x="486" y="226" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">skade 0.5.1</text>
  <text x="486" y="245" fill="#9fc9e0" font-size="9.5" text-anchor="middle">embedded Iceberg</text>
  <text x="486" y="259" fill="#9fc9e0" font-size="9.5" text-anchor="middle">catalog + reader</text>
  <text x="486" y="278" fill="#7CFFB2" font-size="9.5" text-anchor="middle">no JVM &#183; no REST</text>

  <path d="M562 239 H598" stroke="#7CFFB2" stroke-width="3" fill="none" marker-end="url(#flowg)"/>

  <!-- A3 IcebergSource -->
  <rect x="604" y="186" width="152" height="106" rx="10" fill="url(#chip)" stroke="#7CFFB2" stroke-width="2"/>
  <rect x="643" y="176" width="74" height="19" rx="9.5" fill="#0a2032" stroke="#7CFFB2" stroke-width="1.2"/>
  <text x="680" y="190" fill="#7CFFB2" font-size="9" font-weight="700" text-anchor="middle">EMBEDDED</text>
  <text x="680" y="226" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">IcebergSource</text>
  <text x="680" y="245" fill="#9fc9e0" font-size="9.5" text-anchor="middle">full snapshot read</text>
  <text x="680" y="259" fill="#9fc9e0" font-size="9.5" text-anchor="middle">or manifest delta</text>
  <text x="680" y="278" fill="#86b3cc" font-size="9.5" text-anchor="middle">Arrow 58, zero copy</text>

  <path d="M756 239 H792" stroke="#6fd3f5" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- A4 your process -->
  <rect x="798" y="186" width="152" height="106" rx="10" fill="url(#chip)" stroke="#6fd3f5" stroke-width="2"/>
  <rect x="841" y="176" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#6fd3f5" stroke-width="1.2"/>
  <text x="874" y="190" fill="#6fd3f5" font-size="9" font-weight="700" text-anchor="middle">PROCESS</text>
  <text x="874" y="226" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">your Rust binary</text>
  <text x="874" y="245" fill="#9fc9e0" font-size="9.5" text-anchor="middle">links the crate,</text>
  <text x="874" y="259" fill="#9fc9e0" font-size="9.5" text-anchor="middle">calls the function</text>
  <text x="874" y="278" fill="#86b3cc" font-size="9.5" text-anchor="middle">this is the only thing</text>

  <!-- A badge -->
  <rect x="978" y="186" width="164" height="106" rx="11" fill="#0d2b22" stroke="#7CFFB2" stroke-width="2.5"/>
  <text x="1060" y="228" fill="#7CFFB2" font-size="34" font-weight="700" text-anchor="middle">0</text>
  <text x="1060" y="250" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">services to start</text>
  <text x="1060" y="270" fill="#9fc9e0" font-size="10" text-anchor="middle">no container, no JVM</text>
  <text x="1060" y="284" fill="#9fc9e0" font-size="10" text-anchor="middle">no catalog server</text>

  <!-- ==================================================================== -->
  <!-- LANE B — Iceberg -> FalkorDB streaming.  ONE SERVICE.                -->
  <!-- ==================================================================== -->
  <rect x="36" y="334" width="1128" height="164" rx="12" fill="#08182a" stroke="#3c6a86" stroke-width="1.6"/>
  <text x="54" y="362" fill="#bfe6ff" font-size="15" font-weight="700">B &#183; transfer to graph</text>
  <text x="54" y="382" fill="#eaf6ff" font-size="11.5" font-weight="700">Iceberg &#8594; FalkorDB</text>
  <text x="54" y="400" fill="#9fc9e0" font-size="10">poll loop, MERGE upsert,</text>
  <text x="54" y="415" fill="#9fc9e0" font-size="10">durable snapshot cursor</text>
  <text x="54" y="436" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">watch_iceberg_delta</text>
  <text x="54" y="451" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">listener.rs:372</text>

  <!-- B1 -->
  <rect x="216" y="364" width="152" height="106" rx="10" fill="url(#chip)" stroke="#7CFFB2" stroke-width="2"/>
  <rect x="255" y="354" width="74" height="19" rx="9.5" fill="#0a2032" stroke="#7CFFB2" stroke-width="1.2"/>
  <text x="292" y="368" fill="#7CFFB2" font-size="9" font-weight="700" text-anchor="middle">EMBEDDED</text>
  <text x="292" y="404" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">warehouse + skade</text>
  <text x="292" y="423" fill="#9fc9e0" font-size="9.5" text-anchor="middle">snapshot diff walks</text>
  <text x="292" y="437" fill="#9fc9e0" font-size="9.5" text-anchor="middle">the manifest lineage</text>
  <text x="292" y="456" fill="#ffcf6f" font-size="9" text-anchor="middle">&#9888; redb is single-open</text>

  <path d="M368 417 H404" stroke="#6fd3f5" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- B2 -->
  <rect x="410" y="364" width="152" height="106" rx="10" fill="url(#chip)" stroke="#6fd3f5" stroke-width="2"/>
  <rect x="453" y="354" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#6fd3f5" stroke-width="1.2"/>
  <text x="486" y="368" fill="#6fd3f5" font-size="9" font-weight="700" text-anchor="middle">PROCESS</text>
  <text x="486" y="404" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">Listener loop</text>
  <text x="486" y="423" fill="#9fc9e0" font-size="9.5" text-anchor="middle">poll &#8594; transform &#8594;</text>
  <text x="486" y="437" fill="#9fc9e0" font-size="9.5" text-anchor="middle">sink &#8594; advance</text>
  <text x="486" y="456" fill="#ffcf6f" font-size="9" text-anchor="middle">&#9888; you must host it</text>

  <path d="M562 417 H598" stroke="#6fd3f5" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- B3 -->
  <rect x="604" y="364" width="152" height="106" rx="10" fill="url(#chip)" stroke="#7CFFB2" stroke-width="2"/>
  <rect x="643" y="354" width="74" height="19" rx="9.5" fill="#0a2032" stroke="#7CFFB2" stroke-width="1.2"/>
  <text x="680" y="368" fill="#7CFFB2" font-size="9" font-weight="700" text-anchor="middle">EMBEDDED</text>
  <text x="680" y="404" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">FalkorDbSink</text>
  <text x="680" y="423" fill="#9fc9e0" font-size="9.5" text-anchor="middle">MERGE upsert &#183; CDC</text>
  <text x="680" y="437" fill="#9fc9e0" font-size="9.5" text-anchor="middle">DETACH DELETE</text>
  <text x="680" y="456" fill="#7CFFB2" font-size="9.5" text-anchor="middle">idempotent, replay-safe</text>

  <path d="M756 417 H792" stroke="#ffcf6f" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- B4 FalkorDB -->
  <rect x="798" y="364" width="152" height="106" rx="10" fill="url(#chip)" stroke="#ffcf6f" stroke-width="2.5"/>
  <rect x="841" y="354" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#ffcf6f" stroke-width="1.2"/>
  <text x="874" y="368" fill="#ffcf6f" font-size="9" font-weight="700" text-anchor="middle">SERVICE</text>
  <text x="874" y="404" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">FalkorDB</text>
  <text x="874" y="423" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">redis://&#8230;:6379</text>
  <text x="874" y="437" fill="#9fc9e0" font-size="9.5" text-anchor="middle">GRAPH.QUERY / .BULK</text>
  <text x="874" y="456" fill="#ffcf6f" font-size="9" text-anchor="middle">container on Valkey 9</text>

  <!-- B badge -->
  <rect x="978" y="364" width="164" height="106" rx="11" fill="#2b2415" stroke="#ffcf6f" stroke-width="2.5"/>
  <text x="1060" y="406" fill="#ffcf6f" font-size="34" font-weight="700" text-anchor="middle">1</text>
  <text x="1060" y="428" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">service to start</text>
  <text x="1060" y="448" fill="#9fc9e0" font-size="10" text-anchor="middle">FalkorDB only</text>
  <text x="1060" y="462" fill="#9fc9e0" font-size="10" text-anchor="middle">&#43; podman if autostart</text>

  <!-- ==================================================================== -->
  <!-- LANE C — Spark Connect path.  TWO SERVICES.                          -->
  <!-- ==================================================================== -->
  <rect x="36" y="512" width="1128" height="164" rx="12" fill="#08182a" stroke="#3c6a86" stroke-width="1.6"/>
  <text x="54" y="540" fill="#bfe6ff" font-size="15" font-weight="700">C &#183; Spark Connect</text>
  <text x="54" y="560" fill="#eaf6ff" font-size="11.5" font-weight="700">the only remote-catalog route</text>
  <text x="54" y="578" fill="#9fc9e0" font-size="10">REST / Glue / Hive / S3</text>
  <text x="54" y="593" fill="#9fc9e0" font-size="10">tables live over here</text>
  <text x="54" y="614" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">SparkConnectSource</text>
  <text x="54" y="629" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">source.rs:200</text>

  <!-- C1 -->
  <rect x="216" y="542" width="152" height="106" rx="10" fill="url(#chip)" stroke="#5f7f93" stroke-width="1.6" stroke-dasharray="4 3"/>
  <rect x="265" y="532" width="54" height="19" rx="9.5" fill="#0a2032" stroke="#5f7f93" stroke-width="1.2" stroke-dasharray="3 3"/>
  <text x="292" y="546" fill="#8fb2c6" font-size="9" font-weight="700" text-anchor="middle">OPT</text>
  <text x="292" y="578" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">Iceberg catalog</text>
  <text x="292" y="596" fill="#9fc9e0" font-size="9.5" text-anchor="middle">REST / Glue / Nessie</text>
  <text x="292" y="610" fill="#9fc9e0" font-size="9.5" text-anchor="middle">&#43; S3 / MinIO store</text>
  <text x="292" y="626" fill="#8fb2c6" font-size="9" text-anchor="middle">only if tables live there;</text>
  <text x="292" y="638" fill="#8fb2c6" font-size="9" text-anchor="middle">our image ships hadoop-local</text>

  <path d="M368 595 H404" stroke="#ffcf6f" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- C2 Spark -->
  <rect x="410" y="542" width="152" height="106" rx="10" fill="url(#chip)" stroke="#ffcf6f" stroke-width="2.5"/>
  <rect x="453" y="532" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#ffcf6f" stroke-width="1.2"/>
  <text x="486" y="546" fill="#ffcf6f" font-size="9" font-weight="700" text-anchor="middle">SERVICE</text>
  <text x="486" y="582" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">Spark Connect</text>
  <text x="486" y="601" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">sc://&#8230;:15002</text>
  <text x="486" y="616" fill="#9fc9e0" font-size="9.5" text-anchor="middle">Spark 4.1.2 &#43; iceberg</text>
  <text x="486" y="630" fill="#9fc9e0" font-size="9.5" text-anchor="middle">runtime 1.11.0 &#183; a JVM</text>

  <path d="M562 595 H598" stroke="#6fd3f5" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- C3 -->
  <rect x="604" y="542" width="152" height="106" rx="10" fill="url(#chip)" stroke="#6fd3f5" stroke-width="2"/>
  <rect x="647" y="532" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#6fd3f5" stroke-width="1.2"/>
  <text x="680" y="546" fill="#6fd3f5" font-size="9" font-weight="700" text-anchor="middle">PROCESS</text>
  <text x="680" y="582" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">bifrost client</text>
  <text x="680" y="601" fill="#9fc9e0" font-size="9.5" text-anchor="middle">gRPC &#183; SQL strings</text>
  <text x="680" y="615" fill="#9fc9e0" font-size="9.5" text-anchor="middle">create_changelog_view</text>
  <text x="680" y="634" fill="#ffcf6f" font-size="9" text-anchor="middle">&#9888; attached, cannot detach</text>

  <path d="M756 595 H792" stroke="#ffcf6f" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- C4 -->
  <rect x="798" y="542" width="152" height="106" rx="10" fill="url(#chip)" stroke="#ffcf6f" stroke-width="2.5"/>
  <rect x="841" y="532" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#ffcf6f" stroke-width="1.2"/>
  <text x="874" y="546" fill="#ffcf6f" font-size="9" font-weight="700" text-anchor="middle">SERVICE</text>
  <text x="874" y="582" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">FalkorDB</text>
  <text x="874" y="601" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">redis://&#8230;:6379</text>
  <text x="874" y="615" fill="#9fc9e0" font-size="9.5" text-anchor="middle">same sink as lane B</text>

  <!-- C badge -->
  <rect x="978" y="542" width="164" height="106" rx="11" fill="#2b2415" stroke="#ffcf6f" stroke-width="2.5"/>
  <text x="1060" y="582" fill="#ffcf6f" font-size="34" font-weight="700" text-anchor="middle">2</text>
  <text x="1060" y="603" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">services to start</text>
  <text x="1060" y="621" fill="#9fc9e0" font-size="10" text-anchor="middle">Spark 4.1.2 &#183; FalkorDB</text>
  <text x="1060" y="634" fill="#9fc9e0" font-size="10" text-anchor="middle">our image is hadoop-local:</text>
  <text x="1060" y="645" fill="#9fc9e0" font-size="10" text-anchor="middle">no catalog server needed</text>

  <!-- ==================================================================== -->
  <!-- LANE D — remote clients + UI + submit-and-detach                     -->
  <!-- ==================================================================== -->
  <rect x="36" y="690" width="1128" height="164" rx="12" fill="#08182a" stroke="#3c6a86" stroke-width="1.6"/>
  <text x="54" y="718" fill="#bfe6ff" font-size="15" font-weight="700">D &#183; remote &#43; detach</text>
  <text x="54" y="738" fill="#eaf6ff" font-size="11.5" font-weight="700">clients, UI, spark-submit</text>
  <text x="54" y="756" fill="#9fc9e0" font-size="10">cross-language ingest and</text>
  <text x="54" y="771" fill="#9fc9e0" font-size="10">the &#8220;walk away&#8221; question</text>
  <text x="54" y="792" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">graphar-flight</text>
  <text x="54" y="807" fill="#86b3cc" font-size="9.5" font-family="'DejaVu Sans Mono', monospace">jera Scheduler</text>

  <!-- D1 -->
  <rect x="216" y="720" width="152" height="106" rx="10" fill="url(#chip)" stroke="#5f7f93" stroke-width="1.6" stroke-dasharray="4 3"/>
  <rect x="265" y="710" width="54" height="19" rx="9.5" fill="#0a2032" stroke="#5f7f93" stroke-width="1.2" stroke-dasharray="3 3"/>
  <text x="292" y="724" fill="#8fb2c6" font-size="9" font-weight="700" text-anchor="middle">OPT</text>
  <text x="292" y="760" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">Python / ADBC</text>
  <text x="292" y="779" fill="#9fc9e0" font-size="9.5" text-anchor="middle">KnutClient, Power BI,</text>
  <text x="292" y="793" fill="#9fc9e0" font-size="9.5" text-anchor="middle">any Flight SQL driver</text>
  <text x="292" y="812" fill="#86b3cc" font-size="9" text-anchor="middle">only if you want remote</text>

  <path d="M368 773 H404" stroke="#7fb0cc" stroke-width="2.5" fill="none" stroke-dasharray="5 4" marker-end="url(#flowo)"/>

  <!-- D2 flight server -->
  <rect x="410" y="720" width="152" height="106" rx="10" fill="url(#chip)" stroke="#ffcf6f" stroke-width="2.5"/>
  <rect x="453" y="710" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#ffcf6f" stroke-width="1.2"/>
  <text x="486" y="724" fill="#ffcf6f" font-size="9" font-weight="700" text-anchor="middle">SERVICE</text>
  <text x="486" y="760" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">Flight SQL server</text>
  <text x="486" y="779" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">grpc &#8230;:50051</text>
  <text x="486" y="793" fill="#9fc9e0" font-size="9.5" text-anchor="middle">DoPut ingest &#183; queries</text>
  <text x="486" y="812" fill="#ffcf6f" font-size="9" text-anchor="middle">&#9888; serial lane, ~100&#215; slower</text>

  <path d="M562 773 H598" stroke="#ffcf6f" stroke-width="3" fill="none" marker-end="url(#flow)"/>

  <!-- D3 falkordb -->
  <rect x="604" y="720" width="152" height="106" rx="10" fill="url(#chip)" stroke="#ffcf6f" stroke-width="2.5"/>
  <rect x="647" y="710" width="66" height="19" rx="9.5" fill="#0a2032" stroke="#ffcf6f" stroke-width="1.2"/>
  <text x="680" y="724" fill="#ffcf6f" font-size="9" font-weight="700" text-anchor="middle">SERVICE</text>
  <text x="680" y="760" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">FalkorDB</text>
  <text x="680" y="779" fill="#9fc9e0" font-size="9.5" text-anchor="middle">the one shared terminus</text>
  <text x="680" y="793" fill="#9fc9e0" font-size="9.5" text-anchor="middle">of every write path</text>

  <!-- D4 korp / jera -->
  <rect x="798" y="720" width="152" height="106" rx="10" fill="url(#chip)" stroke="#5f7f93" stroke-width="1.6" stroke-dasharray="4 3"/>
  <rect x="847" y="710" width="54" height="19" rx="9.5" fill="#0a2032" stroke="#5f7f93" stroke-width="1.2" stroke-dasharray="3 3"/>
  <text x="874" y="724" fill="#8fb2c6" font-size="9" font-weight="700" text-anchor="middle">OPT</text>
  <text x="874" y="760" fill="#eaf6ff" font-size="13" font-weight="700" text-anchor="middle">korp UI / jera</text>
  <text x="874" y="779" fill="#9fc9e0" font-size="9.5" text-anchor="middle">GUI job ledger &#183; redb</text>
  <text x="874" y="793" fill="#9fc9e0" font-size="9.5" text-anchor="middle">Process / Container / Vm</text>
  <text x="874" y="812" fill="#ffcf6f" font-size="9" text-anchor="middle">&#9888; ships a spec, not code</text>

  <!-- D badge -->
  <rect x="978" y="720" width="164" height="106" rx="11" fill="#2b2415" stroke="#ffcf6f" stroke-width="2.5"/>
  <text x="1060" y="762" fill="#ffcf6f" font-size="34" font-weight="700" text-anchor="middle">2</text>
  <text x="1060" y="784" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">services to start</text>
  <text x="1060" y="804" fill="#9fc9e0" font-size="10" text-anchor="middle">Flight server &#43; FalkorDB</text>
  <text x="1060" y="818" fill="#8fb2c6" font-size="10" text-anchor="middle">korp / jera optional</text>

  <!-- ==================================================================== -->
  <!-- GROUND RAIL — the honest verdict                                     -->
  <!-- ==================================================================== -->
  <rect x="36" y="872" width="1128" height="76" rx="10" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
  <g fill="#0a1c2c" stroke="#7fc8ea" stroke-width="1.5">
    <circle cx="72" cy="910" r="4"/><circle cx="1128" cy="910" r="4"/>
  </g>
  <text x="96" y="898" fill="#dff1ff" font-size="14" font-weight="700">read this first</text>
  <text x="240" y="898" fill="#bcd9ec" font-size="11.5"><tspan fill="#7CFFB2" font-weight="700">Lane A needs nothing running</tspan> &#8212; link the crate and call a function. Lane B adds exactly one container. Only lane C needs a JVM.</text>
  <text x="96" y="922" fill="#ffcf6f" font-size="11" font-weight="700">not yet true</text>
  <text x="240" y="922" fill="#bcd9ec" font-size="11">There is <tspan fill="#ffcf6f" font-weight="700">no submit-and-detach</tspan>: every lane runs in a process you keep alive. The <tspan font-family="'DejaVu Sans Mono', monospace">bifrost</tspan> CLI wires FileSource only &#8212; lanes A&#8211;C are library-API today.</text>
  <text x="96" y="940" fill="#8fb2c6" font-size="11" font-weight="700">the gap</text>
  <text x="240" y="940" fill="#8fb2c6" font-size="10.5">Closest route to spark-submit ergonomics: add <tspan font-family="'DejaVu Sans Mono', monospace">--warehouse</tspan> to the CLI, ship it as an image, dispatch a jera <tspan font-family="'DejaVu Sans Mono', monospace">WorkPayload::Container</tspan>. SDP is not it &#8212; Python/SQL, equally attached.</text>
</svg>