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
- [ ] **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.
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).