Skip to content

Groups: leave notices, member removal, rekey, admin handoff (signed update chain, key epochs) - #41

Merged
devin-ai-integration[bot] merged 5 commits into
mainfrom
devin/1791815438-group-admin
Oct 12, 2026
Merged

devin-ai-integration[bot] merged 5 commits into
mainfrom
devin/1791815438-group-admin

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Phase 5 of #34. Design: #34 (comment)

Key epochs, stable group ID. The group ID (the directory name) is fixed when the group is created and no longer derives from the current key. Each admin action bumps meta.epoch, and may rotate the key. Members keep the last 16 old keys (keys.json) and the last 17 signed updates (updates.json). Every epoch a peer can still negotiate therefore has a complete update chain.

preface v2: ENTG 2 <group_id[4]> <epoch u32 BE>
responder ack: 0x00 proceed | 0x01 <E> "use my epoch E" (initiator echoes E) | 0x02 <current> too far behind
prologue:   "entangle-link-v5" || group_id || epoch

0x02 is unauthenticated. Its only effects are a log line and backoff (TransportError::TooFarBehind / PeerTooFarBehind). dial then moves on to the next shared group.

Signed GroupUpdate chain (entangle-core):

  • Contents: epoch, key_hex, admin, admin_sign_key, revoked (the full set), kind, issued_by.
  • Signature: Ed25519, by the previous epoch's admin, using a per-device key SHA-256("entangle-sign-v1" || static_private).
  • Acceptance (apply_updates): only epoch == current+1 signed by the current admin. A handoff must name a current member, and its admin_sign_key must match that member's record.
  • Relay: any member can relay the log (updates_since, served only to current members).
  • Catch-up: a link at an old epoch carries only GroupUpdates/GroupUpdatesAck, then redials.

Membership:

  • Revoked particles are dropped from members.json, and their introductions are rejected.
  • A non-admin invite declines a revoked particle (DeclineReason::Removed). An admin re-invite un-revokes it.
  • A device that receives its own revocation deletes the group.
  • Recovery for a device too far behind: a re-invite refreshes its stale local copy. GroupInfo carries the inviter's epoch, and after SPAKE2 the joiner replaces its copy atomically, keeping the local name.

CLI (human-only, single-keypress confirm):

  • group remove <group> <member>, group rekey <group>, group admin <group> <member>: admin-only.
  • group leave: sends Leave through the running node. The admin must hand off first if other members remain.
  • Each command prints one delivery line, taken from groups/.status/<id>.json.

Breaking: the protocol, preface and storage versions all change. 0.6 groups report GroupError::Outdated and must be recreated (group leave still deletes them). The repeater session uses the first active group that is in the key ring.

Docs: playbook 10, SETUP, AGENT_SETUP (agents never run these commands), ARCHITECTURE, troubleshooting.

Tests: 181 pass in a serialized run (cargo test --workspace -- --test-threads=1).

  • A parallel-run timeout in normal_particles_prefer_direct_route_with_repeater_available was traced to this branch: main passed 3/3, the branch 2/3.
  • It was fixed by the direct-Hello address change. Focused runs pass, but a full parallel rerun is still pending.

Link to Devin session: https://app.devin.ai/sessions/2e5afab1127347e783891657f1394118
Open in Devin Desktop: https://app.devin.ai/desktop/session/2e5afab1127347e783891657f1394118?variant=devin
Requested by: @DailenG


Devin Review

Co-Authored-By: Dailen Gunter <daileng@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 49d5bacf-605f-4bb0-8997-e437d352aed2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Co-Authored-By: Dailen Gunter <daileng@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Dailen Gunter <daileng@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Dailen Gunter <daileng@gmail.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

Devin Review

Comment thread crates/entangle/src/invite/protocol.rs Outdated
Comment thread crates/entangle/src/groups.rs Outdated
Co-Authored-By: Dailen Gunter <daileng@gmail.com>
@devin-ai-integration
devin-ai-integration Bot merged commit 7e90abb into main Oct 12, 2026
5 checks passed
@devin-ai-integration devin-ai-integration Bot mentioned this pull request Oct 12, 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