Skip to content

Force recovery key (4S) setup on first device when force_verification is set#33677

Open
FantasticoFox wants to merge 1 commit into
element-hq:developfrom
inblockio:force-first-device-recovery
Open

Force recovery key (4S) setup on first device when force_verification is set#33677
FantasticoFox wants to merge 1 commit into
element-hq:developfrom
inblockio:force-first-device-recovery

Conversation

@FantasticoFox
Copy link
Copy Markdown

force_verification is meant to guarantee a recoverable encrypted identity, but it currently only gates on cross-signing readiness. On a first device the transparent InitialCryptoSetup sets up cross-signing without ever creating secret storage (4S), so shouldForceVerification() returns false and the user reaches the app with no recovery key; losing that device then strands their identity.

Make the gate also require secret-storage readiness, and when a first device has cross-signing ready but no 4S, drive the existing recovery-key creation flow (accessSecretStorage) before login completes. The reset is gated on secretStorage.hasKey() (forceReset: !hasExisting4S) so a returning user whose 4S exists server-side but is not yet cached on this device is taken through the non-destructive unlock path instead of having their recovery key and key backup reset. Cross-signing is never regenerated.

If the user cancels or the attempt fails, offer an explicit Retry / sign-out choice rather than silently leaving them stranded on the (now inert) setup screen, so the requirement can never be slipped past and the user can never be trapped with no way forward.

No behavior change when force_verification is unset.

Checklist

… is set

`force_verification` is meant to guarantee a recoverable encrypted identity, but
it currently only gates on cross-signing readiness. On a first device the
transparent InitialCryptoSetup sets up cross-signing without ever creating secret
storage (4S), so `shouldForceVerification()` returns false and the user reaches
the app with no recovery key; losing that device then strands their identity.

Make the gate also require secret-storage readiness, and when a first device has
cross-signing ready but no 4S, drive the existing recovery-key creation flow
(`accessSecretStorage`) before login completes. The reset is gated on
`secretStorage.hasKey()` (`forceReset: !hasExisting4S`) so a returning user whose
4S exists server-side but is not yet cached on this device is taken through the
non-destructive unlock path instead of having their recovery key and key backup
reset. Cross-signing is never regenerated.

If the user cancels or the attempt fails, offer an explicit Retry / sign-out
choice rather than silently leaving them stranded on the (now inert) setup
screen, so the requirement can never be slipped past and the user can never be
trapped with no way forward.

No behavior change when `force_verification` is unset.

Signed-off-by: Tim Bansemer <tim.bansemer@inblock.io>
@FantasticoFox FantasticoFox requested a review from a team as a code owner May 30, 2026 11:51
@FantasticoFox FantasticoFox requested review from Half-Shot and dbkr May 30, 2026 11:51
@github-actions github-actions Bot added the Z-Community-PR Issue is solved by a community member's PR label May 30, 2026
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 30, 2026

CLA assistant check
All committers have signed the CLA.

@FantasticoFox FantasticoFox reopened this May 30, 2026
@Half-Shot Half-Shot requested review from a team and andybalaam and removed request for a team May 30, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Z-Community-PR Issue is solved by a community member's PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants