phase 7: auth flow UI (email-code login + session resume + revocation)

Implements ui/PLAN.md Phase 7 end-to-end:

- /login two-step form (email -> code) over the gateway public REST
  surface; /lobby placeholder issues the first authenticated
  user.account.get and renders the decoded display name.
- SessionStore (Svelte 5 runes) with loading / unsupported / anonymous /
  authenticated states; layout-level route guard, browser-not-supported
  blocker, and a minimal SubscribeEvents revocation watcher that closes
  the active client within 1s on a clean stream end or
  Unauthenticated.
- VITE_GATEWAY_BASE_URL + VITE_GATEWAY_RESPONSE_PUBLIC_KEY config plus
  AuthError taxonomy in api/auth.ts.
- Vitest (auth-api, session-store, login-page) and Playwright e2e
  (auth-flow.spec.ts) on the four configured projects, with a fixture
  Ed25519 keypair forging Connect-Web JSON responses.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-07 15:24:21 +02:00
parent 390ad3196b
commit 22b0710d04
24 changed files with 2125 additions and 48 deletions
+4 -2
View File
@@ -41,8 +41,10 @@ Browsers older than the baseline above will fail at the first
`NotSupportedError`. Phase 6 deliberately does not ship a JavaScript
fallback (e.g. `@noble/ed25519`) — keeping the keystore on WebCrypto
is what gives us non-extractable storage on every supported engine.
The Phase 7 login UI surfaces a clear "browser not supported"
message instead.
The Phase 7 root layout runs a one-time probe on boot and switches
to a "browser not supported" page (described in
[`auth-flow.md`](auth-flow.md)) when the probe rejects, instead of
attempting the keystore generate.
### WebKit non-determinism note