Skip to content

fix: require pin when app resumes - #1298

Open
jvsena42 wants to merge 9 commits into
masterfrom
fix/724-lock-on-background
Open

jvsena42 wants to merge 9 commits into
masterfrom
fix/724-lock-on-background

Conversation

@jvsena42

@jvsena42 jvsena42 commented Sep 17, 2026

Copy link
Copy Markdown
Member

Fixes #724
Related to #1275

This PR locks the app behind the PIN screen whenever it returns from the background, instead of only at launch.

Description

  • Resets the authenticated state when the main activity stops (not on configuration changes), so returning to Bitkit shows the PIN pad when the PIN is enabled, a wallet exists and the node is not in recovery mode. The reset runs without suspending, reading a cached isPinEnabled state, so the lock is applied before onStop returns and cannot land after the activity has resumed.
  • Uses the activity onStop instead of ProcessLifecycleOwner, because the manifest removes the androidx startup provider, so the process lifecycle never emits ON_STOP in this app. Bitkit has a single UI activity, so the result is the same.
  • Shows the PIN overlay without a fade-in, so the first frame drawn on resume is the PIN pad and not wallet content.
  • Hides alert dialogs while locked, because AppAlertDialog is a real Dialog and draws in its own window above the PIN overlay. Bottom sheets are left composed: BottomSheetOverlayHost lives inside ContentView, which is composed before AuthCheckView in the same Surface, so the opaque PIN pad already covers them and skipping them would only throw away remember state such as a half-typed Trezor passphrase.
  • Clears focus and hides the keyboard when the lock engages, so an auto-focused field in a sheet left open (for example the hardware passphrase prompt) cannot bring the IME back over the PIN pad on resume.
  • Holds the new transaction sheet until unlock, so incoming payment details are not shown over the PIN screen.
  • Ignores amount warning confirmations while locked, so a tap on a dialog that has not redrawn yet cannot start a payment.
  • Keeps payment URIs opened while locked queued until the PIN is entered, then opens the Send flow. If a sheet was left open when the app was backgrounded, unlocking now closes it so the queued scan can run, instead of leaving the payment queued behind that sheet until the user happens to dismiss it. Send, Gift, Pin and the other high-priority sheets are still left alone, as is the QR scanner sheet, and the scan runs when they close.
  • Never auto-pays a scan that crossed the lock. A deferred scan that is still queued when the PIN is accepted skips QuickPay and lands on Send Confirm, because otherwise the unlock gesture authorises a payment the user never confirmed (isPinForPaymentsEnabled does not gate SendQuickPayScreen). Scanning while already unlocked still uses QuickPay as before.

Out of Scope

  • MainActivity: pressing back on the PIN pad still reaches the hidden UI and can dismiss an open in-window sheet (Send, Hardware) or cancel a hardware connect behind the lock. A BackHandler in the overlay is the likely fix; left for a follow-up.
  • MainActivity: toasts are drawn above the PIN overlay and can show while locked.
  • Dev settings, logs and Trezor dev screen raw AlertDialogs, the Create Subscription dropdown and tooltip popups are not hidden while locked. None of them move funds.
  • No grace period and no exemption for the system share chooser or file pickers. The share chooser only pauses the activity, so it does not lock.
  • The recents thumbnail still shows wallet content, as before.
  • The Enter PIN screen differs from Figma (no 000 key, logo and title position); this predates the change.
  • iOS: already clears PIN verification on entering the background. The journey below should be ported to bitkit-ios with this change.

Design

There is no design for when the lock triggers; the PIN screen itself is unchanged.

Preview

Before: HOME then relaunch goes straight to Home with no PIN.

before-no-lock-on-resume.mp4

After: HOME then relaunch shows the PIN pad; unlocking returns to Home.

after-lock-on-resume.mp4
Figma After: PIN on resume
figma-enter-pin after-pin-on-resume
Add Tag sheet while locked Add Tag sheet after unlock
sheet-hidden-while-locked sheet-back-after-unlock
Sign With Device while locked Sign With Device after unlock
hw-sign-locked hw-sign-after-unlock
Payment URI while locked Payment URI after unlock
deeplink-locked deeplink-after-unlock

Payment URI opened while backgrounded: PIN first, then Send Amount after unlock.

deeplink-pin-then-send.mp4

QA Notes

Manual Tests

  • 1a. PIN enabled → Home → HOME key → reopen Bitkit: PIN pad shows before any wallet content.
    • 1b. Enter PIN: returns to Home.
  • 2. PIN enabled → toggle dark mode or rotate while unlocked: no PIN prompt.
  • 3. PIN enabled → Receive → Share → back from the system chooser: Receive sheet still open, no PIN prompt.
  • 4a. PIN enabled → Activity Detail → Tag → HOME → reopen: only the PIN pad is drawn, no Add Tag sheet above it.
    • 4b. Enter PIN: Add Tag sheet is back.
  • 5. PIN enabled → Send with Trezor source → Sign With Device → HOME → reopen → enter PIN: Sign With Device screen unchanged.
  • 6. PIN enabled → HOME → open a bitcoin: or lightning: URI: PIN pad shows with no Send sheet; after PIN, Send opens with the URI's amount.
  • 7. PIN enabled → Send amount triggering a sanity warning → HOME → reopen: warning dialog hidden until PIN is entered, then shown again.
  • 8. PIN and biometrics enabled → HOME → reopen: biometric prompt shows; success unlocks.
  • 9. regression: PIN disabled → HOME → reopen: Home shows with no lock.
  • 10. regression: PIN enabled → kill and relaunch app: PIN pad shows as before.

Steps 1-6 and 9 were run on an emulator (debug build). Step 5 stopped at Sign With Device without a connected Trezor, and step 6 used a bitcoin: URI. Step 8 was not run because no fingerprint was enrolled. The journey below covers steps 1, 2, 4 and 6, and is committed at journeys/security/pin-lock-on-resume.xml.

journeys/security/pin-lock-on-resume.xml
diff --git a/journeys/security/pin-lock-on-resume.xml b/journeys/security/pin-lock-on-resume.xml
new file mode 100644
index 000000000..924308ea5
--- /dev/null
+++ b/journeys/security/pin-lock-on-resume.xml
@@ -0,0 +1,39 @@
+<journey name="pin lock on resume">
+  <description>
+    Verifies that with the app PIN enabled, sending Bitkit to the background locks it: returning
+    to the app shows the PIN pad before any wallet content, a sheet left open is hidden while
+    locked and comes back after unlock, a configuration change does not lock, and a payment URI
+    opened while backgrounded waits for the PIN before the Send flow opens. Matches iOS, which
+    clears the PIN verification when the scene enters the background, with no grace period.
+
+    Precondition: onboarded dev wallet with the app PIN enabled (Settings > Security) and a known
+    PIN, biometrics off, unlocked, on the wallet home screen. The wallet needs a savings balance
+    above 10 000 sats and at least one activity item — with an empty balance the last payment URI
+    is rejected with an insufficient-savings toast instead of opening Send, and with no activity
+    there is no row to open for the Add Tag steps. Never enter a wrong PIN more than once;
+    exhausting attempts leads to the forgot-PIN wallet reset.
+  </description>
+  <actions>
+    <action>Verify the wallet home screen is visible (testTag "Send")</action>
+    <action>Run adb shell input keyevent KEYCODE_HOME and wait 3 seconds</action>
+    <action>Run adb shell am start -n to.bitkit.dev/to.bitkit.ui.MainActivity</action>
+    <action>Verify the PIN pad is visible (testTag "PinPad") with the text "Please enter your PIN code" and keys (testTag "N1")</action>
+    <action>Enter the PIN with the number pad keys (testTags "N0" to "N9")</action>
+    <action>Verify the wallet home screen is visible again (testTag "Send")</action>
+    <action>Run adb shell cmd uimode night yes, wait 5 seconds, then run adb shell cmd uimode night no and wait 5 seconds</action>
+    <action>Verify the wallet home screen is visible and the PIN pad is not shown</action>
+    <action>Tap the first activity item on the home screen (testTag "ActivityShort-0"), then tap Tag (testTag "ActivityTag")</action>
+    <action>Verify the Add Tag sheet is visible (testTag "TagInput")</action>
+    <action>Run adb shell input keyevent KEYCODE_HOME and wait 3 seconds</action>
+    <action>Run adb shell am start -n to.bitkit.dev/to.bitkit.ui.MainActivity</action>
+    <action>Take a screenshot and verify only the PIN pad is drawn, with no Add Tag sheet above it</action>
+    <action>Enter the PIN with the number pad keys</action>
+    <action>Verify the Add Tag sheet is visible again (testTag "TagInput"), then press back until the wallet home screen is visible</action>
+    <action>Run adb shell input keyevent KEYCODE_HOME and wait 3 seconds</action>
+    <action>Run adb shell am start -a android.intent.action.VIEW -d "bitcoin:bcrt1qh6k3khs7qz04a9p5eam6v48nlug9d38x4rgxrn?amount=0.0001" to.bitkit.dev</action>
+    <action>Verify the PIN pad is visible and the Send amount screen is not shown</action>
+    <action>Enter the PIN with the number pad keys</action>
+    <action>Verify the Send amount screen opens (testTag "SendNumberField") showing 10 000 sats</action>
+    <action>Press back to close the Send sheet and verify the wallet home screen is visible</action>
+  </actions>
+</journey>

Automated Checks

  • Unit tests added in AppViewModelSendFlowTest.kt: lockOnBackground locks when the PIN is enabled, locks without waiting for a suspension, and does nothing when the PIN is disabled, no wallet exists or recovery mode is on; a lightning: URI received after a lock stays queued and opens Send Confirm after unlock; an amount warning confirmation is ignored while locked and accepted after unlock; a URI received with a Receive sheet open closes that sheet on unlock and opens Send Confirm; a URI received with a Pin sheet open leaves it untouched and runs the scan when it is dismissed; a URI deferred by the lock skips QuickPay and opens Send Confirm.
  • Unit tests modified in AppViewModelSendFlowTest.kt: two warning tests now authenticate first, since confirmations before authentication are rejected; QuickPay eligible scan remains deferred until authenticated becomes QuickPay eligible scan remains deferred and confirms after authenticating, since a scan that crossed the lock no longer auto-pays.
  • Hiding dialogs while locked has no automated test; it was checked on device.
  • Ran locally: just compile, just test, just lint.

@jvsena42 jvsena42 self-assigned this Sep 17, 2026
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

This PR is not safe to merge until authentication is synchronously gated when the activity stops, preventing wallet content from appearing before the asynchronous checks complete.

Findings

  1. P1 Security Lock happens after suspension

Summary

This PR locks PIN-enabled wallets when MainActivity stops, suppresses window-based sheets and dialogs while locked, delays transaction and payment UI until authentication, and adds send-flow tests.

  • Adds activity-stop-driven authentication reset.
  • Makes the PIN overlay appear without an enter animation.
  • Temporarily removes bottom sheets, alerts, and transaction details while locked.
  • Queues payment intents and rejects stale warning confirmations until unlock.
  • The asynchronous eligibility check leaves a resume-time exposure window before authentication is cleared.

Reviews (1) · Last reviewed commit: "fix: lock on activity stop and show pin ..."

Comment thread app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt Outdated
@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Regtest APK

Built from 52e6f0e (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

jvsena42 and others added 4 commits September 17, 2026 20:58
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42
jvsena42 force-pushed the fix/724-lock-on-background branch from 166d1c8 to 0961754 Compare September 18, 2026 00:04

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested — 1 HIGH/MEDIUM finding(s) inline. (Posted as a comment because GitHub does not allow requesting changes on your own PR.)

Inline: MEDIUM — Payment link opened while locked with a sheet open stays queued after the PIN and fires whenever that sheet is later closed; LOW — BottomSheet early return while locked drops state remembered inside the content lambda; the sheet was already under the PIN overlay

Checked: Traced MainActivity.onStop -> AppViewModel.lockOnBackground: it is synchronous (cached isPinEnabled StateFlow, walletExists(), isRecoveryMode.value), skipped on isChangingConfigurations, and a no-op for PIN-disabled users; there is no separate pin-on-launch setting on Android (SettingsStore has only isPinEnabled, isBiometricEnabled, isPinForPaymentsEnabled). The in-app biometric prompt uses BIOMETRIC_STRONG only (BiometricPrompt.kt:114), so no device-credential activity is launched and the prompt cannot stop MainActivity; the USB permission dialog, camera permission dialog and the share chooser are dialog-themed activities that only pause it, while file pickers do stop it, which the PR body lists as accepted. AuthCheckView (MainActivity.kt:177-189) is composed after ContentView (161-175) inside the same Surface with blockPointerInputPassthrough, so it covers the in-window SheetHost (Send/Hardware/Receive) and the BottomSheetOverlayHost at ContentView.kt:760, and payment/NFC deeplinks are deferred by launchScan (AppViewModel.kt:2223-2232) while locked; a payment in flight keeps running under the overlay and its result sheet is in-window. ForgotPinSheet renders through authSheetOverlayState outside the LocalIsAppLocked provider (MainActivity.kt:191-200), so the early return in BottomSheet does not hide it on the PIN screen. Both greptile threads are resolved at 0961754: the lock no longer suspends, and the new test asserts the flag without advanceUntilIdle. No bitkit-ios twin PR was found by title search; the PR body says iOS already clears PIN verification on background.

Comment thread app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt
Comment thread app/src/main/java/to/bitkit/ui/components/BottomSheet.kt Outdated
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no HIGH/MEDIUM findings at head 6a1c0c825. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Follow-up on 6a1c0c8: both earlier findings are fixed (lock-deferred link now closes the open sheet on unlock and skips QuickPay; passphrase no longer discarded). Follow-up at 6a1c0c8. MEDIUM (4046216525) is fixed: setIsAuthenticated(true) (AppViewModel.kt:409-422) marks the queued scan, then calls hideSheet() when _currentSheet is non-null, has a deferred scan and is neither high-priority nor QrScanner (425); hideSheet (4753-4791) clears the sheet and flushes, and flushDeferredScan (2406-2427) launches with preserveUntilComplete and the stored suppressQuickPay. Traced Receive/Widgets/Backup/Hardware/TimedSheet open at lock (closed, scan runs to Send Confirm), Send/Gift/Pin open (kept, scan runs on dismiss to Confirm, the option offered in the thread), QrScanner open (kept, existing scanner-result tests pin the flush), two links queued (last wins at enqueueDeferredScan 2364-2389, mark applied to the survivor), link arriving with the PIN pad up (launchScan 2254 enqueues, same path), a job suspended at lock time (deferLockedScan 2337 re-enqueues, mark at unlock covers it), process death (intent re-delivered in onCreate, queued at auth false, flushed by the PIN), and PIN disabled (lockOnBackground 4862 no-ops, scans run unlocked with suppressQuickPay=false). QuickPay: handleQuickPayIfApplicable (3665-3676) returns false only when suppressQuickPay is true, which is set solely by markDeferredScanUnlocked (427-433) or propagated from a queued scan; every user-initiated entry (onScanResult, scanner sheet, clipboard, address continue) passes the default false, so normal QuickPay is unchanged; the only unmarked flush is resetIsAuthenticatedStateInternal with PIN disabled at cold start/post-migration, which is the master behaviour. LOW (4046216534) is fixed by dropping the check from BottomSheet.kt (72-90); all BottomSheet entries render in ContentView's BottomSheetOverlayHost (ContentView.kt:760) through SheetHost/BottomSheetScaffold in-window, ContentView is composed before AuthCheckView inside the same Material3 Surface (MainActivity.kt:161-189), AuthCheckView is fillMaxSize/black/blockPointerInputPassthrough (AuthCheckView.kt:90-95), no Dialog/Popup/ModalBottomSheet hosts exist, and AppAlertDialog keeps its window guard (AppAlertDialog.kt:75); the new LaunchedEffect (MainActivity.kt:165-170) clears focus and hides the IME on lock so a focused TextInput in AddTag or HwPassphrasePromptSheet cannot restore the keyboard over the NumberPad. Widening of the accepted back-press limitation: BottomSheet-based sheets now also stay in composition while locked, so back on the PIN pad reaches their SheetHost BackHandler as it already did for Send/Hardware (PR body lists this as out of scope). Tests: payment deeplink received with a sheet open closes it on unlock and payment deeplink deferred by the lock skips QuickPay on unlock fail at 0961754 (Receive stays open / quickPayData set); the renamed QuickPay test asserts Confirm and fails on the old assertion; the high-priority test passes on both and only pins intended behaviour. Locals.kt is a doc comment. Earlier clean items (synchronous lockOnBackground, isChangingConfigurations skip, amount-warning gate at 4935, transaction sheet gated on isAuthenticated at MainActivity.kt:220) are untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42
jvsena42 requested a review from ovitrif September 18, 2026 13:26

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no HIGH/MEDIUM findings at head 5fb363325. (Posted as a comment because GitHub does not allow approving your own PR.)

Inline: LOW — Deeplink step would pass with the deferred-scan fix reverted

Checked: Round 3 (5fb3633, new journey): Round 3 covers only the new journeys/security/pin-lock-on-resume.xml and the two README rows. Every testTag the journey names exists at head: Send (TabBar.kt:135), PinPad (AuthCheckView.kt:143), N0-N9 via NumberPad's default "N$text" tag, ActivityShort-0 (ActivityListSimple.kt:52, rendered on Home), ActivityTag (ActivityDetailScreen.kt:648), TagInput (ActivityAddTagSheet.kt:68) and SendNumberField (SendAmountScreen.kt:260); "Please enter your PIN code" matches security__pin_enter. The preconditions match the lock conditions in lockOnBackground (PIN enabled, wallet exists, not recovery mode), and biometrics off keeps AuthCheckView on the PinPad branch. The uimode toggle really does exercise the isChangingConfigurations skip in MainActivity.onStop, because MainActivity declares no configChanges and is recreated. The payment URI uses a valid regtest bech32 address; with savings above 10 000 sats, onScanOnchain goes to SendRoute.Amount while unlocked, and launchScan defers it while locked. No bitkit-ios twin PR exists, and the cross-platform table records the journey as not ported yet.

Comment thread journeys/security/pin-lock-on-resume.xml
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no blocking HIGH/MEDIUM findings at head 510f4b098. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Round 4 (510f4b0): the journey LOW is fixed. Round 4 (510f4b0) covers only journeys/security/pin-lock-on-resume.xml. It answers the earlier LOW (4047397642): after returning Home the journey now taps Receive (testTag "Receive", TabBar.kt:156, which calls showSheet(Sheet.Receive) at ContentView.kt:729-731) and verifies "ReceiveScreen" (ReceiveSheet.kt:144) before backgrounding and firing the bitcoin: URI. After the PIN it asserts "SendNumberField" is shown and "ReceiveScreen" is gone. At head, setIsAuthenticated(true) (AppViewModel.kt:409-423) sees a tracked Receive sheet with a deferred scan, canCloseSheetForDeferredScan (425) returns true because Receive is neither high priority nor QrScanner, and hideSheet() closes it and flushes the scan into Send Amount. With the fix reverted, the scan stays queued behind the open Receive sheet, so both halves of that assertion fail. The description now states why the Add Tag sheet does not count and why the QuickPay path is left to AppViewModelSendFlowTest.kt. No new findings.

ovi-reviewer[bot]

This comment was marked as resolved.

ovi-reviewer[bot]

This comment was marked as resolved.

ovi-reviewer[bot]

This comment was marked as resolved.

@ovi-reviewer ovi-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: ✅ Approve


Reaudit: diff 1 file.
Counterpart synonymdev/bitkit-ios#722: not compared.

Findings:
N/A

Audit:
Already done in comment.

QA: emu-1 redroid container on Android 15 (API 35), dev build 2.4.1 (188) at 52e6f0e

  1. passed: Backgrounding and reopening showed the PIN pad before wallet content.

    Test 1:
    **1a.** PIN enabled → Home → HOME key → reopen Bitkit: PIN pad shows before any wallet content.
    1.mp4
  2. passed: PIN returned Home; dark-mode recreation stayed unlocked.

    Test 2:
    PIN enabled → toggle dark mode or rotate while unlocked: no PIN prompt.
    2.mp4
  3. passed: Returning from Android share kept Receive open without a PIN prompt.

    Test 3:
    PIN enabled → Receive → Share → back from the system chooser: Receive sheet still open, no PIN prompt.
    3.mp4
  4. passed: PIN hid Add Tag; Trezor Sign With Device returned unchanged after unlock.

    Test 5:
    PIN enabled → Send with Trezor source → Sign With Device → HOME → reopen → enter PIN: Sign With Device screen…
    5.mp4
    5-2.mp4
  5. passed: Unlock restored Add Tag and deferred the payment URI until PIN.

    Test 6:
    PIN enabled → HOME → open a `bitcoin:` or `lightning:` URI: PIN pad shows with no Send sheet; after PIN, Send…
    6.mp4
  6. passed: PIN hid the balance warning; unlock restored it.

    Test 7:
    PIN enabled → Send amount triggering a sanity warning → HOME → reopen: warning dialog hidden until PIN is…
    7.mp4
  7. ⚠️ hardware absent: The redroid device has no physical biometric sensor or service.

    Test 8:
    PIN and biometrics enabled → HOME → reopen: biometric prompt shows; success unlocks.
    8.mp4
  8. passed: With PIN disabled, backgrounding and reopening returned Home unlocked.

    Test 9:
    `regression:` PIN disabled → HOME → reopen: Home shows with no lock.
    9.mp4
  9. passed: Cold relaunch with PIN enabled showed the PIN pad.

    Test 10:
    `regression:` PIN enabled → kill and relaunch app: PIN pad shows as before.
    10.mp4

Ticked Manual Tests 1a, 1b, 2, 3, 4a, 4b, 5, 6, 7, 9, and 10.

Tip

Test 1 worth a journey:

  • Verify the wallet Home screen is visible
  • Send Bitkit to the background
  • Reopen Bitkit
  • Verify the PIN pad appears before wallet content

Test 2 worth a journey:

  • Enter the PIN
  • Verify the wallet Home screen returns
  • Switch dark mode on and then off
  • Verify Home stays visible without a PIN prompt

Test 3 worth a journey:

  • Open Receive
  • Tap Share
  • Return from the system share activity
  • Verify Receive stays open without a PIN prompt

Test 6 worth a journey:

  • Enter the PIN
  • Verify the Add Tag sheet returns
  • Go back to the wallet Home screen
  • Open Receive
  • Send Bitkit to the background
  • Open the bitcoin payment link
  • Verify the PIN pad hides Send
  • Enter the PIN
  • Verify Send opens with 10 000 and Receive is closed

Test 7 worth a journey:

  • Enable the send amount warning
  • Open a 160 000 sat bitcoin payment
  • Continue to confirmation
  • Swipe to pay
  • Verify the balance warning remains visible for 30 seconds
  • Send Bitkit to the background
  • Reopen Bitkit
  • Verify the PIN pad hides the warning
  • Enter the PIN
  • Verify the same warning returns

Test 9 worth a journey:

  • Disable the app PIN
  • Verify the wallet Home screen is visible
  • Send Bitkit to the background
  • Reopen Bitkit
  • Verify Home returns without a PIN prompt

Test 10 worth a journey:

  • Enable the app PIN
  • Verify the wallet Home screen is visible
  • Force-stop Bitkit
  • Launch Bitkit
  • Verify the PIN pad appears

Coverage:
QA: 11 of 12 manual tests passed


Reviewed by gpt-5.6-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest · audit (author or owner)

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.

PIN should be required on app restart + resume

1 participant