Skip to content

fix: don't publish membership on invite-accept, bundle with first message#109

Merged
sanity merged 1 commit intomainfrom
fix-pruning-breaks-invite
Feb 16, 2026
Merged

fix: don't publish membership on invite-accept, bundle with first message#109
sanity merged 1 commit intomainfrom
fix-pruning-breaks-invite

Conversation

@sanity
Copy link
Contributor

@sanity sanity commented Feb 16, 2026

Problem

The six-peer regression test consistently fails because the member pruning logic
(post_apply_cleanup) immediately removes members who have no messages in
recent_messages. When invite-accept published a membership-only delta (without
any messages), the new member was pruned on every peer before their first message
could arrive. This caused a chicken-and-egg problem: the member needed to send a
message to stay, but their messages were rejected because they weren't in the
members list.

Approach

Instead of publishing membership immediately on invite-accept, store the
invitation credentials locally (AuthorizedMember, invite chain, MemberInfo) and
let build_rejoin_delta bundle membership atomically with the first message.
This ensures the member always has at least one message when added, preventing
post_apply_cleanup from pruning them.

Key insight: A member with a valid invitation is still a member, even if they're
not in the active members list. The active members list only tracks members who
have recent messages.

Changes

CLI (cli/src/api.rs):

  • accept_invitation no longer adds member to local room_state or sends
    membership UPDATE to the network
  • Stores AuthorizedMember and invite chain for build_rejoin_delta

UI (get_response.rs):

  • Pending invite handler no longer applies invitation delta to room_state
  • No longer triggers ProcessRooms synchronization
  • Stores self_member_info for use during rejoin

UI (room_data.rs):

  • can_send_message now checks self_authorized_member as fallback,
    matching can_participate behavior — a user with a valid invite can send
    messages even if not yet in the active members list

Testing

  • Six-peer test passes consistently (2/2 runs) after the fix
  • cargo test --package river-core — all 7 tests pass
  • cargo test --package riverctl --lib — all 4 tests pass
  • cargo clippy — clean (no new warnings)

Fixes

Closes #108

[AI-assisted - Claude]

…sage

The member pruning logic (post_apply_cleanup) immediately removes members
who have no messages in recent_messages. When invite-accept published a
membership-only delta, the new member was pruned on every peer before
their first message could arrive, causing the six-peer test to fail.

Instead, store the invitation credentials locally (AuthorizedMember,
invite chain, MemberInfo) and let build_rejoin_delta bundle membership
atomically with the first message. This ensures the member always has
at least one message when added, preventing pruning.

Changes:
- CLI: accept_invitation no longer adds member to local state or sends
  membership UPDATE to the network
- UI: get_response handler no longer applies invitation delta or
  triggers ProcessRooms sync
- UI: can_send_message now checks self_authorized_member as fallback,
  matching can_participate behavior

Fixes #108

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sanity sanity merged commit 09926eb into main Feb 16, 2026
3 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.

feat: run six-peer regression test in River CI

1 participant

Comments