Skip to content

feat: add SelfRemove proposal support for voluntary group departure (MIP-03)#236

Merged
jgmontoya merged 7 commits intomasterfrom
feat/auto-commit-leave
Mar 31, 2026
Merged

feat: add SelfRemove proposal support for voluntary group departure (MIP-03)#236
jgmontoya merged 7 commits intomasterfrom
feat/auto-commit-leave

Conversation

@jgmontoya
Copy link
Copy Markdown
Contributor

@jgmontoya jgmontoya commented Mar 25, 2026

⚠️ Security-sensitive changes

This PR implements MIP-03 SelfRemove proposal support so members can voluntarily leave groups via SelfRemove proposals that are auto-committed, removing the need for an admin-initiated Remove while ensuring departures cannot deplete the admin set. It also advertises SelfRemove capability in MLS capabilities and KeyPackage Nostr tags and adjusts wire-format defaults to accept SelfRemove as PublicMessage for interoperability.

What changed:

  • Added proposal capability constants to mdk-core to advertise SelfRemove support: SUPPORTED_PROPOSALS, GROUP_CONTEXT_REQUIRED_PROPOSALS, TAG_PROPOSALS (crates/mdk-core).
  • Replaced TAG_EXTENSIONS with SUPPORTED_EXTENSIONS for extension tag derivation to keep tag contents aligned with capability extensions (crates/mdk-core).
  • Modified group creation and welcome handling to default to MIXED_CIPHERTEXT_WIRE_FORMAT_POLICY so groups accept SelfRemove as PublicMessage (crates/mdk-core).
  • Implemented try_self_remove() and routed MDK::leave_group() through it; it temporarily switches wire format to send SelfRemove and falls back to legacy Remove for pure-ciphertext groups (crates/mdk-core).
  • process_proposal now handles Proposal::SelfRemove by validating admin depletion and auto-committing via auto_commit_proposal() instead of storing as pending for non-admins (crates/mdk-core).
  • Added validate_admin_depletion(), is_self_remove_only_commit(), and updated validate_commit_authorization() to allow non-admin SelfRemove-only commits while rejecting mixed unauthorized commits (crates/mdk-core).
  • Introduced an mls_proposals Nostr tag in KeyPackage creation and added MDK helper proposals_value() to generate proposal tags (crates/mdk-core).
  • Implemented ProposalType -> Nostr tag formatting as "0xXXXX" via NostrTagFormat for ProposalType (crates/mdk-core).
  • Updated unit tests to assert SelfRemove auto-commit behavior, no pending removals after SelfRemove, and adjusted a concurrent-commit test to accept multiple valid outcomes (crates/mdk-core).

Security impact:

  • Changes MLS departure semantics and authorization rules; added explicit validation to prevent admin depletion when processing SelfRemove, preserving group admin integrity.
  • Wire-format changes (mixed incoming ciphertext) alter message acceptance semantics and require interoperability consideration with legacy peers.
  • No changes to cryptographic primitives, key derivation, SQLCipher configuration, or file permission handling were introduced.

Protocol changes:

  • Implements SelfRemove proposal support per RFC 9420 §7.5 with auto-commit semantics and extends capability advertisement per RFC 9420 §10.4 to include proposal types.
  • Adds mls_proposals Nostr tag to KeyPackage events to advertise supported proposal types (Nostr tag format), encoding ProposalType as 0xXXXX.
  • Default group wire-format policy changed to MIXED_CIPHERTEXT to accept PublicMessage SelfRemove proposals.

API surface:

  • No breaking public API changes; added a public trait impl NostrTagFormat for ProposalType and a crate-private helper proposals_value() in MDK.
  • No storage schema or UniFFI/FFI boundary changes.

Testing:

  • Tests were updated and added in mdk-core to reflect SelfRemove auto-commit behavior, pending-member expectations, and concurrent-commit race outcomes.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds MLS SelfRemove support: new proposal constants and Nostr tag formatting, mixed-ciphertext defaults for group create/join, SelfRemove proposal handling with auto-commit, expanded non-admin commit authorization with admin-depletion validation, and a KeyPackage mls_proposals Nostr tag.

Changes

Cohort / File(s) Summary
Constants & tag formatting
crates/mdk-core/src/constant.rs, crates/mdk-core/src/util.rs
Added SUPPORTED_PROPOSALS, GROUP_CONTEXT_REQUIRED_PROPOSALS, TAG_PROPOSALS (contain ProposalType::SelfRemove) and implemented NostrTagFormat for ProposalType (0x{:04x}). Repointed TAG_EXTENSIONS to SUPPORTED_EXTENSIONS.
MDK capabilities & KeyPackage helper
crates/mdk-core/src/lib.rs
Include proposals in Capabilities::new(...), pass GROUP_CONTEXT_REQUIRED_PROPOSALS to RequiredCapabilitiesExtension, and add pub(crate) fn proposals_value(&self) -> Vec<String> to produce proposal tag strings.
KeyPackage tags
crates/mdk-core/src/key_packages.rs
Insert new custom mls_proposals tag into KeyPackage tag vector (added after mls_extensions), shifting tag indices/counts; tests updated.
Group create / leave flow
crates/mdk-core/src/groups.rs
New try_self_remove() uses wire-format policy switching to send SelfRemove as PublicMessage for mixed groups and falls back to Remove for pure-ciphertext groups; leave_group() delegates to it; tests updated for auto-commit semantics.
Proposal processing & tests
crates/mdk-core/src/messages/proposal.rs, crates/mdk-core/src/messages/commit.rs
Process Proposal::SelfRemove by running admin-depletion validation and auto-committing when valid; updated tests accept multiple valid commit outcomes and assert SelfRemove auto-commit behavior.
Commit validation & authorization
crates/mdk-core/src/messages/validation.rs
Added is_self_remove_only_commit() and validate_admin_depletion(); updated validate_commit_authorization() to allow non-admins either pure self-update commits or SelfRemove-only commits (with admin-depletion checks), rejecting mixed types.
Welcome parsing / join config
crates/mdk-core/src/welcomes.rs
Set MlsGroupJoinConfig to MIXED_CIPHERTEXT_WIRE_FORMAT_POLICY when parsing Welcome messages.
Changelog
crates/mdk-core/CHANGELOG.md
Added Unreleased entries documenting SelfRemove capability (0x000a), wire-format policy changes, admin-depletion validation, and KeyPackage tag changes.

Sequence Diagram(s)

sequenceDiagram
    participant Member
    participant Group as "MLS Group"
    participant Processor as "MessageProcessor"
    participant Validator

    Member->>Group: try_self_remove(signer)
    Group->>Group: set_configuration(MIXED_PLAINTEXT_WIRE_FORMAT_POLICY)
    Group->>Group: leave_group_via_self_remove() -> produce SelfRemove message
    Group->>Group: restore_configuration(MIXED_CIPHERTEXT_WIRE_FORMAT_POLICY)
    Group-->>Member: MlsMessageOut (SelfRemove)

    Member->>Processor: process_proposal(SelfRemove)
    Processor->>Validator: validate_admin_depletion(departing_leaves)
    alt validation fails
        Validator-->>Processor: Error
        Processor-->>Member: IgnoredProposal (rejection)
    else validation succeeds
        Validator-->>Processor: Ok
        Processor->>Group: auto_commit_proposal()
        Processor-->>Member: MessageProcessingResult::Proposal
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

mls-protocol

Suggested reviewers

  • dannym-arx
  • mubarakcoded
  • erskingardner
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the main change: introducing SelfRemove proposal support for voluntary group departure according to MIP-03 specification.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
No Sensitive Identifier Leakage ✅ Passed No sensitive identifiers exposed in production code. Key functions use generic error messages without interpolating sensitive data, and panic calls appear only in test code.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auto-commit-leave

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 25, 2026

UniFFI Binding Coverage

10 public method(s) not bound in UniFFI

Coverage: 31/41 bindable methods (75.6%)

⚠️ Not Bound

Method Source
delete_key_package_from_storage crates/mdk-core/src/key_packages.rs:603
delete_key_package_from_storage_by_hash_ref crates/mdk-core/src/key_packages.rs:618
get_ratchet_tree_info crates/mdk-core/src/groups.rs:600
group_leaf_map crates/mdk-core/src/groups.rs:566
own_leaf_index crates/mdk-core/src/groups.rs:557
pending_added_members_pubkeys crates/mdk-core/src/groups.rs:656
pending_member_changes crates/mdk-core/src/groups.rs:724
pending_removed_members_pubkeys crates/mdk-core/src/groups.rs:689
prepare_group_image_for_upload_with_options crates/mdk-core/src/extension/group_image.rs:459
process_message_with_context crates/mdk-core/src/messages/process.rs:327
✅ Bound methods (31)
Method Source
accept_welcome crates/mdk-core/src/welcomes.rs:315
add_members crates/mdk-core/src/groups.rs:770
clear_pending_commit crates/mdk-core/src/groups.rs:1654
create_group crates/mdk-core/src/groups.rs:1208
create_key_package_for_event crates/mdk-core/src/key_packages.rs:54
create_key_package_for_event_with_options crates/mdk-core/src/key_packages.rs:92
create_message crates/mdk-core/src/messages/create.rs:79
decline_welcome crates/mdk-core/src/welcomes.rs:350
decrypt_group_image crates/mdk-core/src/extension/group_image.rs:227
derive_upload_keypair crates/mdk-core/src/extension/group_image.rs:332
get_group crates/mdk-core/src/groups.rs:496
get_groups crates/mdk-core/src/groups.rs:508
get_last_message crates/mdk-core/src/messages/mod.rs:278
get_members crates/mdk-core/src/groups.rs:542
get_message crates/mdk-core/src/messages/mod.rs:211
get_messages crates/mdk-core/src/messages/mod.rs:250
get_pending_welcomes crates/mdk-core/src/welcomes.rs:72
get_relays crates/mdk-core/src/groups.rs:1154
get_welcome crates/mdk-core/src/welcomes.rs:40
groups_needing_self_update crates/mdk-core/src/groups.rs:526
leave_group crates/mdk-core/src/groups.rs:1601
merge_pending_commit crates/mdk-core/src/groups.rs:1705
parse_key_package crates/mdk-core/src/key_packages.rs:268
prepare_group_image_for_upload crates/mdk-core/src/extension/group_image.rs:413
process_message crates/mdk-core/src/messages/process.rs:320
process_welcome crates/mdk-core/src/welcomes.rs:178
remove_members crates/mdk-core/src/groups.rs:868
self_demote crates/mdk-core/src/groups.rs:1547
self_update crates/mdk-core/src/groups.rs:1380
sync_group_metadata_from_mls crates/mdk-core/src/groups.rs:1776
update_group_data crates/mdk-core/src/groups.rs:1088
➖ Intentionally excluded (5)
Method Reason
builder Wrapped by new_mdk(), new_mdk_with_key(), new_mdk_unencrypted() free functions
load_mls_group Only available behind debug-examples feature flag, not for production use
media_manager Returns borrowed reference with lifetime — cannot cross FFI boundary
migrate_group_image_v1_to_v2 Migration utility for internal use only, not needed in client bindings
new Wrapped by new_mdk(), new_mdk_with_key(), new_mdk_unencrypted() free functions

@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.43% → 91.22% (-0.21%)

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
crates/mdk-core/src/key_packages.rs (2)

109-112: Update the tag count in the internal documentation.

The comment references outdated tag counts (7/8) that should be updated to reflect the new mls_proposals tag (8/9).

📝 Suggested documentation update
 /// The `protected` parameter controls whether the NIP-70 protected tag (`["-"]`) is
 /// included in the output tags. When `true`, the tag is inserted between the `i`
-/// and `client` tags, resulting in 8 total tags. When `false`, the protected tag is
-/// omitted, resulting in 7 total tags.
+/// and `client` tags, resulting in 9 total tags. When `false`, the protected tag is
+/// omitted, resulting in 8 total tags.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/mdk-core/src/key_packages.rs` around lines 109 - 112, Update the
inline doc comment that describes tag counts: the description of the `protected`
parameter and the NIP-70 protected tag currently lists totals as 7/8; adjust
these counts to 8/9 to account for the new `mls_proposals` tag and ensure the
wording mentions the added `mls_proposals` tag between the `client`/`i` tags
where appropriate so the comment correctly reflects the new tag totals and the
presence/absence of the protected tag.

37-44: Update documentation to include the new mls_proposals tag.

The tag list in the doc comment should include the new mls_proposals tag to match the actual output.

📝 Suggested documentation update
 /// * A vector of tags for the Nostr event:
 ///   - `mls_protocol_version` - MLS protocol version (e.g., "1.0")
 ///   - `mls_ciphersuite` - Ciphersuite identifier (e.g., "0x0001")
 ///   - `mls_extensions` - Required MLS extensions
+///   - `mls_proposals` - Supported proposal types (e.g., "0x000a")
 ///   - `relays` - Relay URLs for distribution
 ///   - `i` - Hex-encoded KeyPackageRef for efficient relay queries (MIP-00)
 ///   - `client` - Client identifier and version
 ///   - `encoding` - The encoding format tag ("base64")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/mdk-core/src/key_packages.rs` around lines 37 - 44, Update the doc
comment that lists the Nostr event tags (the vector-of-tags comment block in
crates::mdk_core::key_packages.rs) to include the new mls_proposals tag;
specifically add an entry for `mls_proposals` alongside the existing entries
(`mls_protocol_version`, `mls_ciphersuite`, `mls_extensions`, `relays`, `i`,
`client`, `encoding`) so the documentation matches the actual output produced by
the KeyPackage/Nostr event code.
crates/mdk-core/src/messages/proposal.rs (1)

388-455: Test correctly validates non-admin auto-commit for SelfRemove.

The test properly verifies that Charlie (non-admin) can auto-commit Bob's SelfRemove proposal, which is the key behavioral difference from legacy Remove proposals.

Consider adding a complementary test for the admin depletion rejection case — where a SelfRemove is rejected because it would leave the group with no admins.

,

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/mdk-core/src/messages/proposal.rs` around lines 388 - 455, Add a
complementary test that ensures a SelfRemove is rejected when it would leave the
group with no admins: create a group where the only admin is the leaver (use
Keys::generate(), create_test_mdk(), create_group with
create_nostr_group_config_data(admins)), have that admin call leave_group(),
have another member call process_message(...) on the admin's evolution_event,
and assert the result is a rejection (match MessageProcessingResult::Rejected or
the appropriate rejection variant) instead of Proposal; name the test e.g.
test_self_remove_rejected_due_to_admin_depletion to mirror
test_self_remove_proposal_auto_committed_by_non_admin.
crates/mdk-core/src/messages/validation.rs (1)

214-225: Consider adding unit tests for the new helper functions.

The new is_self_remove_only_commit and validate_admin_depletion functions lack direct unit tests in this file. Consider adding tests for:

  • is_self_remove_only_commit: empty proposals (should return false), single SelfRemove, multiple SelfRemoves, mixed proposal types
  • validate_admin_depletion: single admin departing from single-admin group, non-admin departing, partial admin departure leaving at least one admin

Would you like me to generate unit test stubs for these helper functions, or open an issue to track this?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/mdk-core/src/messages/validation.rs` around lines 214 - 225, Add unit
tests covering is_self_remove_only_commit and validate_admin_depletion: for
is_self_remove_only_commit add cases for an empty StagedCommit (expect false), a
single queued Proposal::SelfRemove (true), multiple SelfRemove proposals (true),
and mixed proposal types including at least one non-SelfRemove (false); for
validate_admin_depletion add cases for a single admin leaving a single-admin
group (should error/indicate depletion), a non-admin departing (no depletion),
and partial admin departures that leave at least one admin (no depletion). Use
the existing StagedCommit/queued_proposals and Proposal enum constructors used
in the module to build test inputs and assert expected boolean/result
conditions. Ensure tests live alongside other unit tests for these helpers and
use the module-private visibility (pub(super)) access pattern as needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/mdk-core/src/key_packages.rs`:
- Around line 109-112: Update the inline doc comment that describes tag counts:
the description of the `protected` parameter and the NIP-70 protected tag
currently lists totals as 7/8; adjust these counts to 8/9 to account for the new
`mls_proposals` tag and ensure the wording mentions the added `mls_proposals`
tag between the `client`/`i` tags where appropriate so the comment correctly
reflects the new tag totals and the presence/absence of the protected tag.
- Around line 37-44: Update the doc comment that lists the Nostr event tags (the
vector-of-tags comment block in crates::mdk_core::key_packages.rs) to include
the new mls_proposals tag; specifically add an entry for `mls_proposals`
alongside the existing entries (`mls_protocol_version`, `mls_ciphersuite`,
`mls_extensions`, `relays`, `i`, `client`, `encoding`) so the documentation
matches the actual output produced by the KeyPackage/Nostr event code.

In `@crates/mdk-core/src/messages/proposal.rs`:
- Around line 388-455: Add a complementary test that ensures a SelfRemove is
rejected when it would leave the group with no admins: create a group where the
only admin is the leaver (use Keys::generate(), create_test_mdk(), create_group
with create_nostr_group_config_data(admins)), have that admin call
leave_group(), have another member call process_message(...) on the admin's
evolution_event, and assert the result is a rejection (match
MessageProcessingResult::Rejected or the appropriate rejection variant) instead
of Proposal; name the test e.g. test_self_remove_rejected_due_to_admin_depletion
to mirror test_self_remove_proposal_auto_committed_by_non_admin.

In `@crates/mdk-core/src/messages/validation.rs`:
- Around line 214-225: Add unit tests covering is_self_remove_only_commit and
validate_admin_depletion: for is_self_remove_only_commit add cases for an empty
StagedCommit (expect false), a single queued Proposal::SelfRemove (true),
multiple SelfRemove proposals (true), and mixed proposal types including at
least one non-SelfRemove (false); for validate_admin_depletion add cases for a
single admin leaving a single-admin group (should error/indicate depletion), a
non-admin departing (no depletion), and partial admin departures that leave at
least one admin (no depletion). Use the existing StagedCommit/queued_proposals
and Proposal enum constructors used in the module to build test inputs and
assert expected boolean/result conditions. Ensure tests live alongside other
unit tests for these helpers and use the module-private visibility (pub(super))
access pattern as needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 14b583ac-3f12-4362-b913-282818b6d18d

📥 Commits

Reviewing files that changed from the base of the PR and between adaf261 and 41dcd79.

📒 Files selected for processing (9)
  • crates/mdk-core/src/constant.rs
  • crates/mdk-core/src/groups.rs
  • crates/mdk-core/src/key_packages.rs
  • crates/mdk-core/src/lib.rs
  • crates/mdk-core/src/messages/commit.rs
  • crates/mdk-core/src/messages/proposal.rs
  • crates/mdk-core/src/messages/validation.rs
  • crates/mdk-core/src/util.rs
  • crates/mdk-core/src/welcomes.rs
👮 Files not reviewed due to content moderation or server errors (1)
  • crates/mdk-core/src/groups.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 25, 2026
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.43% → 91.2% (-0.23%)

coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 25, 2026
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.43% → 91.25% (-0.18%)

coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 25, 2026
Comment thread crates/mdk-core/src/messages/proposal.rs Outdated
Comment thread crates/mdk-core/src/messages/proposal.rs Outdated
Comment thread crates/mdk-core/src/messages/proposal.rs Outdated
Comment thread crates/mdk-core/src/groups.rs
Comment thread crates/mdk-core/src/constant.rs
Comment thread crates/mdk-core/src/groups.rs Outdated
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.43% → 91.29% (-0.14%)

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/mdk-core/src/key_packages.rs (1)

170-173: Prefer using the shared proposal-tag constant instead of a string literal.

Using a shared constant here avoids protocol-string drift across files and tests.

Proposed refactor
-use crate::constant::{DEFAULT_CIPHERSUITE, TAG_EXTENSIONS};
+use crate::constant::{DEFAULT_CIPHERSUITE, TAG_EXTENSIONS, TAG_PROPOSALS};

         let mut tags = vec![
             Tag::custom(TagKind::MlsProtocolVersion, ["1.0"]),
             Tag::custom(TagKind::MlsCiphersuite, [self.ciphersuite_value()]),
             Tag::custom(TagKind::MlsExtensions, self.extensions_value()),
             Tag::custom(
-                TagKind::Custom("mls_proposals".into()),
+                TagKind::Custom(TAG_PROPOSALS.into()),
                 self.proposals_value(),
             ),
             Tag::relays(relays),
             Tag::custom(TagKind::i(), [key_package_ref_hex]),
         ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/mdk-core/src/key_packages.rs` around lines 170 - 173, Replace the
string literal "mls_proposals" in the Tag::custom call with the shared
proposal-tag constant used across the crate (instead of hardcoding the protocol
string), i.e. use the canonical constant (import it if needed) in place of
"mls_proposals". Keep the surrounding code intact
(Tag::custom(TagKind::Custom(...), self.proposals_value())) and ensure the
constant is converted the same way the literal was (e.g., .into() or as required
by TagKind::Custom).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/mdk-core/src/key_packages.rs`:
- Around line 170-173: Replace the string literal "mls_proposals" in the
Tag::custom call with the shared proposal-tag constant used across the crate
(instead of hardcoding the protocol string), i.e. use the canonical constant
(import it if needed) in place of "mls_proposals". Keep the surrounding code
intact (Tag::custom(TagKind::Custom(...), self.proposals_value())) and ensure
the constant is converted the same way the literal was (e.g., .into() or as
required by TagKind::Custom).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 579e71da-c7d8-49df-a691-34a154ce34fb

📥 Commits

Reviewing files that changed from the base of the PR and between 8854b35 and f5b7d77.

📒 Files selected for processing (4)
  • crates/mdk-core/src/constant.rs
  • crates/mdk-core/src/groups.rs
  • crates/mdk-core/src/key_packages.rs
  • crates/mdk-core/src/messages/proposal.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/mdk-core/src/constant.rs
👮 Files not reviewed due to content moderation or server errors (2)
  • crates/mdk-core/src/messages/proposal.rs
  • crates/mdk-core/src/groups.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 26, 2026
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.43% → 91.27% (-0.16%)

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/mdk-core/src/groups.rs`:
- Around line 1496-1503: The restore-of-ciphertext-mode inside leave_group
currently logs failures from group.set_configuration(self.storage(),
&ciphertext_config) and continues; change this so failures are propagated
instead of swallowed: update leave_group to return an Err when
group.set_configuration(...) fails (use ? or map_err to convert the error into
the function's error type), or if you prefer a recovery path, attempt to
reload/reset the group state from persistent storage via self.storage() before
returning an Err; reference the set_configuration call, ciphertext_config
variable, and leave_group function and ensure the error is surfaced to the
caller rather than only logged.
- Around line 5595-5608: The test currently checks
charlie_mdk.pending_member_changes(&group_id) which only tracks
Proposal::Add/Remove and cannot detect a queued Proposal::SelfRemove; update the
assertion to directly inspect the pending proposals or commit and re-check
membership: call charlie_mdk.pending_proposals(&group_id) (or equivalent) and
assert there is no Proposal::SelfRemove for Bob (using bob's id from
bob_leave_result) or alternatively apply/merge the generated commit via
charlie_mdk.process_message(...) / charlie_mdk.merge_commit(...) and then assert
Bob is no longer in the group membership instead of relying on
pending_member_changes().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bb308ffb-f155-4970-bfd9-063b259de7d5

📥 Commits

Reviewing files that changed from the base of the PR and between f5b7d77 and 89201bf.

📒 Files selected for processing (4)
  • crates/mdk-core/src/constant.rs
  • crates/mdk-core/src/groups.rs
  • crates/mdk-core/src/key_packages.rs
  • crates/mdk-core/src/messages/proposal.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/mdk-core/src/messages/proposal.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/mdk-core/src/key_packages.rs

Comment thread crates/mdk-core/src/groups.rs Outdated
Comment thread crates/mdk-core/src/groups.rs
@jgmontoya jgmontoya force-pushed the feat/auto-commit-leave branch from 89201bf to 7874fb8 Compare March 26, 2026 17:28
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.43% → 91.33% (-0.10%)

@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.51% → 91.4% (-0.11%)

@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.51% → 91.3% (-0.21%)

@jgmontoya jgmontoya force-pushed the feat/auto-commit-leave branch from c3bbbfa to de16d64 Compare March 30, 2026 14:58
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.57% → 91.32% (-0.25%)

Comment thread crates/mdk-core/src/groups.rs Outdated
Comment thread crates/mdk-core/src/messages/proposal.rs Outdated
Comment thread crates/mdk-core/src/groups.rs
Comment thread crates/mdk-core/src/key_packages.rs
Comment thread crates/mdk-core/src/messages/proposal.rs
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.57% → 91.36% (-0.21%)

…lfRemove-only, and test receiving-side admin rejection
@jgmontoya jgmontoya force-pushed the feat/auto-commit-leave branch from a7e6747 to 668de3f Compare March 30, 2026 20:30
@github-actions
Copy link
Copy Markdown

❌ Coverage: 91.57% → 91.36% (-0.21%)

@jgmontoya jgmontoya merged commit 6e34398 into master Mar 31, 2026
19 of 20 checks passed
@jgmontoya jgmontoya deleted the feat/auto-commit-leave branch March 31, 2026 15:35
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.

4 participants