Skip to main content

max / alloy

Lockscreen: defer crash recovery to post-v1 (closes #4 for now) For v1, rely on Niri's existing fallback when the lock client dies. The Resilience contract already crash-proofs the auth path from user keystrokes; the remaining risk is a structural crash (GL context loss, Wayland disconnect, OOM) that the auth-path guards don't catch. Watchdog and crash-to-greeter handoff are explicit revisit items, not v1 deliverables. Document Niri's actual fallback behavior during first-light testing — that input will inform which recovery path is worth building. Pre-stabilization revisits section added to docs/todo.md so this isn't dropped silently. The lockscreen open-questions list is now empty. Implementation work can start (with the Wayland crate, PAM wrapper, single-process multi-surface model, and async-task service launching all settled).
Co-Authored-By
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-06-26 19:55 UTC
Signed with PGP, not checked
Commit: dbe69a7a59f3b17a714a248597b3acab32bbe03b
Parent: 32e960a
2 files changed, +5 insertions, -1 deletion
@@ -41,6 +41,10 @@
41 41 - [ ] Lockscreen (egui, ext-session-lock-v1, marquee app #1).
42 42 - [ ] Package GUI (egui, marquee app #2 — pedagogical wedge).
43 43
44 + ## Pre-stabilization revisits
45 +
46 + - [ ] **Lockscreen crash recovery.** v1 ships relying on Niri's existing fallback when the lock client dies. Before stabilizing, evaluate: (a) Niri's actual fallback behavior — does the user get stranded or does the compositor offer something? (b) watchdog / systemd `Restart=on-failure` supervisor as a v1.x add-on, (c) crash-to-greeter handoff if a Rust greetd-shaped path makes sense. See [`crates/alloy_lockscreen/README.md`](../crates/alloy_lockscreen/README.md) open question #4 for the deferred context.
47 +
44 48 ## v2+
45 49
46 50 - [ ] egui notification daemon (marquee app #3).
@@ -73,7 +73,7 @@
73 73 1. ~~**Wayland protocol crate.**~~ Resolved: smithay-client-toolkit. See above.
74 74 2. ~~**PAM crate.**~~ Resolved: pam-sys + thin in-crate wrapper. See Stack picks above.
75 75 3. ~~**Process model.**~~ Resolved: **single process, multiple lock surfaces.** ext-session-lock-v1 is a per-client protocol — the `ExtSessionLockV1` object can only be owned by one Wayland client, and its child `ExtSessionLockSurfaceV1` instances must be created by that owner. One-process-per-output therefore isn't really an option for a lock holder; it'd require either an N-renderer-process IPC dance under one holder, or independent processes racing for the lock (only one can win). Single process owns one Wayland connection, one async runtime, one lock, and N surfaces — one EGL/GL context bound per surface, all surfaces rendering from the same snapshot struct so the dot count, failure state, and clock appear simultaneously on every output without coordination. The "isolation if PAM blocks" motivation that originally argued for per-output processes has been retired by the Resilience contract: PAM runs on a worker task, the UI thread never blocks, so process isolation buys nothing the task model doesn't already give us. Precedent: swaylock, hyprlock, waylock are all single-process.
76 - 4. **Recovery path.** If the lockscreen process crashes while holding the session lock, the compositor stays locked and the user is stranded. ext-session-lock-v1 has explicit semantics for this; document the chosen recovery path (compositor-side fallback, watchdog, intentional crash-to-greeter) before shipping.
76 + 4. ~~**Recovery path.**~~ Resolved for v1: **rely on the compositor's existing fallback behavior; revisit before stabilizing.** v1 ships without a watchdog or crash-to-greeter handoff. The Resilience contract already makes the auth path crash-proof from the user's keystrokes; the remaining risk is a structural crash (GL context loss, Wayland disconnect, OOM) that the auth-path guards don't catch. For v1 we accept this and rely on whatever Niri does when the lock client dies — document Niri's actual fallback behavior during first-light testing. Watchdog and crash-to-greeter handoff are explicit revisit items, not v1 deliverables. See the follow-up in [`docs/todo.md`](../../docs/todo.md).
77 77
78 78 ## Non-goals as a marquee app
79 79