rubyforgood / rubyforgood/alongwithyou
Journal contents appear in the iOS app-switcher snapshot; unlock gate only re-locks on background
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 9
- Forks
- 4
- Avg merge
- 9h 34m
- Merged PRs (30d)
- 16
Description
Description
UnlockGate re-locks on background only (mobile/src/components/unlock-gate.tsx:105-109):
const subscription = AppState.addEventListener('change', (next) => {
if (next === 'background') {
setState({ status: 'locked', message: null });
}
});
On iOS the app transitions to inactive before background, and the OS captures the app-switcher snapshot during that window. The gate has not re-locked yet, so the card shows journal content — and iOS persists those snapshots to disk. Swiping up then displays the journal to anyone holding the phone, which is the exact scenario the comment above that listener describes: "hand someone an already-open phone and the journal is simply there."
Locking on inactive is not the fix — inactive also fires when the biometric prompt and other system alerts appear, so the gate would fight its own unlock flow. The usual approach is an opaque cover rendered while inactive, leaving lock state untouched, with the existing re-lock on background unchanged.
Two smaller items in the same listener, worth folding in:
- A device with no lock is given an impossible instruction. The listener sets
{status:'locked'}regardless of the previous state, so after backgrounding, a phone with no passcode or biometric renders "Your journal is locked / Unlock with your phone to open it." The user has to tap Unlock, land back on "Your phone has no lock set", and tap Continue — every time they switch apps. Verified with a test against the current component. This is independent of what #131 decides: if ADR 0018 settles on the currently built "continue with an explanation", the wrong copy survives the decision. - No re-prompt on return to foreground. After a re-lock the user must tap Unlock;
attemptUnlockonly runs on mount. Defensible — it avoids prompting mid-animation — but it is an extra tap every time, for the audience the ADRs describe as finding phones difficult. Worth being a decision rather than a default.
Acceptance Criteria
- Journal content is not visible in the iOS app-switcher card
- The cover does not interfere with the biometric prompt, which also drives the app
inactive - Re-lock on
backgroundcontinues to work as it does today - A device with no lock configured is never told to "unlock with your phone"
- Whether the gate re-prompts automatically on return to foreground is decided and recorded
- The feature/s being implemented are covered by unit tests - If not, create tests for them on this ticket
Additional Info and Resources
- Android's recents screenshot is a separate mechanism (
FLAG_SECURE); worth deciding at the same time whether it is in scope for this ticket - Related: #131 covers the product question of what a no-lock device should be allowed to do; the display bug above is a defect in the current placeholder regardless of that answer
- Needs a physical device or simulator with a dev build — the snapshot behaviour cannot be verified in jest
- Found in review of #128
QA
- On a device with a dev build: open the app, unlock, swipe up to the app switcher — the card must not show journal content
- Return to the app and confirm the gate behaves correctly: no stuck cover, no double prompt
- On a device with no passcode set: unlock, background, return — the copy must make sense
-
cd mobile && npm test— green
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in mobile/src/components/unlock-gate.tsx, especially the AppState listener at lines 105-109, and review ADR 0018 plus issue #131 for no-lock behavior. Run cd mobile && npm test, then use a dev build or simulator to verify the inactive cover, background re-lock, no-lock copy, and foreground behavior; done means the listed acceptance and QA checks pass without exposing journal content.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, typescript
- Domain
- mobile, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100