Adds an end-to-end check that registering a PRF-enabled login passkey
populates `userDecryption.webAuthnPrfOptions` in /api/sync — the wire-level
prerequisite for the web vault's lock-screen "Unlock with passkey" option.
Two tests, complementary:
- PRF enrolment (`useForEncryption` checked) yields a non-empty array in
/sync, with the wrapped-key blobs the client uses to derive the user key
after the PRF assertion.
- Enrolment without PRF (`useForEncryption` unchecked) leaves the array
empty, pinning the emission filter's other branch.
Drives the real "Turn on Log in with passkey" UI flow under Settings →
Security → Master password against the bundled web vault, satisfying the
WebAuthn credential creation step with a Chromium CDP virtual authenticator.
The post-enrolment /sync call sniffs the bearer token from a live SPA
request rather than reaching into IndexedDB, because the vault aggressively
caches sync state and won't re-fetch on demand.
Runs as a dedicated `account-lifecycle` project in `playwright.config.ts`
(Chromium, `en` locale, SQLite-volatile via `utils.startVault`). The four
DB projects exclude the spec via `testIgnore`, since the rest of the suite
runs Firefox and the CDP virtual-authenticator with the `hmac-secret` PRF
extension is Chromium-only.
Why this file isn't in `passkey.spec.ts`:
- The "Log in with passkey" assertion ceremony itself runs inside a
same-origin `/webauthn-connector.html` iframe; current Chromium does not
satisfy navigator.credentials calls inside that iframe via CDP-injected
virtual authenticators. The enrolment step (which runs WebAuthn in the
main frame via a bit-dialog) IS reachable, and that's exactly the step
that populates webAuthnPrfOptions.
Run:
npx playwright test --project=account-lifecycle
Verified against bundled web-vault v2026.4.1: 2/2 passed end-to-end via the
docker harness.