Skip to content

Gate the A.5 Upd' door on content type, refuse rekey while a bind is owed - #120

Merged
germ-mark merged 1 commit into
mainfrom
llm/rekey-upd-content-gate
Jul 27, 2026
Merged

Gate the A.5 Upd' door on content type, refuse rekey while a bind is owed#120
germ-mark merged 1 commit into
mainfrom
llm/rekey-upd-content-gate

Conversation

@germ-mark

Copy link
Copy Markdown
Contributor

Closes the one substantive gap the post-v0.14 review turned up (pre-existing, not a regression from any of the four merged PRs).

The A.5 Upd' door feeds process_incoming_message on our own send-PQ, which validates and applies a commit atomically. The peer is a member of that group, so it could author a commit there that would apply — moving our send-PQ epoch — before the door's kind check refused it, and the refusal wore the fatal Mls disposition (asks a host to tear the session down). This is the exact gap #111 closed at the A.4 leg doors; it stopped one door short.

  • Content-type gate. The door reads the content type off the plaintext framing (a pure read, no keys, no state) before ingest and refuses anything but a proposal with the retriable DecryptionFailed. Mutation-checked: without it, a smuggled commit applies (send-PQ epoch 1→2).
  • Owed-bind guard. The closure commits our send-PQ, moving the epoch an owed bind reserved in its attestation — discharging against a moved epoch fails with the PQ leaf spent. An honest peer never sends here (owing a bind means the turn is ours); a deviating one is now a retriable guard-phase no-op. Mutation-checked.

No wire, FFI, or error-variant change — the generated uniffi binding is byte-identical, so no contract bump (following #111). Both new tests build a real, applicable commit/proposal in the peer's recv-PQ mirror of our send-PQ, so they exercise the gate itself rather than a group-id refusal.

🤖 Generated with Claude Code

…owed

The Upd' door feeds process_incoming_message on our send-PQ, which applies a
commit atomically — so a peer-authored commit smuggled behind the tag would
advance our epoch before the kind check refused it, and the refusal wore the
fatal Mls disposition. Same gap the A.4 leg doors already closed (#111): read
the content type off the plaintext framing first, refuse anything but a
proposal with the retriable DecryptionFailed, nothing applied.

The door also refuses a rekey while a classical bind is owed — its Commit'
would move the epoch the owed bind reserved, failing the discharge with the PQ
leaf spent. Honest peers never reach it (owing a bind means the turn is ours);
a deviating one is a retriable guard-phase no-op.

Both guards mutation-checked. No wire, FFI, or error-variant change; the
generated binding is unchanged, so no contract bump (as #111).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e9081c9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@germ-network/two-mls-pq Minor

Not sure what this means? Click here to learn what changesets are.

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

@germ-mark
germ-mark merged commit 47f69db into main Jul 27, 2026
10 checks passed
@germ-mark
germ-mark deleted the llm/rekey-upd-content-gate branch July 27, 2026 20:16
@github-actions github-actions Bot mentioned this pull request Jul 27, 2026
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