OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / docs / html / HTTPS-GATEWAY.html

201 lines · html ref:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>HTTPS Gateway — The HTTP(S) Read Plane over P2P Storage</title>
<style>
  :root { color-scheme: light; }
  * { box-sizing: border-box; }
  body { margin: 0; padding: 0; background: #eef1f6; color: #1a2333;
    font: 16px/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
  .page { max-width: 920px; margin: 32px auto; background: #fff; padding: 56px 64px;
    border-radius: 14px; box-shadow: 0 2px 18px rgba(20,30,60,.10); }
  h1 { font-size: 1.9rem; line-height: 1.25; margin: 0 0 .4em; padding-bottom: .35em; border-bottom: 3px solid #4a6fa5; }
  h2 { font-size: 1.35rem; margin-top: 2em; border-bottom: 1px solid #dde3ee; padding-bottom: .2em; }
  h3 { font-size: 1.1rem; margin-top: 1.6em; color: #2c3e63; }
  blockquote { margin: 1em 0; padding: .8em 1.1em; background: #f2f6fd; border-left: 4px solid #4a6fa5; border-radius: 0 8px 8px 0; color: #2c3e63; }
  code { background: #f0f2f7; padding: .12em .38em; border-radius: 5px; font: .86em ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
  pre { background: #141a28; color: #e6ebf5; padding: 16px 18px; border-radius: 10px; overflow-x: auto; }
  pre code { background: none; padding: 0; color: inherit; }
  table { border-collapse: collapse; width: 100%; margin: 1em 0; font-size: .92rem; }
  th, td { border: 1px solid #d8deea; padding: 8px 10px; text-align: left; vertical-align: top; }
  th { background: #eef2fa; }
  tr:nth-child(even) td { background: #fafbfe; }
  a { color: #2f5fb3; }
  .mermaid-figure { margin: 1.4em 0; padding: 20px; background: #fbfcfe; border: 1px solid #e2e8f2; border-radius: 12px; text-align: center; overflow-x: auto; }
  .mermaid-figure svg { max-width: 100%; height: auto; }
  .doc-badge { display: inline-block; font-size: .75rem; letter-spacing: .04em; text-transform: uppercase;
    background: #4a6fa5; color: #fff; border-radius: 999px; padding: 3px 12px; margin-bottom: 14px; }
  hr { border: none; border-top: 1px solid #dde3ee; margin: 2em 0; }
  </style>
</head>
<body>
<div class="page">
<div class="doc-badge">HTTPS-GATEWAY</div>
<h1>HTTPS Gateway — The HTTP(S) Read Plane over P2P Storage</h1>
<p><strong>Status:</strong> path gateway shipped (release lane, v0.24.x) · app-origin gateway in Phase-1 canary (<code>hr-https-gateway</code> lane, staging-only) · <strong>Code:</strong> <code>packages/core/gateway/hyper-gateway.js</code>, <code>packages/core/core/relay-node/api.js</code>, <code>packages/core/core/relay-node/gateway-server.js</code></p>
<blockquote>
<p>The gateway re-serves seeded Hyperdrives over ordinary HTTP so clients that can&#39;t (yet) speak Hyperswarm — browsers, mobile apps, curl, CDNs — can fetch content immediately: <em>&quot;open the app/site now, keep P2P syncing in the background.&quot;</em> It is also the <strong>Tor read plane</strong>: the onion read-plane vport forwards to the same gateway port, giving the same three public routes over Tor with genuine client-IP privacy.</p>
</blockquote>
<h2>1. Two maturity states (be precise)</h2>
<table>
<thead>
<tr>
<th></th>
<th>Path gateway (shipped)</th>
<th>App-origin gateway (Phase 1 canary)</th>
</tr>
</thead>
<tbody><tr>
<td>URL shape</td>
<td><code>GET /v1/hyper/&lt;64-hex-key&gt;/&lt;path&gt;</code></td>
<td><code>https://&lt;52-char-z32-key&gt;.&lt;gateway-domain&gt;/&lt;path&gt;</code></td>
</tr>
<tr>
<td>Origin model</td>
<td>shared origin, HTML rewritten for relative paths</td>
<td>per-app origins, <strong>exact untransformed bytes</strong></td>
</tr>
<tr>
<td>Admission</td>
<td>seeded + <code>public</code> tier + PolicyGuard</td>
<td>+ operator allowlist + storage-proof pin</td>
</tr>
<tr>
<td>TLS edge</td>
<td>reverse proxy of your choice</td>
<td>strict nginx wildcard edge (SNI==Host, 421 default)</td>
</tr>
<tr>
<td>Deployment</td>
<td>in relay (port 9100) or split data plane (port 9200)</td>
<td>loopback-only behind the wildcard edge</td>
</tr>
</tbody></table>
<p>The app-origin lane lives in the <code>hr-https-gateway</code> worktree and is <strong>not merged</strong>; its own spec gates live-fleet use. Everything below marks which state each behavior belongs to. The gateway is <strong>not a privacy upgrade</strong> for content: blind/custody data stays on encrypted P2P paths (blind entries are hard-403).</p>
<h2>2. Request lifecycle — path gateway (shipped)</h2>
<div class="mermaid-figure"><svg id="my-svg" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="max-width: 1164px; background-color: transparent;" viewBox="-50 -10 1164 914" role="graphics-document document" aria-roledescription="sequence"><g><rect x="914" y="828" fill="#eaeaea" stroke="#666" width="150" height="65" name="D" rx="3" ry="3" class="actor actor-bottom"/><text x="989" y="860.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="989" dy="0">Drive (Corestore)</tspan></text></g><g><rect x="540" y="828" fill="#eaeaea" stroke="#666" width="150" height="65" name="GW" rx="3" ry="3" class="actor actor-bottom"/><text x="615" y="860.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="615" dy="0">HyperGateway</tspan></text></g><g><rect x="235" y="828" fill="#eaeaea" stroke="#666" width="150" height="65" name="API" rx="3" ry="3" class="actor actor-bottom"/><text x="310" y="860.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="310" dy="0">RelayAPI (:9100)</tspan></text></g><g><rect x="0" y="828" fill="#eaeaea" stroke="#666" width="150" height="65" name="C" rx="3" ry="3" class="actor actor-bottom"/><text x="75" y="860.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="75" dy="0">Client</tspan></text></g><g><line id="actor3" x1="989" y1="65" x2="989" y2="828" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="D" data-et="life-line" data-id="D"/><g id="root-3" data-et="participant" data-type="participant" data-id="D"><rect x="914" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="D" rx="3" ry="3" class="actor actor-top"/><text x="989" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="989" dy="0">Drive (Corestore)</tspan></text></g></g><g><line id="actor2" x1="615" y1="65" x2="615" y2="828" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="GW" data-et="life-line" data-id="GW"/><g id="root-2" data-et="participant" data-type="participant" data-id="GW"><rect x="540" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="GW" rx="3" ry="3" class="actor actor-top"/><text x="615" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="615" dy="0">HyperGateway</tspan></text></g></g><g><line id="actor1" x1="310" y1="65" x2="310" y2="828" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="API" data-et="life-line" data-id="API"/><g id="root-1" data-et="participant" data-type="participant" data-id="API"><rect x="235" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="API" rx="3" ry="3" class="actor actor-top"/><text x="310" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="310" dy="0">RelayAPI (:9100)</tspan></text></g></g><g><line id="actor0" x1="75" y1="65" x2="75" y2="828" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="C" data-et="life-line" data-id="C"/><g id="root-0" data-et="participant" data-type="participant" data-id="C"><rect x="0" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="C" rx="3" ry="3" class="actor actor-top"/><text x="75" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="75" dy="0">Client</tspan></text></g></g><style>#my-svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:#552222;}#my-svg .error-text{fill:#552222;stroke:#552222;}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:#5a7196;stroke:#5a7196;}#my-svg .marker.cross{stroke:#5a7196;}#my-svg svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;}#my-svg p{margin:0;}#my-svg .actor{stroke:#9370DB;fill:#ECECFF;stroke-width:1;}#my-svg rect.actor.outer-path[data-look="neo"]{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg rect.note[data-look="neo"]{stroke:#aaaa33;fill:#fff5ad;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg text.actor&gt;tspan{fill:black;stroke:none;}#my-svg .actor-line{stroke:#9370DB;}#my-svg .innerArc{stroke-width:1.5;stroke-dasharray:none;}#my-svg .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#my-svg .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#my-svg [id$="-arrowhead"] path{fill:#333;stroke:#333;}#my-svg .sequenceNumber{fill:white;}#my-svg [id$="-sequencenumber"]{fill:#333;}#my-svg [id$="-crosshead"] path{fill:#333;stroke:#333;}#my-svg .messageText{fill:#333;stroke:none;}#my-svg .labelBox{stroke:#9370DB;fill:#ECECFF;filter:none;}#my-svg .labelText,#my-svg .labelText&gt;tspan{fill:black;stroke:none;}#my-svg .loopText,#my-svg .loopText&gt;tspan{fill:black;stroke:none;}#my-svg .sectionTitle,#my-svg .sectionTitle&gt;tspan{fill:black;stroke:none;}#my-svg .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:#9370DB;fill:#9370DB;}#my-svg .note{stroke:#aaaa33;fill:#fff5ad;}#my-svg .noteText,#my-svg .noteText&gt;tspan{fill:black;stroke:none;font-weight:normal;}#my-svg .activation0{fill:#f4f4f4;stroke:#666;}#my-svg .activation1{fill:#f4f4f4;stroke:#666;}#my-svg .activation2{fill:#f4f4f4;stroke:#666;}#my-svg .actorPopupMenu{position:absolute;}#my-svg .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#my-svg .actor-man circle,#my-svg line{fill:#ECECFF;stroke-width:2px;}#my-svg g rect.rect{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));stroke:#9370DB;}#my-svg .node .neo-node{stroke:#9370DB;}#my-svg [data-look="neo"].node rect,#my-svg [data-look="neo"].cluster rect,#my-svg [data-look="neo"].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].swimlane.cluster rect{filter:none;}#my-svg [data-look="neo"].node path{stroke:#9370DB;stroke-width:1px;}#my-svg [data-look="neo"].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node .neo-line path{stroke:#9370DB;filter:none;}#my-svg [data-look="neo"].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node circle .state-start{fill:#000000;}#my-svg [data-look="neo"].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g/><defs><symbol id="my-svg-computer" width="24" height="24"><path transform="scale(.5)" d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z"/></symbol></defs><defs><symbol id="my-svg-database" fill-rule="evenodd" clip-rule="evenodd"><path transform="scale(.5)" d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z"/></symbol></defs><defs><symbol id="my-svg-clock" width="24" height="24"><path transform="scale(.5)" d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z"/></symbol></defs><defs><marker id="my-svg-arrowhead" refX="7.9" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"><path d="M -1 0 L 10 5 L 0 10 z"/></marker></defs><defs><marker id="my-svg-crosshead" markerWidth="15" markerHeight="8" orient="auto" refX="4" refY="4.5"><path fill="none" stroke="#000000" stroke-width="1pt" d="M 1,2 L 6,7 M 6,2 L 1,7" style="stroke-dasharray: 0, 0;"/></marker></defs><defs><marker id="my-svg-filled-head" refX="15.5" refY="7" markerWidth="20" markerHeight="28" orient="auto"><path d="M 18,7 L9,13 L14,7 L9,1 Z"/></marker></defs><defs><marker id="my-svg-sequencenumber" refX="15" refY="15" markerWidth="60" markerHeight="40" orient="auto"><circle cx="15" cy="15" r="6"/></marker></defs><defs><marker id="my-svg-solidTopArrowHead" refX="7.9" refY="7.25" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"><path d="M 0 0 L 10 8 L 0 8 z"/></marker></defs><defs><marker id="my-svg-solidBottomArrowHead" refX="7.9" refY="0.75" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"><path d="M 0 0 L 10 0 L 0 8 z"/></marker></defs><defs><marker id="my-svg-stickTopArrowHead" refX="7.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"><path d="M 0 0 L 7 7" stroke="black" stroke-width="1.5" fill="none"/></marker></defs><defs><marker id="my-svg-stickBottomArrowHead" refX="7.5" refY="0" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"><path d="M 0 7 L 7 0" stroke="black" stroke-width="1.5" fill="none"/></marker></defs><g data-et="control-structure" data-id="i13"><line x1="64" y1="524" x2="626" y2="524" class="loopLine"/><line x1="626" y1="524" x2="626" y2="808" class="loopLine"/><line x1="64" y1="808" x2="626" y2="808" class="loopLine"/><line x1="64" y1="524" x2="64" y2="808" class="loopLine"/><line x1="64" y1="618" x2="626" y2="618" class="loopLine" style="stroke-dasharray: 3, 3;"/><line x1="64" y1="707" x2="626" y2="707" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="64,524 114,524 114,537 105.6,544 64,544" class="labelBox"/><text x="89" y="537" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="370" y="542" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="370">[directory path]</tspan></text><text x="345" y="636" text-anchor="middle" class="sectionTitle" style="font-size: 16px; font-weight: 400;">[HTML]</text><text x="345" y="725" text-anchor="middle" class="sectionTitle" style="font-size: 16px; font-weight: 400;">[other types]</text></g><text x="191" y="80" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">GET /v1/hyper/:key/:path</text><line x1="76" y1="109" x2="306" y2="109" class="messageLine0" data-et="message" data-id="i0" data-from="C" data-to="API" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="fill: none;"/><text x="311" y="124" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">CORS decision, per-IP + per-endpoint rate limits</text><path d="M 311,153 C 371,143 371,183 311,173" class="messageLine0" data-et="message" data-id="i1" data-from="API" data-to="API" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="fill: none;"/><text x="461" y="198" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">isHyperGatewayRoute then handle()</text><line x1="311" y1="227" x2="611" y2="227" class="messageLine0" data-et="message" data-id="i2" data-from="API" data-to="GW" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="fill: none;"/><text x="616" y="242" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">GET/HEAD only, split key/path,</text><text x="616" y="260" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">double-decode traversal rejection, 64-hex check</text><path d="M 616,288 C 676,278 676,318 616,308" class="messageLine0" data-et="message" data-id="i3" data-from="GW" data-to="GW" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="fill: none;"/><text x="616" y="333" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">authz — seeded? blind gives 403, non-public tier gives 403,</text><text x="616" y="351" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">PolicyGuard serve-code</text><path d="M 616,379 C 676,369 676,409 616,399" class="messageLine0" data-et="message" data-id="i4" data-from="GW" data-to="GW" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="fill: none;"/><text x="801" y="424" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">_getDrive — borrow live, else LRU cache, else</text><text x="801" y="442" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">session + swarm + wait max 20s</text><line x1="616" y1="470" x2="985" y2="470" class="messageLine0" data-et="message" data-id="i5" data-from="GW" data-to="D" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="fill: none;"/><text x="804" y="485" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">entry() existence + byteLength</text><line x1="988" y1="514" x2="619" y2="514" class="messageLine1" data-et="message" data-id="i6" data-from="D" data-to="GW" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="347" y="574" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">index.html or bounded JSON listing</text><line x1="614" y1="603" x2="79" y2="603" class="messageLine1" data-et="message" data-id="i8" data-from="GW" data-to="C" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="347" y="663" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">buffered, absolute→relative rewrite</text><line x1="614" y1="692" x2="79" y2="692" class="messageLine1" data-et="message" data-id="i10" data-from="GW" data-to="C" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="347" y="752" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">streamed (range → 206, bad range → 416),</text><text x="347" y="770" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">MIME map, nosniff, Accept-Ranges</text><line x1="614" y1="798" x2="79" y2="798" class="messageLine1" data-et="message" data-id="i12" data-from="GW" data-to="C" stroke-width="2" stroke="none" marker-end="url(#my-svg-arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/></svg></div>
<p>Steps and the code behind them:</p>
<ol>
<li><strong>Ingress</strong> — CORS (<code>api-cors.js</code>), global + per-endpoint rate limits (<code>api.js</code>), route dispatch via <code>isHyperGatewayRoute</code>.</li>
<li><strong>Validation</strong> — methods, key/path split, <strong>double-decode path-traversal rejection</strong> (<code>..</code>, NUL, drive letters, double-encoded), 64-hex key check.</li>
<li><strong>Authorization chain</strong> — must be in <code>seededApps</code>; <code>blind</code> → 403 &quot;P2P access only&quot;; non-<code>public</code> tier → 403 (default); <code>PolicyGuard.check(..., &#39;serve-code&#39;)</code>.</li>
<li><strong>Drive resolution</strong> — borrow the live seeded drive → 20-entry LRU cache with refresh-in-background → else a <strong>per-drive Corestore session</strong> (avoids the root-store-close cascade bug), join swarm, wait ≤20 s for content, background full download.</li>
<li><strong>Response</strong> — directories resolve to <code>index.html</code> or a ≤1000-entry JSON listing; HTML is buffered and rewritten (<code>href=&quot;/x&quot;</code> → <code>href=&quot;./x&quot;</code>) so bundles resolve on the shared origin; everything else streams via <code>drive.createReadStream().pipe(res)</code> with strict single-range support (206/416), client-disconnect teardown, <code>X-Hyper-Key</code>, <code>Cache-Control: public, max-age=60</code>, <code>nosniff</code>.</li>
</ol>
<p><strong>Optional split data plane:</strong> setting <code>gatewayPort ≠ apiPort</code> starts <code>GatewayServer</code> on <code>0.0.0.0:9200</code>, sharing the same <code>HyperGateway</code> but serving only <code>/v1/hyper/*</code>, <code>/catalog.json</code>, <code>/health</code> with its own 600 req/min/IP limiter — <em>&quot;so heavy file traffic cannot starve management endpoints.&quot;</em></p>
<h2>3. App-origin gateway (Phase 1 canary)</h2>
<div class="mermaid-figure"><svg id="my-svg" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 2264.08px; background-color: transparent;" viewBox="0 0 2264.078125 289" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#my-svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:#552222;}#my-svg .error-text{fill:#552222;stroke:#552222;}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:#5a7196;stroke:#5a7196;}#my-svg .marker.cross{stroke:#5a7196;}#my-svg svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;}#my-svg p{margin:0;}#my-svg .label{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#333;}#my-svg .cluster-label text{fill:#333;}#my-svg .cluster-label span{color:#333;}#my-svg .cluster-label span p{background-color:transparent;}#my-svg .label text,#my-svg span{fill:#333;color:#333;}#my-svg .node rect,#my-svg .node circle,#my-svg .node ellipse,#my-svg .node polygon,#my-svg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#my-svg .rough-node .label text,#my-svg .node .label text,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-anchor:middle;}#my-svg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#my-svg .rough-node .label,#my-svg .node .label,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-align:center;}#my-svg .node.clickable{cursor:pointer;}#my-svg .root .anchor path{fill:#5a7196!important;stroke-width:0;stroke:#5a7196;}#my-svg .arrowheadPath{fill:#333333;}#my-svg .edgePath .path{stroke:#5a7196;stroke-width:1px;}#my-svg .flowchart-link{stroke:#5a7196;fill:none;}#my-svg .edgeLabel{background-color:#ffffff;text-align:center;}#my-svg .edgeLabel p{background-color:#ffffff;}#my-svg .edgeLabel rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#my-svg .cluster rect{fill:#f6f8fc;stroke:#aaaa33;stroke-width:1px;}#my-svg .cluster text{fill:#333;}#my-svg .cluster span{color:#333;}#my-svg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#my-svg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#my-svg rect.text{fill:none;stroke-width:0;}#my-svg .icon-shape,#my-svg .image-shape{background-color:#ffffff;text-align:center;}#my-svg .icon-shape p,#my-svg .image-shape p{background-color:#ffffff;padding:2px;}#my-svg .icon-shape .label rect,#my-svg .image-shape .label rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#my-svg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#my-svg .node .neo-node{stroke:#9370DB;}#my-svg [data-look="neo"].node rect,#my-svg [data-look="neo"].cluster rect,#my-svg [data-look="neo"].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].swimlane.cluster rect{filter:none;}#my-svg [data-look="neo"].node path{stroke:#9370DB;stroke-width:1px;}#my-svg [data-look="neo"].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node .neo-line path{stroke:#9370DB;filter:none;}#my-svg [data-look="neo"].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node circle .state-start{fill:#000000;}#my-svg [data-look="neo"].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="my-svg_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="my-svg_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"><g class="cluster" id="my-svg-GW" data-look="classic"><rect style="" x="1323.546875" y="34.5" width="932.53125" height="220"/><g class="cluster-label" transform="translate(1736.421875, 34.5)"><foreignObject width="106.78125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5;"><span class="nodeLabel"><p>HyperGateway</p></span></div>
<p></foreignObject></g></g><g class="cluster" id="my-svg-Plane" data-look="classic"><rect style="" x="388" y="46.5" width="885.546875" height="196"/><g class="cluster-label" transform="translate(669.0390625, 46.5)"><foreignObject width="323.46875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5;"><span class="nodeLabel"><p>GatewayServer data plane (:9200, loopback)</p></span></div></foreignObject></g></g></g><g class="edgePaths"><path d="M653.219,144.5L657.385,144.5C661.552,144.5,669.885,144.5,677.552,144.5C685.219,144.5,692.219,144.5,695.719,144.5L699.219,144.5" id="my-svg-L_Host_Ctx_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Host_Ctx_0" data-points="W3sieCI6NjUzLjIxODc1LCJ5IjoxNDQuNX0seyJ4Ijo2NzguMjE4NzUsInkiOjE0NC41fSx7IngiOjcwMy4yMTg3NSwieSI6MTQ0LjV9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M938.547,144.5L942.714,144.5C946.88,144.5,955.214,144.5,962.88,144.5C970.547,144.5,977.547,144.5,981.047,144.5L984.547,144.5" id="my-svg-L_Ctx_Lim_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Ctx_Lim_0" data-points="W3sieCI6OTM4LjU0Njg3NSwieSI6MTQ0LjV9LHsieCI6OTYzLjU0Njg3NSwieSI6MTQ0LjV9LHsieCI6OTg4LjU0Njg3NSwieSI6MTQ0LjV9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1248.547,144.5L1252.714,144.5C1256.88,144.5,1265.214,144.5,1273.547,144.5C1281.88,144.5,1290.214,144.5,1298.547,144.5C1306.88,144.5,1315.214,144.5,1322.88,144.5C1330.547,144.5,1337.547,144.5,1341.047,144.5L1344.547,144.5" id="my-svg-L_Lim_Adm_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Lim_Adm_0" data-points="W3sieCI6MTI0OC41NDY4NzUsInkiOjE0NC41fSx7IngiOjEyNzMuNTQ2ODc1LCJ5IjoxNDQuNX0seyJ4IjoxMjk4LjU0Njg3NSwieSI6MTQ0LjV9LHsieCI6MTMyMy41NDY4NzUsInkiOjE0NC41fSx7IngiOjEzNDguNTQ2ODc1LCJ5IjoxNDQuNX1d" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1608.547,144.5L1612.714,144.5C1616.88,144.5,1625.214,144.5,1632.88,144.5C1640.547,144.5,1647.547,144.5,1651.047,144.5L1654.547,144.5" id="my-svg-L_Adm_Drv_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Adm_Drv_0" data-points="W3sieCI6MTYwOC41NDY4NzUsInkiOjE0NC41fSx7IngiOjE2MzMuNTQ2ODc1LCJ5IjoxNDQuNX0seyJ4IjoxNjU4LjU0Njg3NSwieSI6MTQ0LjV9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1929.703,144.5L1933.87,144.5C1938.036,144.5,1946.37,144.5,1954.036,144.5C1961.703,144.5,1968.703,144.5,1972.203,144.5L1975.703,144.5" id="my-svg-L_Drv_Out_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Drv_Out_0" data-points="W3sieCI6MTkyOS43MDMxMjUsInkiOjE0NC41fSx7IngiOjE5NTQuNzAzMTI1LCJ5IjoxNDQuNX0seyJ4IjoxOTc5LjcwMzEyNSwieSI6MTQ0LjV9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M338,144.5L342.167,144.5C346.333,144.5,354.667,144.5,363,144.5C371.333,144.5,379.667,144.5,387.333,144.5C395,144.5,402,144.5,405.5,144.5L409,144.5" id="my-svg-L_Edge_Host_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Edge_Host_0" data-points="W3sieCI6MzM4LCJ5IjoxNDQuNX0seyJ4IjozNjMsInkiOjE0NC41fSx7IngiOjM4OCwieSI6MTQ0LjV9LHsieCI6NDEzLCJ5IjoxNDQuNX1d" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_Host_Ctx_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Ctx_Lim_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Lim_Adm_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Adm_Drv_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Drv_Out_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Edge_Host_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="root" transform="translate(0, 0)"><g class="clusters"><g class="cluster" id="my-svg-Edge" data-look="classic"><rect style="" x="8" y="8" width="330" height="273"/><g class="cluster-label" transform="translate(83.9765625, 8)"><foreignObject width="178.046875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5;"><span class="nodeLabel"><p>nginx wildcard TLS edge</p></span></div></foreignObject></g></g></g><g class="edgePaths"/><g class="edgeLabels"/><g class="nodes"><g class="node default" id="my-svg-flowchart-SNI-0" data-look="classic" transform="translate(173, 144.5)"><rect class="basic label-container" style="" x="-130" y="-99" width="260" height="198"/><g class="label" style="" transform="translate(-100, -84)"><rect/><foreignObject width="200" height="168"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>default_server → 421 unknown SNI<br />SNI==Host or 421<br />regex: exactly one z32 label<br />GET only, no bodies, gzip off</p></span></div></foreignObject></g></g></g></g><g class="node default" id="my-svg-flowchart-Host-1" data-look="classic" transform="translate(533.109375, 144.5)"><rect class="basic label-container" style="" x="-120.109375" y="-51" width="240.21875" height="102"/><g class="label" style="" transform="translate(-90.109375, -36)"><rect/><foreignObject width="180.21875" height="72"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>resolveHiveAppHost()<br />strict Host grammar,<br />z32 canonical re-encode</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Ctx-2" data-look="classic" transform="translate(820.8828125, 144.5)"><rect class="basic label-container" style="" x="-117.6640625" y="-39" width="235.328125" height="78"/><g class="label" style="" transform="translate(-87.6640625, -24)"><rect/><foreignObject width="175.328125" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>issueExactAppContext()<br />(WeakSet-verified)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Lim-3" data-look="classic" transform="translate(1118.546875, 144.5)"><rect class="basic label-container" style="" x="-130" y="-63" width="260" height="126"/><g class="label" style="" transform="translate(-100, -48)"><rect/><foreignObject width="200" height="96"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>per-IP rate, per-app concurrency,<br />egress budget, response TTL</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Adm-4" data-look="classic" transform="translate(1478.546875, 144.5)"><rect class="basic label-container" style="" x="-130" y="-75" width="260" height="150"/><g class="label" style="" transform="translate(-100, -60)"><rect/><foreignObject width="200" height="120"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>admitPublicHiveAppEntry()<br />allowlist + public tier +<br />persistent + availability +<br />NO blind/custody/shard markers</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Drv-5" data-look="classic" transform="translate(1794.125, 144.5)"><rect class="basic label-container" style="" x="-135.578125" y="-75" width="271.15625" height="150"/><g class="label" style="" transform="translate(-105.578125, -60)"><rect/><foreignObject width="211.15625" height="120"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>_acquireDrive()<br />storage-proof tuple vs live core<br />→ drive.checkout(proofVersion)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Out-6" data-look="classic" transform="translate(2105.390625, 144.5)"><rect class="basic label-container" style="" x="-125.6875" y="-51" width="251.375" height="102"/><g class="label" style="" transform="translate(-95.6875, -36)"><rect/><foreignObject width="191.375" height="72"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>exact-byte response<br />X-Hive-Byte-Mode: exact<br />no-store, no HTML rewrite</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="my-svg-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="my-svg-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs></svg></div></p>
<p>Key properties of the canary:</p>
<ul>
<li><strong>Fail-closed admission</strong> happens <em>before</em> any existence-revealing response: the key must be in the operator allowlist with an explicit <code>public</code> tier, <code>persistent</code> storage class, declared availability, and no blind/custody/shard markers. With <code>requireLifecycleDriveAuthority</code>, the seeded entry must carry a persisted storage-proof <code>driveVersion</code> matching the configured pin.</li>
<li><strong>Immutable reads</strong>: responses are served from <code>drive.checkout(proof.driveVersion)</code> with the lifecycle-owned blob snapshot — bytes cannot shift mid-response (<code>X-Hive-Drive-Version</code>).</li>
<li><strong>Exact bytes</strong>: no HTML rewriting, <code>X-Hive-Byte-Mode: exact</code>, <code>Cache-Control: no-store</code>, <code>Vary: Host</code>, <code>Origin-Agent-Cluster: ?1</code>, canonical <code>Link:</code> headers to <code>hive://&lt;key&gt;/&lt;path&gt;</code>.</li>
<li><strong>Edge discipline</strong>: TLS default server → 421 for unknown SNI; SNI==Host enforcement; app origins never inherit compatibility CORS; no request bodies; forwarded-SNI attestation header verified when <code>gatewayRequireForwardedSNI</code>.</li>
<li><code>/.well-known/hiverelay-app.json</code> returns a bounded descriptor (<code>hiverelay-public-app-v1</code>) with the honest limitation: <em>&quot;HTTPS transport does not prove Hypercore content provenance.&quot;</em></li>
</ul>
<h2>4. Trust boundaries</h2>
<div class="mermaid-figure"><svg id="my-svg" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 857.586px; background-color: transparent;" viewBox="0 0 857.5859375 630" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#my-svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:#552222;}#my-svg .error-text{fill:#552222;stroke:#552222;}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:#5a7196;stroke:#5a7196;}#my-svg .marker.cross{stroke:#5a7196;}#my-svg svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;}#my-svg p{margin:0;}#my-svg .label{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#333;}#my-svg .cluster-label text{fill:#333;}#my-svg .cluster-label span{color:#333;}#my-svg .cluster-label span p{background-color:transparent;}#my-svg .label text,#my-svg span{fill:#333;color:#333;}#my-svg .node rect,#my-svg .node circle,#my-svg .node ellipse,#my-svg .node polygon,#my-svg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#my-svg .rough-node .label text,#my-svg .node .label text,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-anchor:middle;}#my-svg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#my-svg .rough-node .label,#my-svg .node .label,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-align:center;}#my-svg .node.clickable{cursor:pointer;}#my-svg .root .anchor path{fill:#5a7196!important;stroke-width:0;stroke:#5a7196;}#my-svg .arrowheadPath{fill:#333333;}#my-svg .edgePath .path{stroke:#5a7196;stroke-width:1px;}#my-svg .flowchart-link{stroke:#5a7196;fill:none;}#my-svg .edgeLabel{background-color:#ffffff;text-align:center;}#my-svg .edgeLabel p{background-color:#ffffff;}#my-svg .edgeLabel rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#my-svg .cluster rect{fill:#f6f8fc;stroke:#aaaa33;stroke-width:1px;}#my-svg .cluster text{fill:#333;}#my-svg .cluster span{color:#333;}#my-svg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#my-svg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#my-svg rect.text{fill:none;stroke-width:0;}#my-svg .icon-shape,#my-svg .image-shape{background-color:#ffffff;text-align:center;}#my-svg .icon-shape p,#my-svg .image-shape p{background-color:#ffffff;padding:2px;}#my-svg .icon-shape .label rect,#my-svg .image-shape .label rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#my-svg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#my-svg .node .neo-node{stroke:#9370DB;}#my-svg [data-look="neo"].node rect,#my-svg [data-look="neo"].cluster rect,#my-svg [data-look="neo"].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].swimlane.cluster rect{filter:none;}#my-svg [data-look="neo"].node path{stroke:#9370DB;stroke-width:1px;}#my-svg [data-look="neo"].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node .neo-line path{stroke:#9370DB;filter:none;}#my-svg [data-look="neo"].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node circle .state-start{fill:#000000;}#my-svg [data-look="neo"].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="my-svg_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="my-svg_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M138,62L138,68.167C138,74.333,138,86.667,138,98.333C138,110,138,121,138,126.5L138,132" id="my-svg-L_Internet_Nginx_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Internet_Nginx_0" data-points="W3sieCI6MTM4LCJ5Ijo2Mn0seyJ4IjoxMzgsInkiOjk5fSx7IngiOjEzOCwieSI6MTM2fV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M138,214L138,220.167C138,226.333,138,238.667,138,254.333C138,270,138,289,138,298.5L138,308" id="my-svg-L_Nginx_DP_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Nginx_DP_0" data-points="W3sieCI6MTM4LCJ5IjoyMTR9LHsieCI6MTM4LCJ5IjoyNTF9LHsieCI6MTM4LCJ5IjozMTJ9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M409.586,202L409.586,210.167C409.586,218.333,409.586,234.667,409.586,248.333C409.586,262,409.586,273,409.586,278.5L409.586,284" id="my-svg-L_Clients2_CP_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Clients2_CP_0" data-points="W3sieCI6NDA5LjU4NTkzNzUsInkiOjIwMn0seyJ4Ijo0MDkuNTg1OTM3NSwieSI6MjUxfSx7IngiOjQwOS41ODU5Mzc1LCJ5IjoyODh9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M138,366L138,374.167C138,382.333,138,398.667,164.821,413.154C191.642,427.641,245.285,440.282,272.106,446.602L298.927,452.923" id="my-svg-L_DP_GW2_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_DP_GW2_0" data-points="W3sieCI6MTM4LCJ5IjozNjZ9LHsieCI6MTM4LCJ5Ijo0MTV9LHsieCI6MzAyLjgyMDMxMjUsInkiOjQ1My44NDAzNzYyNjIxMTc4fV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M409.586,518L409.586,522.167C409.586,526.333,409.586,534.667,409.586,542.333C409.586,550,409.586,557,409.586,560.5L409.586,564" id="my-svg-L_GW2_Store_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GW2_Store_0" data-points="W3sieCI6NDA5LjU4NTkzNzUsInkiOjUxOH0seyJ4Ijo0MDkuNTg1OTM3NSwieSI6NTQzfSx7IngiOjQwOS41ODU5Mzc1LCJ5Ijo1Njh9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M409.586,390L409.586,394.167C409.586,398.333,409.586,406.667,409.586,414.333C409.586,422,409.586,429,409.586,432.5L409.586,436" id="my-svg-L_CP_GW2_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CP_GW2_0" data-points="W3sieCI6NDA5LjU4NTkzNzUsInkiOjM5MH0seyJ4Ijo0MDkuNTg1OTM3NSwieSI6NDE1fSx7IngiOjQwOS41ODU5Mzc1LCJ5Ijo0NDB9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M719.586,378L719.586,384.167C719.586,390.333,719.586,402.667,686.366,415.692C653.147,428.716,586.708,442.433,553.488,449.291L520.269,456.149" id="my-svg-L_Operator_GW2_0" class="edge-thickness-normal edge-pattern-dotted edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Operator_GW2_0" data-points="W3sieCI6NzE5LjU4NTkzNzUsInkiOjM3OH0seyJ4Ijo3MTkuNTg1OTM3NSwieSI6NDE1fSx7IngiOjUxNi4zNTE1NjI1LCJ5Ijo0NTYuOTU4MDY0NTE2MTI5fV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel" transform="translate(138, 99)"><g class="label" data-id="L_Internet_Nginx_0" transform="translate(-14.2421875, -12)"><foreignObject width="28.484375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>TLS</p></span></div>
<p></foreignObject></g></g><g class="edgeLabel" transform="translate(138, 251)"><g class="label" data-id="L_Nginx_DP_0" transform="translate(-50.4921875, -12)"><foreignObject width="100.984375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>loopback only</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Clients2_CP_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_DP_GW2_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GW2_Store_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_CP_GW2_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Operator_GW2_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="my-svg-flowchart-Internet-0" data-look="classic" transform="translate(138, 35)"><rect class="basic label-container" style="" x="-83.9765625" y="-27" width="167.953125" height="54"/><g class="label" style="" transform="translate(-53.9765625, -12)"><rect/><foreignObject width="107.953125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Internet clients</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Nginx-1" data-look="classic" transform="translate(138, 175)"><rect class="basic label-container" style="" x="-130" y="-39" width="260" height="78"/><g class="label" style="" transform="translate(-100, -24)"><rect/><foreignObject width="200" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>nginx edge (terminates TLS)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-DP-3" data-look="classic" transform="translate(138, 339)"><rect class="basic label-container" style="" x="-91.5859375" y="-27" width="183.171875" height="54"/><g class="label" style="" transform="translate(-61.5859375, -12)"><rect/><foreignObject width="123.171875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>data plane :9200</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Clients2-4" data-look="classic" transform="translate(409.5859375, 175)"><rect class="basic label-container" style="" x="-85.328125" y="-27" width="170.65625" height="54"/><g class="label" style="" transform="translate(-55.328125, -12)"><rect/><foreignObject width="110.65625" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>LAN/API clients</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-CP-5" data-look="classic" transform="translate(409.5859375, 339)"><rect class="basic label-container" style="" x="-130" y="-51" width="260" height="102"/><g class="label" style="" transform="translate(-100, -36)"><rect/><foreignObject width="200" height="72"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>control plane :9100<br />(mgmt behind API key/loopback)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-GW2-7" data-look="classic" transform="translate(409.5859375, 479)"><rect class="basic label-container" style="" x="-106.765625" y="-39" width="213.53125" height="78"/><g class="label" style="" transform="translate(-76.765625, -24)"><rect/><foreignObject width="153.53125" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>HyperGateway<br />fail-closed admission</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Store-9" data-look="classic" transform="translate(409.5859375, 595)"><rect class="basic label-container" style="" x="-124.484375" y="-27" width="248.96875" height="54"/><g class="label" style="" transform="translate(-94.484375, -12)"><rect/><foreignObject width="188.96875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Corestore (seeded drives)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Operator-12" data-look="classic" transform="translate(719.5859375, 339)"><rect class="basic label-container" style="" x="-130" y="-39" width="260" height="78"/><g class="label" style="" transform="translate(-100, -24)"><rect/><foreignObject width="200" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Operator allowlist + storage proofs</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="my-svg-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="my-svg-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs></svg></div></p>
<ul>
<li>The relay process <strong>never terminates TLS</strong>; Node binds loopback only in the hardened topology.</li>
<li>Management routes live only on the control plane behind bearer/loopback auth (loopback bypass is disabled when <code>trustProxy</code> is on).</li>
<li>Blind/custody content is structurally unreachable: the <code>blind</code> flag and custody/shard markers are hard gates evaluated before existence is revealed.</li>
</ul>
<h2>5. Route inventory</h2>
<table>
<thead>
<tr>
<th>Route</th>
<th>Plane</th>
<th>Auth</th>
<th>Notes</th>
</tr>
</thead>
<tbody><tr>
<td><code>GET/HEAD /v1/hyper/:key/*</code></td>
<td>both</td>
<td>none (public)</td>
<td>blind→403, tier→403, PolicyGuard, ranges</td>
</tr>
<tr>
<td><code>GET /catalog.json</code></td>
<td>both</td>
<td>none (public)</td>
<td>redacted custody entries; slimmer form on data plane</td>
</tr>
<tr>
<td><code>GET /.well-known/hiverelay.json</code>, <code>/api/capabilities</code></td>
<td>control</td>
<td>none</td>
<td>signed capability doc</td>
</tr>
<tr>
<td><code>GET /api/gateway</code></td>
<td>control</td>
<td>none</td>
<td>sanitized counters only</td>
</tr>
<tr>
<td><code>GET /health</code>, <code>/</code></td>
<td>data</td>
<td>none</td>
<td>liveness</td>
</tr>
<tr>
<td><code>GET https://&lt;z32&gt;.&lt;suffix&gt;/*</code> (canary)</td>
<td>data</td>
<td>none</td>
<td>operator allowlist + storage-proof admission</td>
</tr>
<tr>
<td><code>/.well-known/hiverelay-app.json</code> (canary)</td>
<td>data</td>
<td>none</td>
<td>generated, bounded</td>
</tr>
<tr>
<td><code>POST /api/manage/*</code>, seed/unseed, wizard</td>
<td>control</td>
<td><strong>operator</strong></td>
<td>never on the data plane</td>
</tr>
</tbody></table>
<h2>6. Streaming, ranges, limits</h2>
<ul>
<li>Non-HTML bodies stream with Node backpressure; client disconnect destroys the drive stream; the canary adds <code>ExactLengthTransform</code> that hard-fails on byte-count drift.</li>
<li>Single ranges only; malformed/unsatisfiable → 416 (canary is stricter than legacy&#39;s RFC-allowed ignore).</li>
<li>Limits (canary in parentheses): drive op timeout 30 s; empty-drive wait 20 s; LRU 20 drives; listing ≤1000 entries (and ≤1 MiB payload); max response (64 MiB/1 GiB ceiling); egress budget (256 MiB per IP×app per 60 s → 429); concurrency (256 global / 32 per app → 503); response lifetime (15 min); HTTP hardening (header caps, 10 s headersTimeout, CONNECT/upgrade rejected).</li>
<li>Canary production tuple is frozen: <code>PUBLIC_T1_GATEWAY_FINITE_LIMITS</code> = {64 MiB, 4 MiB, 256 MiB, 60 s, 15 min}.</li>
</ul>
<h2>7. TLS / deployment</h2>
<ul>
<li><strong>API/control plane</strong>: nginx on :443 with certbot exact-host cert → loopback 9100 (see <code>docs/REVERSE-PROXY.md</code>).</li>
<li><strong>App plane (canary)</strong>: per-operator <strong>wildcard cert</strong> for <code>*.&lt;hiveAppHostSuffix&gt;</code>, ACME <strong>DNS-01</strong> only (HTTP-01 can&#39;t issue wildcards), credentials scoped to <code>_acme-challenge</code>; two vhosts (API vs app wildcard) must never cross-route.</li>
<li>Umbrel/StartOS packaging carries <strong>no gateway config</strong> — app-gateway is out of Phase-1 packaging scope by spec.</li>
<li>No self-signed or embedded ACME in the relay; publisher-owned domains are Phase 3; ACME automation Phase 5.</li>
</ul>
<h2>8. Composition with the rest of the release</h2>
<div class="mermaid-figure"><svg id="my-svg" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1182.72px; background-color: transparent;" viewBox="0 0 1182.71875 385" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#my-svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:#552222;}#my-svg .error-text{fill:#552222;stroke:#552222;}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:#5a7196;stroke:#5a7196;}#my-svg .marker.cross{stroke:#5a7196;}#my-svg svg{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;}#my-svg p{margin:0;}#my-svg .label{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#333;}#my-svg .cluster-label text{fill:#333;}#my-svg .cluster-label span{color:#333;}#my-svg .cluster-label span p{background-color:transparent;}#my-svg .label text,#my-svg span{fill:#333;color:#333;}#my-svg .node rect,#my-svg .node circle,#my-svg .node ellipse,#my-svg .node polygon,#my-svg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#my-svg .rough-node .label text,#my-svg .node .label text,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-anchor:middle;}#my-svg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#my-svg .rough-node .label,#my-svg .node .label,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-align:center;}#my-svg .node.clickable{cursor:pointer;}#my-svg .root .anchor path{fill:#5a7196!important;stroke-width:0;stroke:#5a7196;}#my-svg .arrowheadPath{fill:#333333;}#my-svg .edgePath .path{stroke:#5a7196;stroke-width:1px;}#my-svg .flowchart-link{stroke:#5a7196;fill:none;}#my-svg .edgeLabel{background-color:#ffffff;text-align:center;}#my-svg .edgeLabel p{background-color:#ffffff;}#my-svg .edgeLabel rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#my-svg .cluster rect{fill:#f6f8fc;stroke:#aaaa33;stroke-width:1px;}#my-svg .cluster text{fill:#333;}#my-svg .cluster span{color:#333;}#my-svg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#my-svg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#my-svg rect.text{fill:none;stroke-width:0;}#my-svg .icon-shape,#my-svg .image-shape{background-color:#ffffff;text-align:center;}#my-svg .icon-shape p,#my-svg .image-shape p{background-color:#ffffff;padding:2px;}#my-svg .icon-shape .label rect,#my-svg .image-shape .label rect{opacity:0.5;background-color:#ffffff;fill:#ffffff;}#my-svg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#my-svg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#my-svg .node .neo-node{stroke:#9370DB;}#my-svg [data-look="neo"].node rect,#my-svg [data-look="neo"].cluster rect,#my-svg [data-look="neo"].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].swimlane.cluster rect{filter:none;}#my-svg [data-look="neo"].node path{stroke:#9370DB;stroke-width:1px;}#my-svg [data-look="neo"].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node .neo-line path{stroke:#9370DB;filter:none;}#my-svg [data-look="neo"].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node circle .state-start{fill:#000000;}#my-svg [data-look="neo"].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="my-svg_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="my-svg_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M246.06,55L262.834,49.167C279.607,43.333,313.155,31.667,366.075,25.833C418.995,20,491.286,20,553.266,20C615.245,20,666.911,20,708.346,44.604C749.78,69.207,780.981,118.415,796.582,143.018L812.183,167.622" id="my-svg-L_CapDoc_GW_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CapDoc_GW_0" data-points="W3sieCI6MjQ2LjA1OTY0OTQ5MzI0MzIzLCJ5Ijo1NX0seyJ4IjozNDYuNzAzMTI1LCJ5IjoyMH0seyJ4Ijo1NjMuNTc4MTI1LCJ5IjoyMH0seyJ4Ijo3MTguNTc4MTI1LCJ5IjoyMH0seyJ4Ijo4MTQuMzI1MDA4Nzc4MDg5OSwieSI6MTcxfV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M169.685,133L199.188,165.167C228.691,197.333,287.697,261.667,331.013,293.833C374.328,326,401.953,326,415.766,326L429.578,326" id="my-svg-L_CapDoc_Tor_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CapDoc_Tor_0" data-points="W3sieCI6MTY5LjY4NDYzNzY2MTYzNzk0LCJ5IjoxMzN9LHsieCI6MzQ2LjcwMzEyNSwieSI6MzI2fSx7IngiOjQzMy41NzgxMjUsInkiOjMyNn1d" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M259.828,94L274.307,94C288.786,94,317.745,94,351.238,94C384.732,94,422.76,94,441.775,94L460.789,94" id="my-svg-L_CapDoc_IR_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_CapDoc_IR_0" data-points="W3sieCI6MjU5LjgyODEyNSwieSI6OTR9LHsieCI6MzQ2LjcwMzEyNSwieSI6OTR9LHsieCI6NDY0Ljc4OTA2MjUsInkiOjk0fV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M680.109,198L686.521,198C692.932,198,705.755,198,715.667,198C725.578,198,732.578,198,736.078,198L739.578,198" id="my-svg-L_Catalog_GW_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Catalog_GW_0" data-points="W3sieCI6NjgwLjEwOTM3NSwieSI6MTk4fSx7IngiOjcxOC41NzgxMjUsInkiOjE5OH0seyJ4Ijo3NDMuNTc4MTI1LCJ5IjoxOTh9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M919.313,198L923.479,198C927.646,198,935.979,198,943.646,198C951.313,198,958.313,198,961.813,198L965.313,198" id="my-svg-L_GW_Store_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_GW_Store_0" data-points="W3sieCI6OTE5LjMxMjUsInkiOjE5OH0seyJ4Ijo5NDQuMzEyNSwieSI6MTk4fSx7IngiOjk2OS4zMTI1LCJ5IjoxOTh9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M693.578,326L697.745,326C701.911,326,710.245,326,728.814,309.667C747.383,293.333,776.187,260.667,790.59,244.334L804.992,228" id="my-svg-L_Tor_GW_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Tor_GW_0" data-points="W3sieCI6NjkzLjU3ODEyNSwieSI6MzI2fSx7IngiOjcxOC41NzgxMjUsInkiOjMyNn0seyJ4Ijo4MDcuNjM3MzkwMTM2NzE4OCwieSI6MjI1fV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel" transform="translate(563.578125, 20)"><g class="label" data-id="L_CapDoc_GW_0" transform="translate(-40.796875, -12)"><foreignObject width="81.59375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>gatewayUrl</p></span></div>
<p></foreignObject></g></g><g class="edgeLabel" transform="translate(346.703125, 326)"><g class="label" data-id="L_CapDoc_Tor_0" transform="translate(-61.875, -12)"><foreignObject width="123.75" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>onionGatewayUrl</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(346.703125, 94)"><g class="label" data-id="L_CapDoc_IR_0" transform="translate(-40.2890625, -12)"><foreignObject width="80.578125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>indexRoom</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Catalog_GW_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_GW_Store_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Tor_GW_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="my-svg-flowchart-CapDoc-0" data-look="classic" transform="translate(133.9140625, 94)"><rect class="basic label-container" style="" x="-125.9140625" y="-39" width="251.828125" height="78"/><g class="label" style="" transform="translate(-95.9140625, -24)"><rect/><foreignObject width="191.828125" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Signed capability doc<br />/.well-known/hiverelay.json</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-GW-2" data-look="classic" transform="translate(831.4453125, 198)"><rect class="basic label-container" style="" x="-87.8671875" y="-27" width="175.734375" height="54"/><g class="label" style="" transform="translate(-57.8671875, -12)"><rect/><foreignObject width="115.734375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>HTTPS gateway</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Tor-4" data-look="classic" transform="translate(563.578125, 326)"><rect class="basic label-container" style="" x="-130" y="-51" width="260" height="102"/><g class="label" style="" transform="translate(-100, -36)"><rect/><foreignObject width="200" height="72"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Tor read plane<br />(onion vport 80 → gateway port)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-IR-6" data-look="classic" transform="translate(563.578125, 94)"><rect class="basic label-container" style="" x="-98.7890625" y="-27" width="197.578125" height="54"/><g class="label" style="" transform="translate(-68.7890625, -12)"><rect/><foreignObject width="137.578125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>index room sidecar</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Catalog-7" data-look="classic" transform="translate(563.578125, 198)"><rect class="basic label-container" style="" x="-116.53125" y="-27" width="233.0625" height="54"/><g class="label" style="" transform="translate(-86.53125, -12)"><rect/><foreignObject width="173.0625" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>/catalog.json (redacted)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Store-10" data-look="classic" transform="translate(1072.015625, 198)"><rect class="basic label-container" style="" x="-102.703125" y="-27" width="205.40625" height="54"/><g class="label" style="" transform="translate(-72.703125, -12)"><rect/><foreignObject width="145.40625" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>seeded Hyperdrives</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="my-svg-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="my-svg-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs></svg></div></p>
<ul>
<li>The capability doc advertises <code>gatewayUrl</code> (clearnet base), <code>onionGatewayUrl</code> (Tor ingress), and <code>indexRoom</code>; the Tor and nginx edges are <strong>two ingresses to the same read plane</strong> (legacy path mode vs per-app origins).</li>
<li>Catalog and gateway share one trust policy block (<code>gatewayPublicOnlyPrivacyTier</code>, signed-catalog knobs).</li>
<li>Phase 2 of the canary spec adds gateway profile/byte-mode advertisement to the capability doc (<code>hiverelay-gateway-advertisement-v1</code>).</li>
</ul>
<h2>9. Honest limits</h2>
<ol>
<li>The gateway is a <strong>read plane for declared-public content only</strong> — privacy for content comes from blind sealing/custody, not from this layer.</li>
<li>Path-mode HTML rewriting is a convenience for shared origins; exact-byte app origins are the strong form (canary).</li>
<li>The canary lane is <strong>staging-only, unmerged</strong>; live-fleet use is gated on its readiness checklist.</li>
<li>HTTPS responses do not prove Hypercore provenance — clients that need integrity must verify content hashes out-of-band (or consume the drive over P2P).</li>
</ol>

<hr>
<p style="color:#7a869e;font-size:.8rem">HiveRelay release documentation — rendered 2026-07-18. Source: <code>docs/HTTPS-GATEWAY</code> in the hiverelay repository.</p>
</div>
</body>
</html>