Files
amethyst/quartz/src
Claude 9ae07894c7 fix(marmot): sign commits under pre-proposal extensions (fix InvalidMembershipTag)
For a GroupContextExtensions commit, openmls signs the
`FramedContentTBS` over `group.public_group.group_context()` — the
UNMUTATED context, before the `diff` applies the GCE proposal. The
post-proposal extensions only make it into the HPKE path-encryption
context and the subsequent key schedule, not into the TBS / signature /
membership_tag.

Quartz's `applyProposal` handler for `GroupContextExtensions` mutates
`groupContext.extensions` inline — by the time `commit()` captured
`preCommitContextBytes`, the extensions were already updated. The
signature and membership_tag were then minted over the post-GCE context,
and openmls's `verify_membership` recomputed the MAC over the pre-GCE
context and reported `ValidationError(InvalidMembershipTag)` on every
cross-impl rename / promote / demote / leave.

Fix: snapshot `groupContext.extensions` before any proposal is applied,
and rebuild `preCommitContextBytes` with those original extensions. The
path-encryption context and post-commit key schedule still use the
updated extensions, matching openmls.

https://claude.ai/code/session_016kAxdp6ubB5CnF9URhCEzP
2026-04-22 03:35:09 +00:00
..
2026-04-14 22:24:55 -04:00