feat(fingerprint): password OR fingerprint in parallel at one prompt
Some checks failed
Check / eval (push) Failing after 2m45s

Bernardo promoted the PROPOSED item live: with fingerprint PAM on,
sudo/login should accept whichever factor comes first instead of
pam_fprintd's wait-for-the-reader-then-password. Stock PAM cannot
express parallel factors (linux-pam#301), so this packages
pam-fprint-grosshack v0.3.0 (pkgs/, pinned from GitLab — the
field-standard fprintd fork), source-reviewed before packaging: every
failure path (no reader, no prints, fprintd absent/hung, timeout,
password typed) returns PAM_AUTHINFO_UNAVAIL and falls through; a
typed password is only ferried via PAM_AUTHTOK to the stock
`auth sufficient pam_unix.so … try_first_pass` rule — the module never
validates passwords itself, so it cannot lock out password login.

New option nomarchy.hardware.fingerprint.parallel, default TRUE (the
better UX is what opting into fingerprint PAM buys; false = stock
sequential). Wiring swaps the modulePath of stock fprintd's rule slot
(mkForce) so the sufficient-before-pam_unix ordering is inherited, not
recomputed. README + downstream template rows added.

Verified: V2 — checks.hardware-toggles extended to three nodes, green:
parallel node asserts the grosshack auth line precedes pam_unix in
/etc/pam.d/sudo and that with NO reader a correct password still
passes sudo while a wrong one fails (the lockout-safety invariant);
seqpam node gets stock pam_fprintd and no grosshack; nopam gets
neither. flake check + option-docs + template-sot green.
V3 pending (HARDWARE-QUEUE, AMD dev box): the real type-or-touch race,
fprintd-stopped fallback, hyprlock/greeter after a fingerprint win.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 19:03:56 +01:00
parent c840202018
commit 7aae204014
9 changed files with 175 additions and 14 deletions

View File

@@ -443,6 +443,27 @@ Design/decision records and a running log of shipped work (items marked
V3 decides if the menu row needs a mirror-based rework. Also fixed in
the rescue: `grep -c .` exits 1 at count 0 — an `||`-guard on that
pipeline silently disabled the rescue exactly when it mattered.
✓ **Parallel fingerprint-or-password (2026-07-12, Bernardo promoted
from PROPOSED):** `nomarchy.hardware.fingerprint.parallel` (default
**true** — the better UX is what opting into fingerprint PAM gets you;
`false` restores stock sequential pam_fprintd). Implementation:
packaged `pam-fprint-grosshack` v0.3.0 (pkgs/, GitLab pin — the
field-standard fprintd fork; stock PAM cannot express parallel
factors, linux-pam#301; the cleaner-concept `pam-any` stays the
fallback candidate if grosshack fights greetd/hyprlock). Source
reviewed before packaging: every failure path returns
PAM_AUTHINFO_UNAVAIL (falls through to password) and a typed password
is only ferried via PAM_AUTHTOK to the stock
`auth sufficient pam_unix.so … try_first_pass` — the hack never
validates passwords itself, so password login cannot be locked out by
it. Wiring reuses stock fprintd's rule slot (mkForce'd modulePath) so
ordering is inherited, not recomputed. checks.hardware-toggles grew to
three nodes: parallel default (stack shape + password-works/
wrong-password-fails with no reader), parallel=false (stock
pam_fprintd), pam=false (neither). Real-reader race → HARDWARE-QUEUE
(AMD dev box). Accepted quirks (documented in the package): process-
wide SIGUSR1 handler, pthread_cancel'd prompt on fingerprint win,
prompt buffer not zeroized.
✓ **neon-glass finish (#88, `VISION § D`):** rewrote whole-swap
`rofi.rasi` to rofi-native `@color` glass panel (cyan rim, soft
selection wash — same hex-alpha glass pattern as Boreal); btop title/