Skip to content

Fix group invite discovery after direct add#373

Merged
laulpogan merged 1 commit into
mainfrom
fix/group-invite-materialization
Jul 20, 2026
Merged

Fix group invite discovery after direct add#373
laulpogan merged 1 commit into
mainfrom
fix/group-invite-materialization

Conversation

@laulpogan

@laulpogan laulpogan commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

What

Directly added verified members now materialize a signed group invite when listing groups, so they do not need to request a separate wire-group join code.

Safety

Invite intake requires both the local recipient and local roster membership before persisting the shared room credential.

Verification

  • cargo fmt
  • cargo test --test e2e_group group_bidirectional_room_with_introduce_pin -- --nocapture
  • cargo test --test cli group_list_empty_reports_no_groups -- --nocapture
  • cargo test -q
  • Two independent semantic reviews

Summary by CodeRabbit

  • New Features

    • Group members can discover and access newly shared groups by running wire group list, without entering a separate join code.
    • Newly received invitations are available immediately after synchronization when addressed to the local identity.
  • Bug Fixes

    • Invitations are now restricted to correctly addressed recipients whose signed roster includes them.
    • Group listing works safely before initialization and reports an empty state appropriately.
  • Documentation

    • Added design documentation covering invitation discovery, validation, and verification scenarios.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

wire group list now ingests eligible signed direct invites before listing initialized groups. Recipient and roster membership checks prevent unrelated invites from materializing groups, with CLI and end-to-end tests covering empty, successful, and rejected cases.

Changes

Group invite materialization

Layer / File(s) Summary
Direct invite intake and materialization
docs/superpowers/specs/2026-07-19-group-invite-materialization-design.md, src/cli/group.rs
The invite ingester matches the local recipient DID, requires the local identity in the signed roster, and runs before initialized group listings.
Materialization and rejection coverage
tests/cli.rs, tests/e2e_group.rs, SESSION_LOG_2026_07_19.md
Tests cover uninitialized empty listings, direct invite materialization for members, and rejection of mismatched or incomplete outsider invites; the session log records the behavior and verification evidence.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant cmd_group_list
  participant ingest_group_invites
  participant Inbox
  participant GroupState
  User->>cmd_group_list: wire group list
  cmd_group_list->>ingest_group_invites: ingest when initialized
  ingest_group_invites->>Inbox: read group_invite events
  ingest_group_invites->>GroupState: persist matching verified roster
  GroupState-->>cmd_group_list: return materialized groups
  cmd_group_list-->>User: display group list
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: making group invites discoverable after a direct add.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/group-invite-materialization

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cli/group.rs (1)

153-175: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use canonical full DIDs consistently for direct-invite recipients. The ingester compares against a reconstructed bare DID, and the e2e fixtures encode the same format; canonical signed events addressed to fingerprinted DIDs are rejected, while the roster-rejection fixture masks the membership gate.

  • src/cli/group.rs#L153-L175: compare event["to"] with self_did returned by group_self(), not did:wire:<handle>.
  • tests/e2e_group.rs#L425-L426: sign the wrong-recipient invite with Bob’s full DID and the excluded-roster invite with eve_did, so each rejection path is exercised independently.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/group.rs` around lines 153 - 175, Use the canonical self_did returned
by group_self() when validating direct-invite recipients in the group invite
ingestion logic; remove the reconstructed did:wire:<handle> comparison. In
tests/e2e_group.rs lines 425-426, sign the wrong-recipient invite with Bob’s
full DID and the excluded-roster invite with eve_did so the two rejection paths
are tested independently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@SESSION_LOG_2026_07_19.md`:
- Line 24: Update the impact record for ingest_group_invites to explicitly
document the added recipient-DID and roster-membership validation gates,
replacing the claim that its validation logic was unchanged; retain the existing
risk and caller information.

In `@tests/e2e_group.rs`:
- Around line 425-426: Update the test fixtures in the relevant E2E test to use
full recipient DIDs: construct the wrong-recipient event with Bob’s full DID and
construct the excluded-roster event with the existing eve_did value. Preserve
the distinct scenarios so recipient filtering does not mask the roster-exclusion
check.

---

Outside diff comments:
In `@src/cli/group.rs`:
- Around line 153-175: Use the canonical self_did returned by group_self() when
validating direct-invite recipients in the group invite ingestion logic; remove
the reconstructed did:wire:<handle> comparison. In tests/e2e_group.rs lines
425-426, sign the wrong-recipient invite with Bob’s full DID and the
excluded-roster invite with eve_did so the two rejection paths are tested
independently.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1d20e4d1-3a0d-4cb0-9b31-853f43997e10

📥 Commits

Reviewing files that changed from the base of the PR and between fc28959 and fe274b8.

📒 Files selected for processing (5)
  • SESSION_LOG_2026_07_19.md
  • docs/superpowers/specs/2026-07-19-group-invite-materialization-design.md
  • src/cli/group.rs
  • tests/cli.rs
  • tests/e2e_group.rs

Comment thread SESSION_LOG_2026_07_19.md
- Regression reproduced: `cargo test --test e2e_group group_bidirectional_room_with_introduce_pin -- --nocapture` failed before the code fix because the recipient listed zero groups after pull.
- Focused verification passed: `cargo fmt --check`, `cargo test --test e2e_group -- --nocapture`, and `cargo test --test cli group_list_empty_reports_no_groups -- --nocapture`.
- Full verification passed: `cargo test -q`.
- GitNexus impact: `cmd_group_list` had one direct caller / LOW risk; shared `ingest_group_invites` was HIGH risk due to `send` and `tail` callers, so its validation logic was unchanged.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the impact record.

Line 24 says ingest_group_invites validation was unchanged, but this PR adds recipient-DID and roster-membership gates there. Record those validation changes explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SESSION_LOG_2026_07_19.md` at line 24, Update the impact record for
ingest_group_invites to explicitly document the added recipient-DID and
roster-membership validation gates, replacing the claim that its validation
logic was unchanged; retain the existing risk and caller information.

Comment thread tests/e2e_group.rs
Comment on lines +425 to +426
let wrong_recipient = sign_invite(format!("did:wire:{bob_h}"), &roster_including_eve);
let excluded_recipient = sign_invite(format!("did:wire:{eve_h}"), &group);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use full DIDs so the roster gate is tested independently.

Lines 425-426 use bare DIDs. After recipient matching is corrected, the Eve-targeted fixture fails recipient filtering first, so this test no longer proves that a signed roster excluding Eve is rejected. Use Bob’s full DID for the wrong-recipient event and eve_did for the excluded-roster event.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/e2e_group.rs` around lines 425 - 426, Update the test fixtures in the
relevant E2E test to use full recipient DIDs: construct the wrong-recipient
event with Bob’s full DID and construct the excluded-roster event with the
existing eve_did value. Preserve the distinct scenarios so recipient filtering
does not mask the roster-exclusion check.

@laulpogan
laulpogan merged commit 9a24138 into main Jul 20, 2026
10 checks passed
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