git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit401effe6c3b191fb150a9077ece8bdd21c74106e
parent6ac3b0d01f
authorLucas Galante <[email protected]>
date2026-08-29 22:34
Restore keepassxc like any other app

Session restore special-cased keepassxc and refused to respawn it, on the
reasoning that "the Secret Service provider is owned by cce-keepassxc.service
so it comes up with the session". That unit no longer exists: gnome-keyring
provides org.freedesktop.secrets now, and KeePassXC is an ordinary app the user
opens by hand.

So the skip had inverted from a guard into a bug — nothing else brings
KeePassXC back, and a window open at logout simply vanished at the next login,
silently and with a log line claiming a unit had it covered.

The keyring barrier itself is unchanged and still correct: needs_secret_service
keys off Electron's --password-store= flag, not on any particular provider, and
wait_for_secret_service polls /org/freedesktop/secrets/aliases/default, which
now resolves to gnome-keyring's login collection. Only the rationale needed
rewording — the old text described hanging on KeePassXC's modal unlock prompt,
where the real hazard now is an app losing the race and quietly falling back to
plaintext credential storage.

cargo test -p cce-fx --lib window_manager: 12 passed, including
keyring_barrier_holds_until_unlocked_then_releases.

Co-Authored-By: Claude Opus 5 <[email protected]>

 src/server/window_manager.rs | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 10480fd..75e5101 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -1017,9 +1017,11 @@ impl WindowManager {
         std::thread::spawn(move || {
             // Clients that reach for the Secret Service on startup start last,
             // behind the keyring barrier: launched into a still-locked keyring
-            // they either fail outright or hang on KeePassXC's modal unlock
-            // prompt — which in turn delays the D-Bus unlock they are waiting
-            // for. Everything else starts immediately.
+            // they either fail outright or quietly fall back to plaintext
+            // credential storage. gnome-keyring now comes up already unlocked
+            // in ~1.3s, so the wait is short — but it is not zero, and losing
+            // that race downgrades an app's storage without saying so.
+            // Everything else starts immediately.
             let (secret_gated, immediate): (Vec<_>, Vec<_>) = restored
                 .into_iter()
                 .partition(|w| Self::needs_secret_service(&w.cmdline));
@@ -1132,14 +1134,6 @@ impl WindowManager {
             );
             return;
         }
-        // The Secret Service provider is owned by cce-keepassxc.service so it
-        // comes up with the session rather than from the middle of this queue;
-        // respawning it here would just race that unit.
-        if std::path::Path::new(cmd_trimmed).file_name().and_then(|f| f.to_str()) == Some("keepassxc")
-        {
-            log::info!("Skipping {cmd_trimmed}: started by cce-keepassxc.service");
-            return;
-        }
         if w.cmdline.is_empty() {
             return;
         }
@@ -5677,8 +5671,9 @@ mod tests {
         assert!(!WindowManager::needs_secret_service(
             "some-app --password-store=basic"
         ));
-        // Everything else starts immediately — including the provider itself,
-        // which must never wait on the barrier it is supposed to satisfy.
+        // Everything else starts immediately. KeePassXC is an ordinary app now
+        // that gnome-keyring provides the Secret Service — it reaches for no
+        // keyring of its own at startup, so it is not gated.
         assert!(!WindowManager::needs_secret_service("/usr/bin/keepassxc"));
         assert!(!WindowManager::needs_secret_service(
             "/home/lsgalante/.local/bin/cce-terminal"