Sealed group membership changes, and secrets that survive a reinstall #28

Merged
paulhitt merged 1 commits from 1-sealed-rosters-android into main 2026-08-31 15:12:31 +00:00
paulhitt commented 2026-08-31 15:10:46 +00:00 (Migrated from gitlab.com)

Closes #1

125 lines that had been sitting uncommitted and never built. They build.

Session.updateSealedGroupMembers

Owner-only, and refused locally rather than sent for the relay to reject — we
hold the owner signing key only if we created the group.

⚠️ The version must increase. A roster signature stays valid for ever, so a stale
roster could otherwise be replayed to re-add somebody who was just removed, with
a signature that genuinely verifies.

Existing members keep their tags; only newcomers get fresh ones. Reusing a tag
would hand somebody the token another member had held.

Vault export/import

🔴 Without this a restored device loses its sealed groups for good. The relay
cannot tell you what you are a member of — that is the point of sealing — so the
tag is the only way to fetch a group and the key the only way to read it. A
backup carrying the messages but not these restores a device that can see old
conversations and can never rejoin the groups they came from.

Import fills gaps only, the same rule the group names use: a backup is older than
the device by definition, and a roster version that went backwards would be
refused by the relay on the next rewrite anyway.

Verification

:engine:test          BUILD SUCCESSFUL   (SealedRosterTest incl. 2 new backup tests)
:app:assembleDebug    BUILD SUCCESSFUL

Not in this MR

The app still never calls createSealedGroup — filed as #3, and that is what
actually matters, since the iPhone build is still with Apple and Android is the
only route to sealing paulhitt/flamenet-relay#2 rosters.

Closes #1 125 lines that had been sitting uncommitted and never built. They build. ### `Session.updateSealedGroupMembers` Owner-only, and refused locally rather than sent for the relay to reject — we hold the owner signing key only if we created the group. ⚠️ The version must increase. A roster signature stays valid for ever, so a stale roster could otherwise be replayed to re-add somebody who was just removed, with a signature that genuinely verifies. Existing members keep their tags; only newcomers get fresh ones. Reusing a tag would hand somebody the token another member had held. ### Vault export/import 🔴 **Without this a restored device loses its sealed groups for good.** The relay cannot tell you what you are a member of — that is the point of sealing — so the tag is the only way to fetch a group and the key the only way to read it. A backup carrying the messages but not these restores a device that can see old conversations and can never rejoin the groups they came from. Import fills gaps only, the same rule the group names use: a backup is older than the device by definition, and a roster version that went backwards would be refused by the relay on the next rewrite anyway. ### Verification ``` :engine:test BUILD SUCCESSFUL (SealedRosterTest incl. 2 new backup tests) :app:assembleDebug BUILD SUCCESSFUL ``` ### Not in this MR The app still never *calls* `createSealedGroup` — filed as #3, and that is what actually matters, since the iPhone build is still with Apple and Android is the only route to sealing paulhitt/flamenet-relay#2 rosters.
paulhitt commented 2026-08-31 15:12:31 +00:00 (Migrated from gitlab.com)

mentioned in commit 9ae7b5473d

mentioned in commit 9ae7b5473d81c4e4df3d14a4c8242af058e2789a
paulhitt (Migrated from gitlab.com) merged commit 9ae7b5473d into main 2026-08-31 15:12:32 +00:00
Sign in to join this conversation.