docs(openspec): archive fingerprint-token-auth after the production pass

The wizard's a2loft calls now authenticate with the session token and carry no
OTP. Field pass in production: the lookup and both fingerprint saves succeeded
with no OTP, so task 3.2 is done. Merged the fingerprint-wizard and tools-app
deltas into the main specs and archived the change.
This commit is contained in:
2026-10-06 19:19:29 +01:00
parent 8d42faf707
commit 8a13fb527e
8 changed files with 43 additions and 35 deletions
@@ -0,0 +1,60 @@
# Spec Delta: fingerprint-wizard
## MODIFIED Requirements
### Requirement: Two-finger enrollment flow
The wizard SHALL enroll a profile by: selecting a permitted domain, looking
up staff by reference (token-validated through the a2loft proxy), displaying
the staff details, capturing the right thumb and right index finger, and
saving both fingerprints through the a2loft proxy authenticated with the
session token. The wizard SHALL offer per-finger recapture until save, SHALL
require both fingers before save, and SHALL reset domain-independent state
(reference, staff details, captured artifacts) when starting a new
enrollment.
#### Scenario: Complete enrollment
- **WHEN** the operator looks up staff, captures both fingers, and saves
- **THEN** both fingerprints are saved through the a2loft proxy and the
wizard reports success
#### Scenario: Save requires both fingers
- **WHEN** the operator attempts to save with only one finger captured
- **THEN** the wizard rejects the save and explains both fingers are
required
#### Scenario: New enrollment resets state
- **WHEN** the operator starts a new enrollment after a save
- **THEN** the reference, staff details, and captured finger artifacts are
cleared while the permitted domain list persists
## REMOVED Requirements
### Requirement: OTP validated on every a2loft call
**Reason**: a2loft's fingerprint staff-lookup and save endpoints now accept the
session's PocketBase token, so the operator proves identity with the session
instead of a per-call OTP. The OTP scoped operators to the domain's uploader
list and rejected capture agents who hold only `capture_biometric`.
**Migration**: the wizard sends the session token through the same-origin
proxy and collects no OTP; a2loft keeps OTP mode for other clients.
## ADDED Requirements
### Requirement: Token authenticated on every a2loft call
The wizard SHALL authenticate each a2loft call — staff lookup and fingerprint
save — with the signed-in operator's PocketBase session token, sent by the
same-origin proxy as an `Authorization: Bearer` credential. The wizard SHALL
NOT collect an OTP.
#### Scenario: Lookup uses the session token
- **WHEN** the operator submits a reference
- **THEN** the wizard calls the staff-lookup proxy and a2loft authenticates the
session token
#### Scenario: Save uses the session token
- **WHEN** the operator saves the captured fingerprints
- **THEN** the wizard calls the fingerprint-save proxy and a2loft authenticates
the session token
#### Scenario: No OTP field
- **WHEN** the wizard page is served
- **THEN** it offers no OTP input for lookup or save
@@ -0,0 +1,26 @@
# Spec Delta: tools-app
## MODIFIED Requirements
### Requirement: a2loft proxies inject operator identity
The app SHALL proxy staff lookup and fingerprint-save calls to
`https://apis.a2loft.net` under same-origin API routes. The proxy SHALL
authenticate the operator with the signed-in session's PocketBase token, sent
as an `Authorization: Bearer` credential, preserving the a2loft request and
response shapes. The proxies SHALL require a session; a request without one
SHALL be rejected without contacting a2loft. The proxies SHALL NOT forward or
require an OTP.
#### Scenario: Staff lookup via proxy
- **WHEN** the page requests staff details for a domain and reference
- **THEN** the app calls a2loft's identity endpoint with the session token as a
bearer credential and returns a2loft's response unchanged
#### Scenario: Fingerprint save via proxy
- **WHEN** the page saves fingerprints for a domain and reference
- **THEN** the app posts them to a2loft's fingerprint endpoint with the session
token as a bearer credential
#### Scenario: Unauthenticated proxy call rejected
- **WHEN** a proxy route is called without a valid session
- **THEN** the app rejects the call without contacting a2loft