Adopt passkey-first authentication with WebAuthn
Context
The app needs user authentication. Passwords are the default but they're a known-weak pattern — reuse, phishing, credential stuffing. Passkeys (WebAuthn/FIDO2) provide phishing-resistant authentication tied to the device's biometrics or secure enclave, and Apple has made them a first-class citizen on iOS.
Decision
Passkeys as the primary authentication method using the webauthn-rs crate (v0.5). Email and password as a fallback for cases where passkeys aren't available.
The backend serves an Apple App Site Association (AASA) file for iOS domain association, enabling the system passkey UI. Registration and authentication use WebAuthn's discoverable credential flow — the user doesn't need to type a username, the device offers matching passkeys automatically.
Expired WebAuthn challenges are cleaned up daily via the tokio-cron scheduler (same infrastructure as PASETO key rotation, ADR-0026).
Local development requires Caddy for TLS on port 443 — passkeys need HTTPS with a valid domain association.
Consequences
Phishing-resistant auth with biometric confirmation. No passwords to store, hash, or leak. The iOS experience is seamless — Face ID / Touch ID to log in.
The cost is WebAuthn's complexity (challenge-response flows, credential storage, domain association), the Caddy requirement for local dev, and the password fallback still needs maintaining.