Skip to content

fix(lock): lock at launch once the auto-lock time has passed (#510) - #593

Merged
kipavy merged 1 commit into
devfrom
fix/lock-cold-start-510
Oct 9, 2026
Merged

kipavy merged 1 commit into
devfrom
fix/lock-cold-start-510

Conversation

@kipavy

@kipavy kipavy commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #510, from the reporter's comment: force-closing the app and reopening it after the auto-lock timeout did not lock.

Cause

useSessionExpiration kept the last activity only in memory and reset it at mount. A cold start went straight to auto-login, so the timeout was never checked across a restart. #591 hides this on Android once the key is sealed, because every launch prompts. It still applies before the first seal, to no-password accounts, with system authentication off, and on desktop.

Change

  • Rust LastActive stores the last user activity in <config_dir>/last-active (app_lock_touch / app_lock_last_active), written synchronously so a kill right after backgrounding keeps it.
  • The hook writes it when activity changes (at most every 5 s), on mount, and when the app is hidden.
  • lockOnLaunchIfIdle() runs once per process (a sessionStorage flag, so location.reload() is skipped). It locks when the effective timeout (including the org policy) has passed, when Immediately is set, or when no activity was ever recorded (fails closed). It uses the same lock kind and action as lockApp, now shared through lockKind() / engage().
  • Splash: if Lock vault applies, it goes to the unlock page without auto-login. With Lock screen, the vault opens behind the overlay, the same as a lock that survived a restart.

#592: Lock vault on a local account with no secrets.enc

  • SecretsStore::unlock writes the empty vault when the file is missing (best-effort, logged). From then on there is always a file to check a password against. Before this, with no file, keyThatOpensVault accepted any password.
  • hasAccountToUnlock now uses canLockVault(mode), generalising feat(lock): org-enforced lock policy (#510) #581's server-mode check, so an account locked before this fix gets the unlock page, not onboarding.

Closes #592

Behaviour changes

  • Desktop: quitting and relaunching after the auto-lock time now asks for the master password, or system authentication when it is on. Previously the timer reset at every launch.
  • Immediately: every cold launch locks.
  • First launch after updating, with a timeout set: locks once (no activity recorded yet).

Testing

  • vitest: appLock (8 new), useSessionExpiration (2 new), SplashScreen.appLock (3 new); lock, account and binding suites 214/214.
  • cargo: app_lock 10/10, storage::secrets 42/42 (new: an unlocked vault with no file writes one that only its key opens).
  • tsc --noEmit clean.
  • Not run in the live app or on a device yet. No UI surface changed: the existing unlock page and lock overlay just appear at launch.

The idle timer only lived in memory, so force-closing the app and reopening
it after the timeout signed straight back in. The last activity is now
written to `<config_dir>/last-active` (on change, at most every 5 s, and when
the app is hidden). A fresh launch past the timeout, or any launch with
Immediately, applies the configured lock before auto-login. Reloads of the
running app are not launches. With no recorded activity the launch fails
closed.

A local account that never wrote a secret had no secrets.enc. Lock vault
then landed on onboarding, and with no file to check, any password would
have opened it. Unlocking now writes the empty vault when it is missing, and
the splash treats any local or cloud account as one to unlock.

Closes #592
@kipavy
kipavy merged commit 6429ddf into dev Oct 9, 2026
5 checks passed
@kipavy
kipavy deleted the fix/lock-cold-start-510 branch October 9, 2026 14:02
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