cocoon compatibility: rfc 9421 space signatures + dual-dialect client #19

Closed scarnecchia.net
targeting main from spaces-alpha-20261022
Closed opened by and assigned to scarnecchia.net
targeting main from spaces-alpha-20261022

The 2026-10-19 incident (60x getSpaceCredential -> 401 BadSpaceSignature against a cocoon PDS) was the August-alpha wire dialect meeting cocoon v0.13+'s evolved protocol. This adds the cocoon dialect alongside the alpha one, selected per server origin via /xrpc/_health with a one-shot BadSpaceSignature fallback:

  • httpsig.ts: the reference http-signature module lifted verbatim, adapted to a WebCrypto SpaceSigner; pinned by the cocoon test vectors and the negative cases from cocoon's httpsig_test.go
  • space-key.ts: one WebCrypto P-256 key per credential serving both dialects (RFC 9421 signer + DPoP adapter replacing JoseKey)
  • dialect.ts: per-dialect wire shapes (exchange headers, Atproto-Space reads with per-host audiences, createSpace/putMember/listSpaces shapes, repoRev normalization)
  • client.ts: dialect probe + cache, exchange fallback on exact BadSpaceSignature, read-path 401 re-probe heal, dialect-named errors
  • fake.ts: a cocoon mode that really verifies signatures, audiences and single-use delegations offline
  • explain.ts + provider classifier: BadSpaceSignature-class failures read as update-the-app, never sign-out-and-back-in
  • spaces-spike.ts: dialect-aware; 22/22 against a local cocoon
Commits 0