Repository navigation
feat(chat): open the invite key bundle for invite-joined members - #1144
Merged
Merged
Conversation
bmc08gt
force-pushed
the
feat/group-invites-key-bundle
branch
from
October 28, 2026 17:44
82b6293 to
7844d2c
Compare
bmc08gt
marked this pull request as ready for review
October 28, 2026 18:47
`invited_by` is required on `UserJoined.Invited`, so a set `systemInvitedBy` marks an invite join on its own and the extra column carried nothing. Schema 60 hasn't shipped (flipcash-2026.10.4 is on 54), so the column comes out of 60 rather than a new 61. An `invited_by` that doesn't parse now reads as a plain join, and `userJoinedViaInvite` takes a non-optional inviter. Adds a round-trip test for `canInvite`, which the scaffold already persists.
GetKeyEnvelope returns `invite_key_bundle` for a member who joined by invite and hasn't stored an envelope of their own. Both callers mapped that to `noEnvelope`, so the group's messages never opened. `GroupKeyEnvelopes` now gets a `GroupKeyMaterial` and opens the bundle through `SharedInviteCipher.openKeyBundle`, behind `GroupKeySealing` so tests can fake it. The creator's key is the resolved one, falling back to `wrapped_by_public_key`. An opened key is re-wrapped for the viewer with SetKeyEnvelope, best effort: if that write fails, the bundle opens again next launch. A bundle that fails any check throws `GroupKeyUnusable`, which the keyring surfaces as `ChatOpener.unusableKey` rather than folding it into "awaiting key". Messages stay covered and sending fails. This is the wrong-key state frame 4d draws. The notification extension's instance passes `opensInviteBundles: false`, so it never opens a bundle or writes an envelope. An invite-joined member's push stays undecrypted until the app has stored their own envelope.
…chemes as unsupported Follows chat/v1 model.proto on InviteKeyEnvelope: reject a bundle whose wrapped_by isn't Metadata.creator before resolving any key, prefer the creator key resolved outside GetKeyEnvelope, and fall back to wrapped_by_public_key when that fails. A bundle in a scheme this build doesn't know now throws UnsupportedKeyEnvelopeScheme, as an own envelope does, so the chat waits for a key instead of showing the wrong-key state.
bmc08gt
force-pushed
the
feat/group-invites-key-bundle
branch
from
October 29, 2026 01:16
fafa9bc to
6cd8545
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of three PRs for v1 invite links to private groups. #1149 (host surfaces) stacks on this one, and C (
feat/group-invites-joiner, joiner surfaces) stacks on #1149.The bundle is opened with
SharedInviteCipherfrom code-payments/code-android-app#1866, so this branch pinsflipcash-shared-coreto 0.17.0.Key bundle
A member who joined by invite and hasn't stored their own envelope gets
invite_key_bundlefrom GetKeyEnvelope. Before this PR,FlipClient.getKeyEnvelopeandChatNotificationClientboth turned that intonoEnvelope, so the group's messages never opened.GroupKeyEnvelopestakes aGroupKeyMaterial(own envelope or invite copy) and opens the bundle through a newGroupKeySealing.open, whichSharedCoreGroupKeySealerimplements withSharedInviteCipher.openKeyBundle.InviteKeyEnvelopein chat/v1model.proto:wrapped_byisn'tMetadata.creatoris rejected before any key is looked up.wrapped_by_public_keyfrom the same response, which the contract accepts.GroupKeyUnusable(failsAt:).ChatKeyringreports that as the newChatOpener.unusableKeyinstead of "awaiting key". Messages stay covered and sending throws. C reads this state to draw frame 4d.UnsupportedKeyEnvelopeScheme, as an own envelope in an unknown scheme already does. The chat waits for a key; it isn't marked wrong-key.Notification extension
Its
GroupKeyEnvelopespassesopensInviteBundles: false, so it never opens a bundle or writes an envelope. A push for an invite-joined member stays undecrypted until the app has stored the member's own envelope. Spec Decision 2 says the extension opens the bundle to decrypt only. To follow that instead, flip that one argument.Schema
systemViaInviteis dropped from schema 60 (Decision 3). It is unreleased:flipcash-2026.10.4ships 54.invited_byis required on the wire, so a setsystemInvitedByis enough to mark an invite join.userJoinedViaInvite.invitedByis no longer optional.canInvitewas already persisted by #1141, and a round-trip test now covers it.Tests
GroupKeyEnvelopesTestsadds 10 cases with a fake sealer:wrapped_byis missingwrapped_by_public_keyChatKeyringTestsadds the wrong-key opener, andSharedCoreGroupKeySealerTestscovers the unknown-scheme mapping.