# Design ## Context See proposal.md for motivation. The wizard already holds the PocketBase token in the page (`window.__SESSION__.token`) for fpagent enrollment, and the cropper's save already sends `Authorization: Bearer ${req.session.token}` to a2loft through its own proxy (`tools/cropper.js`). The two remaining OTP calls are the wizard's staff-lookup and fingerprint-save proxies in `tools/server.js`; their handlers receive the a2loft URL from `a2loftUrl`/`a2loftSaveUrl`, which currently append `phone`+`otp`, and `validateProxy` rejects a missing `otp`. ## Goals / Non-Goals **Goals:** both wizard a2loft calls use the session token; no OTP in the wizard; proxy validation keeps rejecting unauthenticated calls; deployable after the a2loft change with a clean rollback. **Non-Goals:** fpagent capture (already carries the token); the cropper; a2loft's own OTP compatibility; the legacy singular fingerprint endpoint. ## Decisions 1. **Bearer from the server session**, never the browser: the proxy attaches `Authorization: Bearer ${req.session.token}`, mirroring `tools/cropper.js`. The page's token copy stays for fpagent only. 2. **Drop the OTP check in `validateProxy`**, along with the now-unnecessary phone check; keep the hardcoded-domain and reference checks. `requireApi` already guarantees a session. 3. **Remove the OTP inputs and state** rather than hiding them; `canLookup`/`canSave` no longer require an OTP. ## Risks / Trade-offs - [a2loft not yet dual-mode] → deploy the a2loft change first; this proxy change depends on it. - [Operators outside a domain's uploader list can now enroll] → intended; a2loft authorizes `capture_biometric` with the `domain:idid` fallback. - [Rollback] → revert the proxy and re-add the OTP fields; a2loft stays dual-mode. ## Migration Plan Deploy a2loft dual-mode → deploy this app → field pass: look up a reference and save both fingerprints with no OTP; a bogus-token call fails cleanly. ## Open Questions None.