Skip to content

Mailbox grant wire types (GER-1965/1966/1967) - #44

Merged
germ-mark merged 3 commits into
mainfrom
feat/mailbox-grant-wire-types
Aug 4, 2026
Merged

Mailbox grant wire types (GER-1965/1966/1967)#44
germ-mark merged 3 commits into
mainfrom
feat/mailbox-grant-wire-types

Conversation

@germ-mark

Copy link
Copy Markdown
Contributor

Client side of mailbox v2, in three commits:

  • GER-1965: swift-cbor pinned at CoreAppLogic's revision + a DeterministicCbor seam documenting the conventions (short string keys — swift-cbor's Codable surface can't round-trip integer keys; archive-companion pattern; CBOR-in-positional rides as a plain Data field).
  • GER-1966: MailboxGrant {authKey, serviceHost, expiration} with address/putTag HMAC derivation, KATs cross-validated byte-for-byte against germ-service's test vectors. Plus the ProtocolAddress↔MailboxGrant bridge: a grant's authKey (32 decoded bytes) and a legacy UUID identifier (27) never collide by length, so grants ride the existing identifier field on the wire-frozen PQ establishment surfaces with zero arity change.
  • GER-1967: AgentUpdateV2 (grants only) behind CommProposal tag 6, emitted only to peers observed ≥ mailboxGrantVersion (2.4.0). Readers ship before writers; tags 1–5 pinned byte-identical.

149 tests green, including CBOR wire-pinning fixtures hand-verified at introduction. Pairs with germ-network/germ-service#29 (server-side string-key rename).

🤖 Generated with Claude Code

Pin swift-cbor at the same revision CoreAppLogic uses, and add a small
DeterministicCbor seam establishing the conventions new wire types must
follow: short string map keys (swift-cbor's Codable surface only ever
produces/accepts string keys — it silently drops non-string keys on
decode rather than erroring, so integer keys are wire-incompatible by
construction), the archive-companion pattern, and riding a CBOR blob
inside a positional container as a plain Data field.

Also hoists the hex-fixture decode helper out of AgentHelloDualOfferTests
into shared test support, for reuse by new wire-pinning tests.
MailboxGrant {authKey, serviceHost, expiration} — the authenticated
mailbox address, replacing ProtocolAddress in new carriage. address and
putTag(nonce:bodyDigest:) are HMAC-SHA256 derivations matching
germ-service's deriveMailboxAddress/computePutTag byte-for-byte (KATs
cross-validated against test/mailbox-hmac.spec.ts). TypedKeyMaterial's
existing .hmacSha256 case and validated symmetric-key initializer already
covered what the issue asked for; nothing to add there.

Also adds the transitional ProtocolAddress <-> MailboxGrant bridge: a
grant's authKey (32 raw bytes) and a legacy crypto.randomUUID() address
(36 chars, 27 decoded bytes) never collide by length, so a grant can ride
the existing identifier field on wire-shape-frozen surfaces without any
arity change — see AgentUpdateV2's commit for where this applies.
AgentUpdateV2 {version, isAppClip, grants} — grants only, no legacy
addresses field — carried by a new CommProposal.agentUpdateV2 case (tag
6, appended so existing tags 1-5 keep their values). Follows the
pqCardUpgrade precedent exactly: a new ProposalType tag drops the whole
message on a peer that doesn't recognize it, so this is emitted only to
a peer observed >= AgentUpdate.mailboxGrantVersion (2.4.0, next after
pqCapableVersion). Readers ship before writers; the emission gate itself
lives in the app.

mailboxGrantVersion/supportsMailboxGrants mirror pqCapableVersion/
isPQCapable exactly. Below the gate, addresses keeps riding the classic
.sameAgent triple, byte-for-byte unchanged (pinned).

The PQ establishment surfaces (PQAppWelcome/PQAnchorWelcome/handoffs)
don't need a wire change at all: they're already live, fixed-arity
structs, but they already carry AgentUpdate.addresses (directly or via
an embedded AgentUpdate), and the ProtocolAddress <-> MailboxGrant bridge
means those addresses can already be grants. Once a peer clears the
gate, the steady-state conversation upgrades to real agentUpdateV2
proposals; the bridge is only ever the transitional carriage.
@changeset-bot

changeset-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 55ddccb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@germ-mark
germ-mark merged commit 2ebf8c3 into main Aug 4, 2026
8 checks passed
@germ-mark
germ-mark deleted the feat/mailbox-grant-wire-types branch August 4, 2026 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant