diff --git a/agent/BACKLOG.md b/agent/BACKLOG.md index c936af0..bf801a8 100644 --- a/agent/BACKLOG.md +++ b/agent/BACKLOG.md @@ -200,6 +200,46 @@ risk. Look into: what polls fprintd on that interval (hyprlock fingerprint backe from `nomarchy.idle.fingerprint`? a geoclue/other watcher?), and whether the reset is avoidable (autosuspend quirk, or gating the poll). Cost: investigation only; low. +### 157. Redundant hyprlock on suspend-then-hibernate resume (encrypted disks) + +Filed 2026-07-24 (dev box, reported by Bernardo + journal-confirmed). On a LUKS +machine, resuming from the **suspend-then-hibernate** path lands on a **hyprlock** screen +even though the LUKS passphrase already gated the resume — a second password. The design +intent (idle.nix + `nomarchy-{lock,unlock}-before-*` in `modules/nixos/default.nix`) is +exactly "no hyprlock on encrypted hibernate — LUKS is the gate"; it holds for a **direct** +`systemctl hibernate` but **not** for s2h. + +**Root cause (two layers).** (1) s2h's hibernate phase runs *inside* +`systemd-suspend-then-hibernate.service` and **never activates `hibernate.target`** — +journal-confirmed: at the phase-2 transition (`Performing sleep operation 'hibernate'` +from the same `systemd-sleep` PID) there is no target, no "Starting System Hibernate", +no unit/`system-sleep` hook at all. So `nomarchy-unlock-before-encrypted-hibernate` +(`wantedBy = hibernate.target`) never fires for s2h, whereas direct hibernate *does* +reach the target and unlock. (2) The deeper problem: phase-1 (the RAM suspend) *must* +lock (`nomarchy-lock-before-sleep` is `wantedBy` `suspend-then-hibernate.target`), so +**hyprlock is already up** before phase-2 — and a live Wayland session-lock **cannot be +safely dropped** (idle.nix: killing the locker trips hyprlock's "go to a tty" failsafe). +The whole unlock-before-hibernate design only works because for direct hibernate hyprlock +is *never up*; s2h violates that premise, and there is no systemd event between the two +phases to un-ring the bell. + +**Scope.** Encrypted disk + the s2h auto-hibernate path only (the default idle path on +battery). Direct `systemctl hibernate`/Power ▸ Hibernate is fine. Not a security hole — +the redundant lock is the *safe* failure (never leaves you unlocked). + +**Options (all have a cost).** (a) Accept it — safe default, one extra password. +(b) Skip locking on s2h for encrypted — removes the redundant lock but leaves the ≤1h +RAM-suspend window **unlocked** (real exposure; advise against). (c) A **safe external +hyprlock-dismiss** — the only clean fix, gated on whether current hyprlock exposes an +IPC/socket to unlock without the tty-failsafe (needs investigating; may not exist). + +**Intersection:** shares the s2h switch with **#155** — flipping +`nomarchy.system.power.suspendThenHibernate = false` on a box makes *both* the redundant +lock and the #155 crash exposure disappear (cost: no auto-hibernate-on-idle). Positioning: +correctness gap in a shipped v1 feature (**VISION § Theme C**, hibernate/sleep confidence). +Files: `modules/nixos/default.nix` (~257–286), `modules/home/idle.nix` (hypridle: no +`unlock_cmd`; the design comment). + ### 146. `[watch]` hypridle hangs instead of exiting when its compositor vanishes **Re-measured 2026-07-20 (dev box; user journal is persistent back to 2026-05-01,