Skip to content

fix(collab): re-derive content key on collection updates — deliver rotated keys to members (HIGH #173) - #175

Merged
cuttlefisch merged 1 commit into
mainfrom
fix/e2e-content-key-refresh
Jun 27, 2026
Merged

fix(collab): re-derive content key on collection updates — deliver rotated keys to members (HIGH #173)#175
cuttlefisch merged 1 commit into
mainfrom
fix/e2e-content-key-refresh

Conversation

@cuttlefisch

Copy link
Copy Markdown
Owner

Closes #173. Subsumes #169 M2. Found during the M2 investigation — broader + more severe.

Bug

A member derived its per-KB content key once (join/share/enable). On subsequent kbc: collection broadcasts, handle_kbc_membership_broadcast relearned the epoch but never re-derived the content key — the network task's content_keys (seal + open) was frozen at first derive. So:

The data layer was correct (find_wrapped_content_key returns k' — tested); the gap was collab-bridge wiring.

Fix

  • KbCryptoCtx gains kb_collections — per-KB full collection replicas, seeded at join/share/enable, advanced by inbound kbc: deltas.
  • New refresh_kb_content_key_on_collection_delta: on a kbc: delta, advance the replica + re-derive content_keys (+ persist), wired into both inbound sync_update paths. No-op for non-kbc: / unseeded / unencrypted KBs (a plain KB is undisturbed).
  • The rotation handler now registers the find_wrapped winner derived from the post-rotation collection (the M2 single-source-of-truth fix), not the locally-generated k2.

Test (principle #14 — rotation-delivery oracle)

refresh_kb_content_key_re_derives_on_rotation_remaining_yes_removed_no: a REMAINING member re-derives k' on the rotation delta; the REMOVED member stays stranded on the old k. 116 collab_bridge tests + full cargo test -p mae green; clippy clean.

release:none.

🤖 Generated with Claude Code

@cuttlefisch cuttlefisch added area:collab Collaborative editing / sync / CRDT release:none Skip version bump on merge security Security / auth / access control labels Jun 27, 2026
…r rotated keys to members (HIGH #173)

A member derived its per-KB content key ONCE, at join/share/enable. On subsequent kbc:
collection broadcasts, handle_kbc_membership_broadcast relearned the epoch but never
re-derived the content key, so the network task's content_keys (seal + open) was frozen at
first derive. Consequences:
- 3c rotation was broken for remaining members: after the owner rotated to k', members kept
  the old k — couldn't open k'-sealed content, sealed their edits under the stale k →
  divergence after any membership change.
- Wrap-on-admit for a member who already joined never reached their seal/open path.
- Subsumes #169 M2 (concurrent rotations converge once both deltas merge + re-derive).

Fix:
- KbCryptoCtx gains kb_collections: per-KB full collection replicas, seeded at
  join/share/enable, advanced by inbound kbc: deltas.
- New refresh_kb_content_key_on_collection_delta: on a kbc: delta, advance the replica and
  RE-DERIVE content_keys via derive_kb_content_key (+ persist), wired into both inbound
  sync_update paths. No-op for non-kbc / unseeded / unencrypted (a plain KB is undisturbed).
- Rotation handler now registers the find_wrapped winner derived from the post-rotation
  collection (the #169 M2 single-source-of-truth fix), not the locally-generated k2.

Test (principle #14, the rotation-delivery oracle):
refresh_kb_content_key_re_derives_on_rotation_remaining_yes_removed_no — a REMAINING member
re-derives k' on the rotation delta; the REMOVED member stays stranded on the old k.

116 collab_bridge tests green; clippy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cuttlefisch
cuttlefisch force-pushed the fix/e2e-content-key-refresh branch from 5870342 to 1bf9ca5 Compare June 27, 2026 19:01
@cuttlefisch
cuttlefisch merged commit 8ca94e1 into main Jun 27, 2026
14 checks passed
@cuttlefisch
cuttlefisch deleted the fix/e2e-content-key-refresh branch June 27, 2026 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:collab Collaborative editing / sync / CRDT release:none Skip version bump on merge security Security / auth / access control

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HIGH: members don't re-derive the content key on collection updates → 3c rotation + post-join wrap don't reach members

1 participant