UI-driven Playwright coverage for the passkey login + management
flows: enrolment via the Account page, PRF unlock toggle, login via
the "Log in with passkey" affordance, removal, and post-removal
fall-through to the master-password unlock path. The UI suite
complements the request-level coverage in `passkey.spec.ts` by
exercising the bundled web vault's connector iframe and the
account-page CDP virtual-authenticator interaction.
SSO_ONLY denial coverage extends the suite with two tests next to
the existing webauthn-grant denial:
- 'GET assertion-options (login challenge) denied with an
SSO-mentioning message' — sibling to the existing webauthn-grant
test, covers the unauthenticated entry point of the
discoverable-login flow at `src/api/identity.rs:1250`. The SPA
fetches this BEFORE invoking the WebAuthn ceremony, so the
server-side gate here is what prevents an attacker from attempting
passkey login even with a credential a victim has previously
enrolled.
- 'POST /api/webauthn/attestation-options denied with an
SSO-mentioning message' — covers the deny-by-default gate on the
enrolment endpoint at `src/api/core/mod.rs:308`. The handler is
authenticated, so the test provisions a user via the UI under
default config, sniffs the Bearer header from the SPA's post-login
/api/sync, then flips `sso_enabled`/`sso_only` at runtime via
`POST /admin/config` instead of restarting the vault container. The
runtime toggle avoids the tmpfs wipe an env-change-driven container
recreate would trigger, keeping the user, the RSA signing key, and
the pre-issued token all valid for the test.