Summary #
- Moves Ziran's Spaces client to the 2026-10-22 spaces alpha (
0.0.0-spaces-alpha-20261022141228) in one step: dependency pins, the client wire (credential exchange, presentation, MACs, deletion), the in-memory server double, tests, tooling, and docs. - The August DPoP dialect is removed (it cannot talk to an Oct-22 reference PDS); the surviving
alpha/cocoonsplit now selects management request shapes only.
Changes #
- Dependencies:
@atproto/space,@atproto/crypto,@atproto/oauth-scopespinned to the Oct-22 snapshot; OAuth clients intentionally stay on 2026-08-18.@atproto/lex-cbor/@atproto/lex-datavendored underpatches/— the Oct-22^0.0.0-spaces-alpha-…ranges are also satisfied (and preferred) by ancient broken0.0.0publishes with unrewrittenworkspace:*manifests; the links carry the real snapshot. New@noble/hashessubpath mappings for the MAC module. - Exchange (client.ts): unsigned body POST
{space, credentialKid, delegationToken}; one fresh-mint retry on 400InvalidDelegationToken;SpaceNotFound/SpaceDeleted/UserNotAuthorizedsurface by name. - Presentation (httpsig.ts):
Authorization: Atproto-Space-Credential+ audience DID + RFC 9421 signature under labelatproto-space-credentialwith mandatorytag, covering exactly("authorization" "atproto-space-audience"), padded base64,format: 'compact'+ malleable-S verify. Vectors regenerated from the pinned upstream signer. - MACs (new mac.ts):
#atproto_kemdiscovery, RFC 9180 DHKEM(P-256) encapsulation on noble curves/hashes (byte-identical to upstream, pinned by test), commit/record MAC verification, Want-Mac/Mac header pair. Client sends a fresh ephemeral key share per request, verifies responses, re-resolves the KEM key once on failure. Commits are{ver, repo, space, rev, data}(hash→data);getReporeturns a STAR archive + MAC + shared secret for caller-ownedverifyRepoStarFull. - Deletion (provider.ts): the
SpaceDeletederror name purges the space from the registry at every call site (poll, flush, invite, rename) — local tiles kept, idempotent; message-text deletion matching narrowed to not-found only; a deleted inbox resets and is recreated.classifySpaceErrorgains thedeletedkind. - Fake network (fake.ts): genuinely verifies the new protocol — publishes
#atproto_kemin DID docs, enforces the exchange validation order and the credential scheme/tag, requires Want-Mac on the MAC methods, computes real response MACs, emits Oct-22 commits with real CIDv1 record CIDs, answersSpaceDeletedon every space endpoint after deletion. Thecocoonflag now selects management shapes only. - Pre-existing bugs fixed en route (found by the new gate):
relay/main.tsshutdown now closes upgraded WebSocket connections (Deno.serve.shutdown()only retires the listener, which kept the test process alive forever — pre-existing, surfaced by the full-suite run);patches/undicivendors undici 8.10.0 with a guardedmarkAsUncloneable(undici ≥ 8.0.3 calls it unconditionally at load; this deno lacks the export — crashede2e.test.tsat boot, also pre-existing). - Comments (session-fetch.ts): the header keeps the operational cause and routing rule; the incident history stays in SYNC-SPACES.md.
Validation #
deno install— clean (the lex-cbor/lex-data trap is handled by the vendored links).deno checkover main.ts, the spaces module, provider, spike, live smoke, CLI — clean.deno task test:spaces— all suites green (mac vectors cross-checked against the pinned upstream primitives; httpsig vectors regenerated from the reference signer).deno task test:sync— exit 0, 512 checks pass, full chain terminates.- Independent read-only review pass (wire conformance vs
node_modules/@atproto/space/dist, scope discipline, test fidelity): verdict SHIP; its three actionable low findings fixed, the rest rebutted with evidence in the commit message. A second comment-only review pass (writing-code-comments+ STE) landed one header trim. - Live spike + live smoke: Not run —
pds.ziran.spacestill serves the pre-Oct-22 protocol; upgrade it first (deploy/pds/README.mdhas the procedure), then run the 25-check spike and the provider smoke against it.
Review notes #
- Operator action after merge: redeploy the reference PDS on the floating
pds-spaces-alphatag (migrations009-space-deletion-and-macs+005-space-commit-datarun automatically; akem_keyfile appears beside each actor-storekey— include it in backups; the KEM backfill publishesatproto_kemto PLC). Until then the app against that PDS shows exchange refusals (400 InvalidToken) — that is the old server, not a regression. - Cocoon interop gap: cocoon servers on the Oct-1 read shape reject the new scheme until cocoon ships Oct-22 — accepted, no fallback dialect (documented in SPACES.md/SYNC-SPACES.md).
- Trust posture unchanged: commit/record MACs verified per response; no LtHash running-set accumulator (documented in SPACES.md).
patches/undiciis a full vendored copy (repo's establishedpatches/pattern; behavior-identical on real Node ≥ 21 — the guard falls back to a no-op only where the export is missing).