fix(mobile): let the signed-in session clear a start fence a previous session left behind - #513
Merged
Merged
Conversation
… session left behind A device that had latched an unknown start outcome could still be unusable after installing the build that was supposed to fix it. Updating the app and signing in again mints a new session id; `sameOwner` compares user, session and device enrollment, so the retained record no longer matched the live owner, the snapshot became `unresolved-other-session`, and that screen carried no controls of any kind. Its guidance told the operator to "sign back into the session that made the request", which is not a thing a person can do: a session is not re-enterable. Start and join stayed blocked with no exit, on a build that already shipped the exit for the same-session case. `acknowledgeUnresolved` now requires only that the caller is the live signed-in owner, not that it also matches whoever wrote the record. Whoever holds the device and is signed in may clear it. Nothing about the record was ever verifiable by the original session anyway: it carries no proof of what the server did, and the active-event list it would have been checked against carries no request-specific idempotency correlation. Retaining it against an owner who can never return only disabled the device. `OtherSessionStartMutationAttention` gains the same explicit control the owner-visible screen has, and its guidance now says the earlier session has ended and cannot be signed back into rather than asking for the impossible. The screen still shows no classified event details from the other session, so the control reveals nothing: it is a clear, not a disclosure. The clear is disabled while offline, matching the owner-visible screen. Coverage: a record written by one session is cleared by the next sign-in on the same device and the following start is admitted; a signed-out device refuses the clear and keeps the record; the previous-session screen exposes the control, fires it once, no longer contains the impossible instruction, and still leaks no event identity; the control is disabled offline. Gate: Prettier, ESLint and typecheck clean across the repository; 6/6 test shards green and 61 mobile native tests pass.
|
Review: PR #513 — let the signed-in session clear an orphaned start fence Summary: clean diff. No IMPORTANT findings. What it does Correctness
Security / data handling
Nits (2)
No CI weakening, no migrations, no |
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.
The gap #512 left
#512 made an unknown start outcome clearable — but only when the retained record matched the live owner.
sameOwnercompares user id, session id, and device enrollment id. Installing the new build and signing in again mints a new session id, so the record no longer matched, the snapshot becameunresolved-other-session, and that screen had zero controls.Its guidance read:
A session is not re-enterable. That instruction cannot be followed. Start and join stayed blocked forever — on the very build that shipped the fix.
Observed in the field this morning on a device running the latest build.
Fix
acknowledgeUnresolvednow requires only that the caller is the live signed-in owner — not that it also matches whoever wrote the record. Whoever holds the device and is signed in can clear it.That is safe because the record was never verifiable by its original session either: it carries no proof of what the server did, and the active-event list it would be checked against carries no request-specific idempotency correlation (which is exactly why
resolveActivationFromFreshEventswas removed). Retaining it against an owner who can never return only disabled the device.OtherSessionStartMutationAttentiongains the same explicit control the owner-visible screen already has, and honest guidance in place of the impossible instruction. It still shows no classified event details from the other session — this is a clear, not a disclosure — and the control is disabled while offline.Coverage
Restoring the old owner-match guard makes the first test fail, which is the field case reproduced.
Gate
Prettier, ESLint, typecheck clean repo-wide. 6/6 test shards green; 61 mobile native tests pass. (One earlier shard failure was load flake while EAS builds were running — 581s vs 59s on a quiet machine; clean on re-run.)
Platform parity
Client-only logic and shared React Native UI — no platform-specific code. Needs verifying on iOS and Android.