Item 7: live IPFS round-trip harness (Helia test node)
Closes the "no live IPFS round-trip" gap: a throwaway verification script
(scripts/ipfs-roundtrip.mjs) that drives the real kuboBlockPut transport through
the real ipfsBlockProducer seam against a genuine IPFS node — Helia (js-ipfs).
A minimal HTTP shim implements just Kubo's POST /api/v0/block/put (the endpoint
kuboBlockPut targets), backed by a real Helia blockstore that computes/verifies
each block's CID itself (multiformats: codec + sha2-256 + CIDv1/base32), never
trusting the client. The script pushes the same blocks publish()'s pushToMirror
does (blobs raw + manifest dag-cbor, incl. a 300 KiB block past IPFS's 256 KiB
chunk threshold) and reads every block back out of Helia, establishing:
- our @atcute/cid base32 CIDv1 strings exactly equal an independent IPFS impl's
CIDs for both raw and dag-cbor (no KuboCidMismatchError on any push);
- every block is byte-exact retrievable under exactly our CID and re-hashes to
it (the gateway's fail-closed check);
- the CID-mismatch fail-safe fires over live HTTP (not just fake-fetch units):
a block whose declared CID != its bytes is rejected, so no dead ipfs: hint.
Helia is a full IPFS implementation, so this is real end-to-end verification of
the transport, not a proxy for some other node.
Deps (helia, libp2p, multiformats) are intentionally NOT committed — opt-in tool,
not shipped code; header documents the one-time install.
H1 Chunk 2: delete the apex /at/ route, resolve derived per-site origins
Every per-site origin is now DID-addressed via the derived label
`<siteRkey>--<did-suffix>.<apex>` (§11.3); the path-based apex /at/
identity route is deleted outright, along with the gateway
handle-resolution stack it fed.
- request.ts: `case "siteOrigin"` now decodes the label with
`parseSiteOriginLabel` → `{by:"identity", did, siteRkey}`; the bare
apex serves only the §13 RASL mirror or 404s (no /at/).
- types.ts: `SiteAddress.identity` → `did` (a handle reaching the
resolver is now unrepresentable).
- resolve.ts: `case "identity"` uses `site.did` directly; deleted
`resolveIdentityDid`, the handle branch, and the `handles` param.
- Deleted the whole handle stack: handle-resolver.ts (+ its test),
the http.ts `handles` option and `dnsTxtResolver`/
`createAtprotoDidFetcher` transports, dispatch `GatewayDeps.handles`,
the server index re-exports, and main.ts `HttpHandleResolver`
(keeping `didDocuments` for verification-key resolution).
- Deleted APEX_SANDBOX_CSP (gateway headers/index + dispatch wiring):
every per-site origin now has its own browser origin, so the
`by === "identity"` sandbox gate would have silently sandboxed
exactly the origins we un-sandbox. Kept the §12 cache-control
downgrade.
- publisher-assets.ts: apex /at/… now 302s to /publish/ like any junk
apex path.
- exit-routes.ts: `atIdentity` → `siteOrigin: string | null` derived
via `siteOriginLabel`; the handle-accepting `identity?` input is
gone (a handle can't produce a derived origin).
- Scripts + stale comments updated to the derived origin.
Build + typecheck + tests green.
H1 Chunk 2: delete the apex /at/ route, resolve derived per-site origins
Every per-site origin is now DID-addressed via the derived label
`<siteRkey>--<did-suffix>.<apex>` (§11.3); the path-based apex /at/
identity route is deleted outright, along with the gateway
handle-resolution stack it fed.
- request.ts: `case "siteOrigin"` now decodes the label with
`parseSiteOriginLabel` → `{by:"identity", did, siteRkey}`; the bare
apex serves only the §13 RASL mirror or 404s (no /at/).
- types.ts: `SiteAddress.identity` → `did` (a handle reaching the
resolver is now unrepresentable).
- resolve.ts: `case "identity"` uses `site.did` directly; deleted
`resolveIdentityDid`, the handle branch, and the `handles` param.
- Deleted the whole handle stack: handle-resolver.ts (+ its test),
the http.ts `handles` option and `dnsTxtResolver`/
`createAtprotoDidFetcher` transports, dispatch `GatewayDeps.handles`,
the server index re-exports, and main.ts `HttpHandleResolver`
(keeping `didDocuments` for verification-key resolution).
- Deleted APEX_SANDBOX_CSP (gateway headers/index + dispatch wiring):
every per-site origin now has its own browser origin, so the
`by === "identity"` sandbox gate would have silently sandboxed
exactly the origins we un-sandbox. Kept the §12 cache-control
downgrade.
- publisher-assets.ts: apex /at/… now 302s to /publish/ like any junk
apex path.
- exit-routes.ts: `atIdentity` → `siteOrigin: string | null` derived
via `siteOriginLabel`; the handle-accepting `identity?` input is
gone (a handle can't produce a derived origin).
- Scripts + stale comments updated to the derived origin.
Build + typecheck + tests green.
H1 Chunk 2: delete the apex /at/ route, resolve derived per-site origins
Every per-site origin is now DID-addressed via the derived label
`<siteRkey>--<did-suffix>.<apex>` (§11.3); the path-based apex /at/
identity route is deleted outright, along with the gateway
handle-resolution stack it fed.
- request.ts: `case "siteOrigin"` now decodes the label with
`parseSiteOriginLabel` → `{by:"identity", did, siteRkey}`; the bare
apex serves only the §13 RASL mirror or 404s (no /at/).
- types.ts: `SiteAddress.identity` → `did` (a handle reaching the
resolver is now unrepresentable).
- resolve.ts: `case "identity"` uses `site.did` directly; deleted
`resolveIdentityDid`, the handle branch, and the `handles` param.
- Deleted the whole handle stack: handle-resolver.ts (+ its test),
the http.ts `handles` option and `dnsTxtResolver`/
`createAtprotoDidFetcher` transports, dispatch `GatewayDeps.handles`,
the server index re-exports, and main.ts `HttpHandleResolver`
(keeping `didDocuments` for verification-key resolution).
- Deleted APEX_SANDBOX_CSP (gateway headers/index + dispatch wiring):
every per-site origin now has its own browser origin, so the
`by === "identity"` sandbox gate would have silently sandboxed
exactly the origins we un-sandbox. Kept the §12 cache-control
downgrade.
- publisher-assets.ts: apex /at/… now 302s to /publish/ like any junk
apex path.
- exit-routes.ts: `atIdentity` → `siteOrigin: string | null` derived
via `siteOriginLabel`; the handle-accepting `identity?` input is
gone (a handle can't produce a derived origin).
- Scripts + stale comments updated to the derived origin.
Build + typecheck + tests green.