Skip to content

fix(eid-wallet): settle the settings store before the app is killed - #1149

Merged
Bekiboo merged 2 commits into
mainfrom
fix/bug-eid-wallet-intermittent-logout
Sep 24, 2026
Merged

Bekiboo merged 2 commits into
mainfrom
fix/bug-eid-wallet-intermittent-logout

Conversation

@Sahil2004

Copy link
Copy Markdown
Contributor

Description of change

Closing the app from the background intermittently signed the user out, dropping them back to the create-or-restore splash with their vault, user, PIN and document gone.

The settings store is saved by tauri-plugin-store with fs::write, which opens the file with O_TRUNC, so the previous contents are discarded before the new bytes are written. Auto-save is debounced and Android kills backgrounded apps with SIGKILL, so a save is frequently still in flight when the kill lands. Interrupting that write leaves global-state.json at zero bytes, and the next launch reads an empty store, concludes this is a first run and persists a fresh onboarding state over the top, which makes the loss permanent.

An app is only killed after it has been backgrounded, and the webview still receives visibilitychange at that point. Use it as the settling point: flush the store so no debounced write remains outstanding, then copy the settled file into a sidecar backup written atomically via a temp file, fsync and rename. Once that completes there is no write left for a kill to interrupt.

Loading falls back to the sidecar when the primary file cannot be parsed, which covers a kill that arrives before the flush finishes; the backup then still holds the previous complete state. Recovery keys off unparseable bytes rather than an absent or empty cache, so a session the user ended deliberately is never resurrected: clearing the store on logout serialises to "{}", which is valid JSON and is passed through untouched. Backing up refuses to copy a primary that does not parse, so a damaged file cannot overwrite a good backup. With no readable backup the original parse error is returned and a genuine first launch still runs normal setup instead of receiving invented state.

All of this runs at backgrounding only. The startup and steady-state save paths are untouched, so launch performs no extra filesystem work.

Issue Number

Closes #1143

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Manually.

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Closing the app from the background intermittently signed the user out,
dropping them back to the create-or-restore splash with their vault,
user, PIN and document gone.

The settings store is saved by tauri-plugin-store with fs::write, which
opens the file with O_TRUNC, so the previous contents are discarded
before the new bytes are written. Auto-save is debounced and Android
kills backgrounded apps with SIGKILL, so a save is frequently still in
flight when the kill lands. Interrupting that write leaves
global-state.json at zero bytes, and the next launch reads an empty
store, concludes this is a first run and persists a fresh onboarding
state over the top, which makes the loss permanent.

An app is only killed after it has been backgrounded, and the webview
still receives visibilitychange at that point. Use it as the settling
point: flush the store so no debounced write remains outstanding, then
copy the settled file into a sidecar backup written atomically via a
temp file, fsync and rename. Once that completes there is no write left
for a kill to interrupt.

Loading falls back to the sidecar when the primary file cannot be
parsed, which covers a kill that arrives before the flush finishes; the
backup then still holds the previous complete state. Recovery keys off
unparseable bytes rather than an absent or empty cache, so a session the
user ended deliberately is never resurrected: clearing the store on
logout serialises to "{}", which is valid JSON and is passed through
untouched. Backing up refuses to copy a primary that does not parse, so
a damaged file cannot overwrite a good backup. With no readable backup
the original parse error is returned and a genuine first launch still
runs normal setup instead of receiving invented state.

All of this runs at backgrounding only. The startup and steady-state
save paths are untouched, so launch performs no extra filesystem work.

Fixes #1143
@Sahil2004 Sahil2004 self-assigned this Sep 23, 2026
@Sahil2004
Sahil2004 requested a review from coodos as a code owner September 23, 2026 17:59
@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 6a061339-95fe-49ad-b626-959ccafb7a00


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Bekiboo Bekiboo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Audit pass. None of these are blocking.

Comment thread infrastructure/eid-wallet/src-tauri/src/lib.rs
Comment thread infrastructure/eid-wallet/src/lib/global/state.ts
Comment thread infrastructure/eid-wallet/src-tauri/src/lib.rs
@Sahil2004
Sahil2004 force-pushed the fix/bug-eid-wallet-intermittent-logout branch from d6090ef to 17bc482 Compare September 24, 2026 04:25
The backup is a copy of the store as it was at the last backgrounding, so
between a reset and the next backgrounding it still held the user, vault
and PIN hash of the session that just ended.

Recovery keys off unparseable bytes, so a kill that truncated the primary
file in that window restored the backup and brought the ended session back
with its credentials intact.

Settle the cleared store and refresh the backup as part of the reset, which
bounds that window to the reset itself. The refresh sits outside the catch
so a controller that throws part-way through clearing cannot leave the
stale copy behind.
@Sahil2004
Sahil2004 force-pushed the fix/bug-eid-wallet-intermittent-logout branch from 17bc482 to b8c6095 Compare September 24, 2026 04:35
@Bekiboo
Bekiboo merged commit 78e9d79 into main Sep 24, 2026
4 checks passed
@Bekiboo
Bekiboo deleted the fix/bug-eid-wallet-intermittent-logout branch September 24, 2026 08:17
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.

[Bug] eID app gets logged out - intermittently

2 participants