Context
In edit mode the dialog sends password = "" ("leave blank to keep"). The command needs to restore the stored password before save. Currently it does so with if let Ok(stored) = ..., swallowing errors.
Problem
If ConnectionStore::get() returns Err (transient keyring backend failure, locked GNOME Keyring, Flatpak sandbox without Secret Service), profile.password stays empty, save() then treats password.is_empty() as "user wants no password" and calls delete_password(&profile.id) — permanently wiping the OS keyring entry. The user sees a success toast and has lost access. test_connection has the same bug: it runs with an empty password and produces a false-negative Access denied error.
Files
- src-tauri/src/commands/mod.rs:38-56 (esp. 45-49)
- src-tauri/src/commands/mod.rs:85-109 (test_connection, esp. 92-96)
- src/components/connection/ConnectionDialog.tsx:261 (empty-string convention)
Repro
- Create a profile with a password (saved to keyring).
- Mock or force a keyring-backend failure on
get().
- Open the profile in edit mode → Save (without touching password).
- Observe: success toast, but password entry gone from keyring.
Expected
The command returns Err("Failed to read password from keyring: ..."), the keyring entry is preserved, the user sees the error and the form is preserved.
Proposed fix
Scope S. Change both if let Ok(stored) blocks to let stored = state.connection_store.get(&profile.id).map_err(|e| ... )?; so failures propagate. Apply same to test_connection. Add an integration test using db_keystore failure injection.
Acceptance
Simulated PlatformFailure on get() returns the command error to the frontend and the keyring entry is preserved.
Needs human verify
Yes (need to force a keyring failure in test env).
Context
In edit mode the dialog sends
password = ""("leave blank to keep"). The command needs to restore the stored password before save. Currently it does so withif let Ok(stored) = ..., swallowing errors.Problem
If
ConnectionStore::get()returnsErr(transient keyring backend failure, locked GNOME Keyring, Flatpak sandbox without Secret Service),profile.passwordstays empty,save()then treatspassword.is_empty()as "user wants no password" and callsdelete_password(&profile.id)— permanently wiping the OS keyring entry. The user sees a success toast and has lost access.test_connectionhas the same bug: it runs with an empty password and produces a false-negativeAccess deniederror.Files
Repro
get().Expected
The command returns
Err("Failed to read password from keyring: ..."), the keyring entry is preserved, the user sees the error and the form is preserved.Proposed fix
Scope S. Change both
if let Ok(stored)blocks tolet stored = state.connection_store.get(&profile.id).map_err(|e| ... )?;so failures propagate. Apply same totest_connection. Add an integration test usingdb_keystorefailure injection.Acceptance
Simulated
PlatformFailureonget()returns the command error to the frontend and the keyring entry is preserved.Needs human verify
Yes (need to force a keyring failure in test env).