Skip to content

Persist active account selection across app restarts - #110

Open
asherp wants to merge 1 commit into
stagingfrom
claude/app-restart-user-persistence-u8xb2w
Open

Persist active account selection across app restarts#110
asherp wants to merge 1 commit into
stagingfrom
claude/app-restart-user-persistence-u8xb2w

Conversation

@asherp

@asherp asherp commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds persistence for the active account selection in the keychain manager. When a user switches to a different account, that choice is now saved and automatically restored when the app restarts, instead of losing the selection or picking an arbitrary account.

Key Changes

  • Vault struct enhancement: Added an active field to track the public key of the currently active account, with #[serde(default)] for backward compatibility with older vault files
  • Keychain manager methods:
    • set_active(): Persists the active account pointer (validates the key exists first)
    • get_active(): Retrieves the persisted active account, returning None if the pointer is unset or stale
    • Updated delete_key() to clear the active pointer if the deleted key was active
  • Account activation refactor: Extracted activate_account_in_memory() helper to load a key into in-memory state, used by both initial activation and cold-start restoration
  • Smart account restoration: keychain_get_active_account() now implements a two-tier lookup:
    • Fast path: returns the in-memory active account if already loaded this session
    • Cold start: restores the persisted active account from the vault on app restart
  • Comprehensive tests: Added unit tests covering legacy vault deserialization, active field round-tripping, and default vault state

Implementation Details

  • The active field is optional and defaults to None for backward compatibility—older vault files without this field will deserialize correctly
  • Stale pointers (referencing deleted keys) are automatically cleaned up and treated as None
  • Persistence failures in set_active() are logged as warnings but don't block the session—the account remains active in memory
  • The restoration logic gracefully handles cold starts by checking the persisted pointer only when no account is already loaded

https://claude.ai/code/session_016iwHXKaFc8y3GhMDLDJueS

The active account was only ever held in memory (AppState.current_private_key),
so on restart the backend started with no active account. keychain_get_active_account
returned None, and the frontend fell back to accounts[0] — an arbitrary entry from
the keychain vault's HashMap, which has no stable order. The result: after a restart
the app could load a different user than the one that was active before.

Persist the active pubkey in the keychain vault (new Vault.active field, with
serde(default) for backward compatibility) whenever an account is made active, and
restore it into memory on cold start. keychain_get_active_account now returns the
previously-active account after a restart instead of None.

- keychain.rs: add Vault.active, set_active/get_active, and clear the pointer when
  the active key is deleted. Add serde round-trip / legacy-compat unit tests.
- lib.rs: extract activate_account_in_memory helper; set_active_account persists the
  choice; get_active_account restores the persisted account on cold start.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016iwHXKaFc8y3GhMDLDJueS
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.

2 participants