Skip to content

feat(mobile): A3 — UnlockPin (PIN/biometric unlock, lockout UI, key-invalidated recovery)#29

Merged
temrjan merged 9 commits into
mainfrom
feat/stage2-a3-unlock-locked
Jul 6, 2026
Merged

feat(mobile): A3 — UnlockPin (PIN/biometric unlock, lockout UI, key-invalidated recovery)#29
temrjan merged 9 commits into
mainfrom
feat/stage2-a3-unlock-locked

Conversation

@temrjan

@temrjan temrjan commented Jul 6, 2026

Copy link
Copy Markdown
Member

Stage-2 slice A3 — the locked-phase unlock screen, closing the Stage-2 loop: create (A2) → cold start → unlock.

What

  • UnlockPin screen (flipbook "Вход — Locked" frame, English strings): PIN path via the A1c ladder, biometric-circle shortcut, 1s lockout countdown (persists across force-quit), 200ms spinner threshold.
  • deviceWallet.unlock single-flight (mirrors commitWallet; sync NoWalletError precondition outside the slot).
  • walletStore.unlock action publishing the live UnlockedSession; no reconcile (A1c contract).
  • PinKeypad disabled prop (lockout/verifying), A2 callers untouched.
  • KeyPermanentlyInvalidated → recovery banner → verbatim-tested confirm (Delete & start over) → wipeWallet → onboarding. Never auto-wipes.
  • Keychain mock extended (getSupportedBiometryType, BIOMETRY_TYPE, hang helper); keystoreSecret docstring fixed (save-side auth prompt — carry-over feat(mobile): ubrn FFI bridge + on-device proof-of-life (Stage 2 D1) #20 resolved).

Evidence

  • Gates (exact CI commands, local — CI is workflow_dispatch-muted, carry-over build(deps): bump actions/upload-artifact from 4.6.2 to 7.0.1 #3/docs(agents): add TypeScript + React Native rules (Codex Compact) #16): npm run typecheck clean, npm run lint 0 errors, npm test -- --coverage 150/150 (was 125). Coverage: stores 100%, UnlockPin 93%. gradlew assembleDebug proven by the smoke build.
  • Red→green proven: 3 red runs + 4 mutations (error-toggle, lock predicate, KPI predicate ×2), each failing exactly its guarding tests.
  • Device smoke PASS (Captain-witnessed, JFLFG6MZSSL7WCF6): lock screen live, shake, lockout+countdown+force-quit persistence, PIN→OS sheet→Home, biometric circle→Home. KPI recovery UNVERIFIED-on-device (destructive to provoke; jest-proven).
  • Gate-1 APPROVED WITH NITS; Gate-2 APPROVED WITH NITS, M1–M6 applied in-round (delta in core/.claude/reports/2026-07-06-stage2-a3-unlock-locked.md).

Carry-overs recorded: #21 (import inert until A4 — go-live blocker), #23 (no-biometrics unlock/PIN-reset path — gate before real users).

Spec: core/.claude/specs/2026-07-06-stage2-a3-unlock-locked.md

@temrjan temrjan merged commit 32f0621 into main Jul 6, 2026
@temrjan temrjan deleted the feat/stage2-a3-unlock-locked branch July 6, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant