.nornir/assets/knut_flow.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 680" 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>
</defs>
<!-- PCB substrate -->
<rect x="0" y="0" width="1180" height="680" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1">
<line x1="0" y1="76" x2="1180" y2="76"/>
<line x1="0" y1="632" x2="1180" y2="632"/>
</g>
<g fill="#16415c">
<circle cx="40" cy="40" r="2"/><circle cx="1140" cy="40" r="2"/>
<circle cx="40" cy="652" r="2"/><circle cx="1140" cy="652" r="2"/>
</g>
<!-- title -->
<text x="40" y="44" fill="#eaf6ff" font-size="22" font-weight="700">knut</text>
<text x="100" y="44" fill="#9fc9e0" font-size="15">knytpunkt — Arrow IPC source flows left→right: GraphAr → FalkorDB → Flight SQL → <tspan fill="#bfe6ff" font-weight="700">Bifrost client</tspan></text>
<!-- legend -->
<g font-size="12.5">
<line x1="830" y1="60" x2="870" y2="60" stroke="#6fd3f5" stroke-width="3"/>
<text x="878" y="64" fill="#cfe6f5">data path</text>
<line x1="980" y1="60" x2="1020" y2="60" stroke="#7fb0cc" stroke-width="2.5" stroke-dasharray="5 4"/>
<text x="1028" y="64" fill="#cfe6f5">optional / export path</text>
</g>
<!-- ===================== ARROW IPC SOURCE (left) ===================== -->
<rect x="36" y="150" width="152" height="200" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="112" y="178" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">Arrow IPC</text>
<text x="112" y="198" fill="#9fc9e0" font-size="11" text-anchor="middle">source data</text>
<text x="112" y="224" fill="#86b3cc" font-size="10.5" text-anchor="middle">RecordBatch stream</text>
<text x="112" y="242" fill="#86b3cc" font-size="10.5" text-anchor="middle">columnar in-memory</text>
<text x="112" y="268" fill="#a9d8ee" font-size="10" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">Parquet / CSV / ORC</text>
<text x="112" y="284" fill="#a9d8ee" font-size="10" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">JSON / Arrow IPC</text>
<text x="112" y="308" fill="#7fa8c4" font-size="10" text-anchor="middle">all fed as RecordBatch</text>
<text x="112" y="326" fill="#7fa8c4" font-size="10" text-anchor="middle">to the GraphAr layer</text>
<rect x="188" y="238" width="6" height="8" fill="#6fd3f5"/>
<!-- source -> GraphAr -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M194 242 H240"/>
</g>
<circle cx="240" cy="242" r="4" fill="#bfecff"/>
<!-- ===================== GRAPHAR ===================== -->
<rect x="240" y="128" width="176" height="248" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<text x="328" y="156" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">GraphAr</text>
<text x="328" y="174" fill="#9fc9e0" font-size="10.5" text-anchor="middle">gar/v1 property graph files</text>
<rect x="262" y="188" width="132" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="328" y="202" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">vertex readers</text>
<text x="328" y="216" fill="#9fc9e0" font-size="9.5" text-anchor="middle">chunked vertex groups</text>
<rect x="262" y="230" width="132" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="328" y="244" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">edge readers</text>
<text x="328" y="258" fill="#9fc9e0" font-size="9.5" text-anchor="middle">chunked adj lists</text>
<rect x="262" y="272" width="132" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="328" y="286" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">ChunkStore</text>
<text x="328" y="300" fill="#9fc9e0" font-size="9.5" text-anchor="middle">object_store (local/S3)</text>
<text x="328" y="334" fill="#86b3cc" font-size="10" text-anchor="middle">merge_property_groups</text>
<text x="328" y="350" fill="#86b3cc" font-size="10" text-anchor="middle">5 formats: parquet/csv/</text>
<text x="328" y="364" fill="#7fa8c4" font-size="10" text-anchor="middle">orc/json/arrow-ipc</text>
<rect x="416" y="238" width="6" height="8" fill="#6fd3f5"/>
<!-- GraphAr -> FalkorDB -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M422 242 H470"/>
</g>
<circle cx="470" cy="242" r="4" fill="#bfecff"/>
<!-- ===================== FALKORDB ===================== -->
<rect x="470" y="148" width="172" height="228" rx="11" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="556" y="176" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">FalkorDB</text>
<text x="556" y="196" fill="#9fc9e0" font-size="10.5" text-anchor="middle">graphar-falkordb layer</text>
<rect x="492" y="210" width="128" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="556" y="226" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">UNWIND CREATE</text>
<text x="556" y="240" fill="#9fc9e0" font-size="9.5" text-anchor="middle">_gar_id keyed identity</text>
<rect x="492" y="252" width="128" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="556" y="268" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">MERGE</text>
<text x="556" y="282" fill="#9fc9e0" font-size="9.5" text-anchor="middle">Arrow → Cypher values</text>
<text x="556" y="320" fill="#86b3cc" font-size="10" text-anchor="middle">RecordBatch → graph elements</text>
<text x="556" y="336" fill="#86b3cc" font-size="10" text-anchor="middle">via Cypher bulk-load</text>
<text x="556" y="352" fill="#7fa8c4" font-size="10" text-anchor="middle">identity: _gar_id key</text>
<rect x="642" y="234" width="6" height="8" fill="#6fd3f5"/>
<!-- FalkorDB -> Flight SQL -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M648 238 H694"/>
</g>
<circle cx="694" cy="238" r="4" fill="#bfecff"/>
<!-- ===================== FLIGHT SQL SERVER ===================== -->
<rect x="694" y="128" width="188" height="260" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="788" y="156" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">Flight SQL</text>
<text x="788" y="174" fill="#9fc9e0" font-size="10.5" text-anchor="middle">graphar-flight server</text>
<rect x="716" y="188" width="144" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="788" y="204" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">Cypher queries in</text>
<text x="788" y="218" fill="#9fc9e0" font-size="9.5" text-anchor="middle">via FlightSQL protocol</text>
<rect x="716" y="230" width="144" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="788" y="246" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">Arrow batches out</text>
<text x="788" y="260" fill="#9fc9e0" font-size="9.5" text-anchor="middle">RecordBatch stream</text>
<rect x="716" y="272" width="144" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="788" y="288" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">metadata surface</text>
<text x="788" y="302" fill="#9fc9e0" font-size="9.5" text-anchor="middle">catalogs/schemas/tables</text>
<text x="788" y="334" fill="#86b3cc" font-size="10" text-anchor="middle">auth: bearer / Basic</text>
<text x="788" y="348" fill="#86b3cc" font-size="10" text-anchor="middle">mutual TLS</text>
<text x="788" y="366" fill="#a9d8ee" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">ADBC/ODBC (Power BI)</text>
<rect x="882" y="232" width="6" height="8" fill="#6fd3f5"/>
<!-- Flight SQL -> Bifrost client -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M888 236 H934"/>
</g>
<circle cx="934" cy="236" r="4" fill="#bfecff"/>
<!-- ===================== BIFROST CLIENT ===================== -->
<rect x="934" y="148" width="208" height="228" rx="11" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="1038" y="176" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">Bifrost client</text>
<text x="1038" y="196" fill="#9fc9e0" font-size="10.5" text-anchor="middle">knut-bifrost</text>
<rect x="956" y="210" width="164" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="1038" y="226" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">watch lakehouse tables</text>
<text x="1038" y="240" fill="#9fc9e0" font-size="9.5" text-anchor="middle">Iceberg change feed</text>
<rect x="956" y="252" width="164" height="34" rx="6" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.6"/>
<text x="1038" y="268" fill="#bfe6ff" font-size="10.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">Arrow Flight stream</text>
<text x="1038" y="282" fill="#9fc9e0" font-size="9.5" text-anchor="middle">response to caller</text>
<text x="1038" y="318" fill="#86b3cc" font-size="10" text-anchor="middle">graph → lakehouse export</text>
<text x="1038" y="332" fill="#a9d8ee" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">query rows → GraphAr file</text>
<text x="1038" y="346" fill="#a9d8ee" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">or Iceberg table (skade)</text>
<text x="1038" y="364" fill="#7fa8c4" font-size="9.5" text-anchor="middle">feature: skade</text>
<!-- optional Iceberg export -->
<path d="M1038 376 V460 H560 V380" stroke="#7fb0cc" stroke-width="2.5" fill="none" stroke-dasharray="6 4"/>
<g fill="#0a1c2c" stroke="#7fb0cc" stroke-width="1.4">
<circle cx="800" cy="460" r="3.5"/>
</g>
<text x="790" y="476" fill="#86b3cc" font-size="10" text-anchor="middle">graph → Iceberg export via skade (optional feature)</text>
<!-- ===================== GROUND RAIL ===================== -->
<rect x="240" y="552" width="902" height="56" rx="10" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<g fill="#0a1c2c" stroke="#7fc8ea" stroke-width="1.5">
<circle cx="284" cy="580" r="4"/><circle cx="556" cy="580" r="4"/>
<circle cx="822" cy="580" r="4"/><circle cx="1040" cy="580" r="4"/>
</g>
<text x="300" y="579" fill="#dff1ff" font-size="15" font-weight="700">properties</text>
<text x="440" y="575" fill="#bcd9ec" font-size="11.5">zero-copy Arrow throughout · Cypher in / Arrow out · Power BI / ADBC compatible</text>
<text x="440" y="596" fill="#7fa8c4" font-size="10.5" font-family="'DejaVu Sans Mono', monospace">GraphAr gar/v1 · FalkorDB bulk-load · Flight SQL auth · Bifrost watch · skade Iceberg export</text>
</svg>