fix(lock): answer a refused finger from the resting view, and survive a wedged reader - #81
Merged
Merged
Conversation
… a wedged reader Two faults found running the locker on the real desktop. A rejected finger was invisible while resting. The chip renders inside the revealed tier, so its shake and its copy were drawn at zero opacity and a refused finger was indistinguishable from a dead sensor. MaxTries now also reveals, which puts the refusal where it is legible and lands the user on the factor that still works. It is the only outcome that reveals: every other one is the reader failing rather than the user being told no, and a reader that vanishes must not open the password field on a screen nobody is standing at. A stop was permanent from the first refusal. Measured here: repeated rejections drove enough claim/release cycles that a ReleaseDevice timed out, the Prometheus wedged, and it fell off the USB bus and re-enumerated about a second later. fprintd reported no device for that window, so the refusal arrived while the hardware was merely mid-reset -- and the chip then stayed absent for the rest of a lock the reader was healthy for. Stops now spend a finite backoff before latching. The budget is bounded because a missing quickshell-fprint policy refuses instantly and forever, and only exhausting it tells that apart from hardware coming back; any message resets it, since a module that spoke has claimed a real reader. Refs #62
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two faults found running the locker on the real desktop after the cutover
(dotfiles#3). Both are in the fingerprint
factor; neither was reachable from the nested harness, because one needs a resting view a
real finger is presented to and the other needs the reader to physically misbehave.
A refused finger was invisible while resting
LockFingerprintis built inside the container gated byopacity: root.revealed ? 1 : 0(
modules/lock/LockSurface.qml:213), so from the resting view a rejection's shake and its"Fingerprint not recognized. Try again." rendered at zero opacity. A win from resting
already worked — the comment at
:210says the reader "can win from the resting viewwithout any of this being on screen" — but a refusal was never given a resting answer, and
a wrong finger was indistinguishable from a dead sensor.
Result.MaxTriesnow carriesEffect.RevealAuthalongside its re-arm, so a refusal opensthe surface exactly as typing does. That puts the shake and the copy where they are legible
and lands the user on the factor that still works, rather than reporting a dead end they
cannot act on.
It is the only outcome that reveals, and there is a test pinning that. A success tears
the screen down anyway, and every other result is the reader failing rather than the user
being told no — a reader that vanishes must not pop the password field open on a screen
nobody is standing at.
A wedged reader was given up on permanently
Measured on this machine rather than reasoned about. Repeated rejections drove enough
claim → verify → release cycles (one per attempt, under
max-tries=1) that a release timedout and the reader dropped off the USB bus:
The reader was back about a second later. But the refusal that arrived during that window
latched
fingerprintStoppedon the first try, so the chip stayedAbsentfor the rest of alock the hardware was healthy for — recoverable only by locking again.
Stops now spend a finite backoff (2s, 5s, 10s) before latching. The budget is bounded
because an unslowed retry is the fork loop the original stop existed to prevent: a missing
quickshell-fprintpolicy refuses instantly and forever, and only exhausting a budget tellsthat apart from hardware coming back. Any PAM message resets it, since the module speaks
only after claiming a working reader.
fingerprintAction's contract is unchanged —StopFingerprintstill means "do not re-armnow". Only the applier's reading of it changed, so the fork-loop reasoning in
LockLogic.jsand its tests stand.Tests
Written first, all five red before the change (
ReferenceError: fingerprintRetryDelay is not defined, then the reveal assertions):sawMessagevaluesnode --test: 294 pass, 0 fail (was 289). All five lock QML fixtures pass. The fullshell loads clean in the nested compositor —
Configuration Loaded, zero errors — which iswhat compile-checks
services/Lock.qml, since no fixture can build it (it needsWlSessionLock).One existing test name was corrected: "stops the reader permanently" is no longer true
of the effect, only of the exhausted budget.
Not verified here — needs a human and a finger
I have no display and cannot present a finger, so neither fix has been seen working:
chip should shake and say "Fingerprint not recognized. Try again."
backoff is best confirmed opportunistically: if the pill vanishes mid-lock again, it
should come back within ~17s instead of staying gone until the next lock.