Skip to content

Journal contents appear in the iOS app-switcher snapshot; unlock gate only re-locks on background #136

Description

@Jberma23

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 Decide unlock behaviour on a device with no lock screen (ADR 0018) #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; attemptUnlock only 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 background continues 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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds-verificationStatic review claim not yet confirmed at runtimeseverity:significantShould be fixed before shipping

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions