[PM-42103] feat: Add opt-in toggle for keeping vault unlocked until timeout - #3004
Conversation
🤖 Bitwarden Claude Code ReviewOverall Assessment: APPROVE Reviewed the opt-in "Keep vault unlocked until timeout" toggle stacked on the feature-flagged session key sharing work: the new Code Review Details
PR Metadata Assessment
|
| ) | ||
| .disabled(store.state.isSessionTimeoutActionDisabled) | ||
| } | ||
| if store.state.isSessionKeySharingFeatureEnabled { |
There was a problem hiding this comment.
Details and fix
Visibility is gated only on isSessionKeySharingFeatureEnabled, but the capture path is additionally gated on the timeout: captureUserSessionKeyIfAllowed returns early unless timeoutValue.allowsUserSessionKeySharing, which is false for .immediately, .onAppRestart, and .never.
So a user on "Immediately" or "On app restart" can switch this on, setUserSessionKeySharingEnabled persists "true", no key is ever captured, and the UI shows an enabled setting with no effect and no feedback. The same mismatch happens in reverse: changing the timeout to one of those values deletes .userSessionKey (AuthRepository.setVaultTimeout) while the toggle stays on.
Options:
- Gate the section on
store.state.sessionTimeoutValue.allowsUserSessionKeySharingtoo (hide, or.disabled(...)with explanatory footer text), and/or - Re-run
captureUserSessionKeyIfAllowedfromsetVaultTimeoutwhen the preference is on so switching back to a timed value takes effect immediately rather than at the next unlock.
| func setUserSessionKeySharingEnabled(_ isEnabled: Bool, userId: String?) async throws { | ||
| let id = try await userIdOrActive(userId) | ||
| try await keychainService.setUserAuthKey( | ||
| for: .userSessionKeySharingEnabled(userId: id), |
There was a problem hiding this comment.
❓ QUESTION: Should .userSessionKeySharingEnabled be cleared on logout?
Details
KeychainRepository.deleteItems(for:) removes .userSessionKey but does not include this new preference item, and that list documents its deliberate exclusions (e.g. vaultTimeout, deviceKey).
As written, the opt-in outlives logout — and, since keychain items survive app deletion, a reinstall — so the next login for that userId re-captures the session key at unlock without the user opting in again. If that persistence is intended (mirroring vaultTimeout), adding the item to that list's comments would make it explicit.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## PM-23301/share-user-session-key-extensions #3004 +/- ##
===========================================================================
Coverage 39.68% 39.68%
===========================================================================
Files 362 362
Lines 16987 16987
===========================================================================
Hits 6741 6741
Misses 10246 10246 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-42103
📔 Objective
Adds a user-facing, opt-in toggle ("Keep vault unlocked until timeout") in Account Security settings that lets a user choose to share their session key across the app and its extensions (e.g. autofill), so the vault stays unlocked until session timeout even after the app is closed.
This is stacked on top of #2661 (PM-23301, feature-flagged session key sharing), and adds the opt-in surface on top of that mechanism:
AuthRepository:isUserSessionKeySharingEnabled(userId:)/setUserSessionKeySharingEnabled(_:userId:), which immediately captures or purges the.userSessionKeyKeychain item to match the preference.KeychainRepository: new.userSessionKeySharingEnabled(userId:)key.AccountSecurityView/Processor/State/Effect: new toggle, gated behind the existing session-key-sharing feature flag, with a "Learn more" link (placeholder help URL, see inline TODO).📸 Screenshots