S-02: Extract extract_credential_raw_id() helper in services/passkey.py
— replaces 2 inline rawId parsing blocks in passkeys.py
S-03: Add PasskeyLoginResponse type, use in useAuth passkeyLoginMutation
S-04: Add Cancel button to disable-passwordless dialog
W-03: Invalidate auth queries on disable ceremony error/cancel
Perf-2: Session cap uses ID-only query + bulk UPDATE instead of loading
full ORM objects and flipping booleans individually
Perf-3: Remove passkey_count from /auth/status hot path (polled every
15s). Use EXISTS for has_passkeys boolean. Count derived from passkeys
list query in PasskeySection (passkeys.length).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
RegistrationCredential and AuthenticationCredential are plain dataclasses,
not Pydantic models — model_validate_json() does not exist on them.
Replace with parse_registration_credential_json() and
parse_authentication_credential_json() from webauthn.helpers, which
correctly parse the camelCase JSON from @simplewebauthn/browser and
convert base64url fields to bytes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>