feat(menu): one fingerprint switch, an auto-login toggle, and the state bridge they needed
All checks were successful
Check / eval (push) Successful in 3m7s
All checks were successful
Check / eval (push) Successful in 3m7s
Bernardo, post-reboot: "Use for login" was the wrong question. Whether the
finger works is one decision, not two, and whether login prompts at all is
a different decision that was never in the menu.
System › Fingerprint is now a single Fingerprint (on/off) switch, leading
the menu with enroll/list/verify/delete as the plumbing behind it. It
writes the one settings.fingerprint.pam key, and modules/home/idle.nix now
defaults idle.fingerprint from that same key — so the lock screen and
login/sudo move together instead of drifting apart the way they did until
e2de906. nomarchy-fingerprint does the two rebuilds this needs (sudo
system for PAM, home switch for hyprlock) and refuses to turn on with no
finger enrolled.
System › Auto-login is new (nomarchy-autologin), and it is what decides
whether anything is asked at boot: auto-login on means no prompt whatever
the fingerprint switch says; off means the greeter asks, for a password or
a finger. Installer-seeded ON for LUKS machines — the passphrase already
gates the disk — and off without it, where the greeter is the only thing
between power-on and the desktop.
Both had to become state-owned to be toggleable at all, which surfaced two
real bugs:
* nomarchy.system.greeter.autoLogin defaulted from
`config.nomarchy.settings…` — an attribute that exists ONLY on the Home
Manager side. On NixOS it is absent and `or null` swallowed the error,
so the default silently evaluated to null on every machine ever built.
That is why the installer baked a Nix line: the state path never
worked. Now read via theme-state-read.nix (the hardware.nix/timezone.nix
pattern) and mkDefault'd, so the menu owns it and a hand-set line still
pins it. Two more options read the same phantom bridge — BACKLOG #116.
* `theme-sync get` printed Python's "None" for a JSON null, so every
`case … null)` a caller writes would miss. Now prints "null", as the
comment above it already promised for booleans.
The installer seeds the state instead of emitting the system.nix line,
because that line outranks the state and would strand the toggle.
V1 (V3 pending: HARDWARE-QUEUE). nix flake check --no-build, installer-
safety and option-docs all pass. Proved by eval/build, not assumed: a state
carrying autoLogin yields greetd initial_session {"user":"bernardo"}, the
template state (no autoLogin) yields none, and a hand-set null beats a state
that says otherwise; a state with only fingerprint.pam=true — nothing set by
hand — renders the hyprlock auth.fingerprint block; both new tools pass
bash -n and land in systemPackages (nomarchy-fingerprint only with a
reader); the patcher writes settings.greeter.autoLogin and no system.nix
line; and the get round trip prints null, so the menu reads "Auto-login
(off)" where it would have read "(on)".
The reader itself, the two rebuilds, and the reboot are hardware — queued.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,59 @@ pre-existing ISO-pinning gap.
|
||||
|
||||
## NEXT
|
||||
|
||||
### 115. Suspend-then-hibernate, with a way to set it up
|
||||
|
||||
Bernardo, 2026-07-14: a suspended laptop should be able to fall through to
|
||||
hibernate after a while, so a bag-carried machine stops draining, and setting
|
||||
that up must be easy — not a systemd-sleep man-page trip.
|
||||
|
||||
The mechanism is `systemd`'s `suspend-then-hibernate` plus
|
||||
`HibernateDelaySec`; the work is the surfacing, and the constraints are
|
||||
already in the tree. Hibernate needs the resume offset + swap the installer
|
||||
detects (`resumeOffset`/`rootUuid` in patch-template.py) — on a machine
|
||||
without them this must self-gate, not fail at suspend time, the way Battery
|
||||
limit gates on a battery. `modules/nixos/default.nix` already declines to
|
||||
hyprlock before an encrypted hibernate (the LUKS resume gates it); check that
|
||||
reasoning still holds when the suspend leads to hibernate. Menu placement: it
|
||||
belongs with the power settings, not the root (§ menu placement convention).
|
||||
|
||||
Settle first (`[human]`): whether the delay is a preset list (30 min / 1 h /
|
||||
2 h / never) or a free-form entry, and whether it applies on battery only or
|
||||
always — the same on-AC question `modules/home/idle.nix`'s suspend listener
|
||||
already answers with `${onAc} ||`.
|
||||
|
||||
In-flake state like the rest (`settings.*`), menu-writable, and read via
|
||||
`theme-state-read.nix` on the NixOS side — NOT `config.nomarchy.settings`,
|
||||
which does not exist there (see #116). Pass = the toggle survives a rebuild,
|
||||
a suspended machine hibernates after the configured delay and resumes, and a
|
||||
machine without hibernate support hides the row instead of offering a
|
||||
suspend that never wakes.
|
||||
|
||||
### 116. Three NixOS options read a `config.nomarchy.settings` that does not exist
|
||||
|
||||
Found while wiring System › Auto-login (2026-07-14). `nomarchy.settings` is
|
||||
declared and populated **only on the Home Manager side** (`modules/home/
|
||||
options.nix`, filled by `theme.nix`). On the NixOS side the attribute is
|
||||
absent, and `or <fallback>` swallows the missing-attribute error — so these
|
||||
defaults have silently always been their fallback on every machine:
|
||||
|
||||
- `nomarchy.system.greeter.autoLogin` — **fixed in this commit** (now reads
|
||||
the state via `theme-state-read.nix` in `greeter.nix`, the working pattern
|
||||
from `hardware.nix`/`timezone.nix`). Left here as the worked example.
|
||||
- `modules/nixos/options.nix` `bluetooth.enable` — `settings.bluetooth.enable`
|
||||
never read; benign today (fallback `true` = the intended default) but the
|
||||
state key is dead.
|
||||
- `modules/nixos/options.nix` `power.batteryChargeLimit` — `settings.power.
|
||||
batteryChargeLimit` never read; the Battery limit menu works because it
|
||||
patches the baked option in `system.nix` instead, which is the older model.
|
||||
|
||||
Decide per option whether the state key should work (wire it like the
|
||||
greeter) or the phantom read should just go. The trap is that `or` makes both
|
||||
a live bridge and a dead one look identical — a grep for
|
||||
`config.nomarchy.settings` under `modules/nixos/` should return nothing when
|
||||
this is done. Pass = no NixOS option claims a state default it cannot read,
|
||||
and any bridge kept is proved by an eval that flips with the state file.
|
||||
|
||||
### 107. Rename `theme.json` to reflect that it is the system state
|
||||
|
||||
The state file long ago stopped being about themes: it carries night-light,
|
||||
|
||||
@@ -181,9 +181,24 @@ the **T14s** (webcam case).
|
||||
authentication daemon to re-prove an evaluated invariant is a bad trade.
|
||||
- [ ] **#55 fingerprint enroll on real reader** — with
|
||||
`nomarchy.hardware.fingerprint.enable` and a physical reader: System ›
|
||||
Fingerprint › Enroll a finger; List shows it; Verify succeeds; optional
|
||||
Use for login (on) → `nomarchy-rebuild` → login/sudo accept fingerprint.
|
||||
Menu surface is V1/V2 without a reader (self-gate + dry paths).
|
||||
Fingerprint › Enroll a finger; List shows it; Verify succeeds.
|
||||
Enroll/List/Verify verified on hardware 2026-07-14 (T14s); the
|
||||
remaining unknown is a reader-less machine's self-gate.
|
||||
- [ ] **fingerprint + auto-login toggles on hardware** (this commit) — on the
|
||||
T14s, after removing the pinning lines from `~/.nomarchy/system.nix`
|
||||
(`greeter.autoLogin`, `hardware.fingerprint.pam`):
|
||||
1. System › Fingerprint shows **Fingerprint (on)** (state already true).
|
||||
Toggle it off → terminal opens, sudo system rebuild + home switch →
|
||||
toast "Fingerprint off". Expect: sudo now refuses the finger and asks
|
||||
only for a password; the lock screen (SUPER+CTRL+L) shows no
|
||||
"or scan your finger" line. Toggle back on → both return.
|
||||
2. With fingerprint OFF and no finger enrolled, the toggle must REFUSE
|
||||
with "Enroll a finger first" and write nothing.
|
||||
3. System › Auto-login shows **(on)**. Toggle off → sudo rebuild →
|
||||
reboot → tuigreet asks, and accepts password OR finger (fingerprint
|
||||
on). Toggle back on → reboot → straight to the session, no prompt.
|
||||
Expected throughout: the two are independent, and auto-login on means
|
||||
no boot prompt regardless of the fingerprint switch.
|
||||
- [ ] **#60 non-BAT* battery name (if available)** — on a machine whose
|
||||
system battery is **not** named `BAT*` (e.g. `CMB0`): confirm
|
||||
charge-limit oneshot writes the threshold, System › Battery limit
|
||||
|
||||
Reference in New Issue
Block a user