fix: eliminate OS keychain prompt on startup by persisting pairing token in DB

The root cause was hydrate_extension_pairing_token accessing the
keychain when keychainAccessGranted was true in the DB.  Any keychain
access on macOS triggers the system prompt when the binary signature
changes after an update.

Architecture change: two-store model.
- The SQLite settings DB is now the primary store for the token.
  hydrate_extension_pairing_token reads from it exclusively -- it
  never touches the OS keychain.  No system prompt on startup.
- The OS keychain remains defence-in-depth: grant_keychain_access
  still writes the token there, but it is only reached from the
  explicit Grant Access button, so any system prompt is user-initiated.

DB helpers: load_pairing_token_from_settings / save_pairing_token_to_settings
hydrate_extension_pairing_token: reads from DB, skips keychain entirely
grant_keychain_access: syncs token to DB after keychain access
Frontend: extensionPairingToken included in partialize for auto-persist
This commit is contained in:
NimBold
2026-06-25 03:09:50 +03:30
parent 09f103ea04
commit 8eb1a55e72
6 changed files with 99 additions and 34 deletions
+8 -4
View File
@@ -273,10 +273,14 @@ pub struct PersistedSettings {
pub prevents_sleep_while_downloading: bool,
pub media_cookie_source: MediaCookieSource,
pub site_logins: Vec<SiteLogin>,
// Note: `extension_pairing_token` is intentionally NOT persisted here. It
// is an HMAC shared secret and is stored in the OS keychain by the
// frontend. The field is kept on legacy persisted JSON only; serde ignores
// unknown fields when decoding, so existing installs migrate cleanly.
/// The HMAC shared secret for the browser extension. It is persisted in the
/// settings database so that startup never needs to touch the OS keychain.
/// The keychain is still used as defence-in-depth — grant_keychain_access
/// writes the token there — but the DB copy is the primary read path,
/// eliminating the OS credential prompt that macOS shows when the binary
/// signature changes after an update.
#[serde(default)]
pub extension_pairing_token: String,
pub auto_check_updates: bool,
#[serde(default)]
pub keychain_access_granted: bool,