Follow-up from #2082 (auto-lock UI flip).
Context
PR #2802 added a background→popup SESSION_LOCKED broadcast plus a lockAccount reducer so all open extension UIs flip to the unlock screen as soon as the idle alarm fires. Internal review-fix round 1 identified that several call sites still do const result = await loadAccount(); dispatch(saveAccount(result)); with no guard against the response arriving after a lock event. Specifically:
extension/src/popup/helpers/hooks/useGetAppData.tsx:67-73
extension/src/popup/helpers/hooks/useGetSubmitAccountData.tsx:27-37
extension/src/popup/helpers/hooks/useGetRecoverAccountData.ts:25-35
If the user is auto-locked while one of these requests is in flight, the late response can saveAccount(...) over the cleared state, briefly rehydrating private-key state in the redux store after we've intentionally cleared it.
The fix in #2802 keeps the navigation push race-free (the listener dispatches lockAccount synchronously before navigating), so this issue does not block the UI flip. But it is a latent correctness bug that the lock broadcast made more visible.
What needs to happen
Introduce a session-epoch guard (or equivalent invalidation token) shared by the auth slice and the data-loading hooks, such that saveAccount(result) only applies when result.epoch === currentEpoch. lockAccount / signOut / account-switch reducers increment the epoch, invalidating in-flight loads.
Add tests covering:
loadAccount() resolves after a SESSION_LOCKED broadcast — store remains locked.
loadAccount() resolves after signOut — store remains signed-out.
Dependencies
None. Independent of #2082 and the broadcast-generalization follow-up.
References
Follow-up from #2082 (auto-lock UI flip).
Context
PR #2802 added a background→popup
SESSION_LOCKEDbroadcast plus alockAccountreducer so all open extension UIs flip to the unlock screen as soon as the idle alarm fires. Internal review-fix round 1 identified that several call sites still doconst result = await loadAccount(); dispatch(saveAccount(result));with no guard against the response arriving after a lock event. Specifically:extension/src/popup/helpers/hooks/useGetAppData.tsx:67-73extension/src/popup/helpers/hooks/useGetSubmitAccountData.tsx:27-37extension/src/popup/helpers/hooks/useGetRecoverAccountData.ts:25-35If the user is auto-locked while one of these requests is in flight, the late response can
saveAccount(...)over the cleared state, briefly rehydrating private-key state in the redux store after we've intentionally cleared it.The fix in #2802 keeps the navigation push race-free (the listener dispatches
lockAccountsynchronously before navigating), so this issue does not block the UI flip. But it is a latent correctness bug that the lock broadcast made more visible.What needs to happen
Introduce a session-epoch guard (or equivalent invalidation token) shared by the auth slice and the data-loading hooks, such that
saveAccount(result)only applies whenresult.epoch === currentEpoch.lockAccount/signOut/ account-switch reducers increment the epoch, invalidating in-flight loads.Add tests covering:
loadAccount()resolves after aSESSION_LOCKEDbroadcast — store remains locked.loadAccount()resolves aftersignOut— store remains signed-out.Dependencies
None. Independent of #2082 and the broadcast-generalization follow-up.
References
plan-do-review/issue-2082for PR Replace 24h absolute auto-lock with configurable idle timer #2802)