feat(auth): redesign login ux with password toggle and autofill - #993
feat(auth): redesign login ux with password toggle and autofill#993d-oit wants to merge 13 commits into
Conversation
Implement ADR-244: server-minted demo sessions for the reserved demo reader/admin accounts plus a validated help/how-to-use link on both auth screens. Add POST /api/demo/reader-login and /api/demo/admin-login with fail-closed gates (server flag, production-env detection, created_by_demo, disabled/compromised, role/book/grant checks). Frontend demo buttons only render when VITE_DEMO_LOGIN_ENABLED=1; the Worker gate stays authoritative. Also relax check-adr-index.mjs to treat GOAP execution records sharing a number with an ADR as siblings per ADR-083 s2 (GOAP-244 + ADR-244), with a focused test.
Finalize GOAP-244 as COMPLETED and ADR-244 as Accepted in the ADR index, and mark the plan documents accordingly.
…-244) Add Playwright specs for the ADR-244 demo entry points (reader demo, admin demo, help links) with the full viewport matrix (chromium, firefox, webkit, iphone, pixel, pwa-chromium). Mock the /api/demo/reader-login and /api/demo/admin-login endpoints in E2E fixtures and wire the demo reader response through mockReaderApi's loginResponse chain. Tests are gated on E2E_DEMO_LOGIN=1 so the scheduled CI e2e build (which does not set VITE_DEMO_LOGIN_ENABLED) skips them cleanly; demo-only build runs the full 550-test matrix green.
Security: - createAdminDemoSession now refuses to mint a password-assurance session when the demo admin is MFA-enrolled (mfa_method=passkey), closing the ADR-234 second-factor bypass. Demo route returns DEMO_DISABLED. - Demo reader login no longer depends on the operator-supplied reader password hash: it looks up the demo book + live grant directly instead of validateGrant (which required the password and broke demo login in deployments that set DEMO_READER_PASSWORD). Server-minted, password-free. Quality: - Memoize resolveHelpUrl() so it is not called on every render (both auth pages). - Align DEMO_READER_RESPONSE E2E fixture with the real API DTO (visibility, coverImageUrl). - Use the idiomatic 'extends JsonRow' for DemoUserRow instead of a manual index signature; fix JSDoc gate numbering and add the missing blank line before the new admin-middleware function. Config/docs: - Document DEMO_ACCOUNTS_PROD_ALLOWLIST in wrangler.jsonc and .dev.vars.example. - Wire E2E_DEMO_LOGIN and demo-enabling build vars into the scheduled CI e2e-full job so the demo E2E specs actually run in CI. Tests: - Add worker tests: password-protected demo grant still mints a reader session; missing demo grant returns 403; MFA-enrolled demo admin returns 403.
… (GOAP-244 Amendment A) Layout: - Anchor auth screens to the top with pb-8 instead of vertical centering so the full login card is scrolled into view — no more clipped admin description or help link below the fold on smaller viewports. - Move the 'Are you an author or manager?' admin/reader description inside the card so it renders alongside the form. Demo info: - Show the reserved demo email (and reader book slug) under the demo button when demo login is enabled, explaining it signs in without a password. - New i18n keys login.demoInfo / admin.login.demoInfo across all 13 catalogs. Help link: - Render the help link inside the card footer at text-sm font-medium so it is discoverable without scrolling on both auth screens. Tests: - Web: demo info panel visibility (shown/hidden by flag). - E2E: assert the demo info panel email text on reader and admin login. Docs: ADR-244 + GOAP-244 Amendment A (full-page visibility + demo info).
…ponent complexity (GOAP-244) Addresses OwlWatch review: LoginPage (333 lines, complexity 19) and AdminLoginPage (400 lines) were long, branching components. Extract the login/recovery/demo forms, token views, header, and the demo-login hook into small focused sub-components: - LoginForm / RecoveryForm / RecoverySuccessView / DemoLoginBlock / LoginCardHeader / TokenVerifyingView / TokenErrorView - useDemoLogin + toAuthStorePayload (shared session->store mapping) - AdminCredentialsForm / AdminRecoveryForm / MfaFactorChooser / AdminDemoBlock / AdminLoginHeader + useAdminDemoLogin - Merge duplicate LoginSubmitButton/RecoverySubmitButton into SubmitButton Behavior unchanged: same DOM, same accessible labels, same actions. 1294 web tests + 20 demo E2E tests pass.
…endment B) The deployed previews never set an absolute VITE_HELP_URL, so the auth screen 'Help / how to use' link never rendered. Research into 2025-26 login/demo UX (Authgear, SaaSUI, MicroFounder, Rajiv Pant) confirms the leading pattern is a password-free one-click demo plus an in-product 'what this app does / how to use' page — not credentials on the login. - New public /help route (lazy + suspense): app intro, reader vs admin roles, and the reserved demo accounts (emails + book slug). No demo password is ever rendered (ADR-233/244). - resolveHelpUrl accepts a same-origin /help path instead of requiring an absolute external URL, so the link works on localhost, previews, and production without baking a hostname. - VITE_HELP_URL=/help wired into .env.local.example, the Cloudflare Pages preview build (lighthouse.yml), and the E2E demo build (ci.yml). - Demo buttons stay local/E2E-only in deployments (ADR-233/244). - i18n help.* keys added across all 13 locale catalogs. - Web tests: HelpPage render/gating/back-link + resolveHelpUrl relative, external, invalid branches; E2E help-link assertions now expect /help. - Plan ADR-244 + GOAP-244 Amendment B.
…244 Amendment B)
The Cloudflare Pages GitHub integration builds with a plain `pnpm build`
and no environment variables, so resolveHelpUrl() returned null and the
isDemoLoginEnabled() gate hid the demo emails — the original complaint
persisted on the exact preview users see.
- resolveHelpUrl() now defaults to { href: '/help', isExternal: false }
when VITE_HELP_URL is unset or invalid; the /help route ships in every
deployment, so the auth-screen help link renders regardless of env.
- HelpPage demo section is no longer gated on isDemoLoginEnabled() — the
reserved demo emails + book slug are documented/public per ADR-233 and
safe to show on the info page even when one-click buttons are off.
- Tests updated: resolveHelpUrl default/fallback branches; HelpPage always
shows demo accounts.
… (GOAP-244 Amendment C) Product decision (user-directed, overrides ADR-244 decision 7 for the demo accounts only): the reserved demo reader and admin users now have documented public passwords and sign in through the normal email+password login forms. Production fail-closed behavior is unchanged — the seed and Worker still refuse production-like environments and the demo admin stays disabled outside local unless explicitly allowlisted. Seed: - Default both demo passwords to documented values (demo-reader-password / demo-admin-password), hash with Argon2id, and always provision the reader grant as password_protected. Operator env vars still override. - Remove the now-redundant DEMO_ADMIN_PASSWORD-required guard; export the documented password constants; keep production fail-closed guards. Frontend: - demo-config exports DEMO_READER_EMAIL/PASSWORD, DEMO_ADMIN_EMAIL/PASSWORD, DEMO_BOOK_SLUG (env-driven with documented defaults) as a single source of truth. - Login demo info panels (reader + admin) and the help page now show email + password + book slug. - Env typing + .env.local.example / .dev.vars.example document the values. i18n: login.demoInfo, admin.login.demoInfo, help.demo* updated in all 13 catalogs to include the password credential. E2E: new tests sign in as the demo reader and demo admin via the standard email+password forms and assert navigation; fixtures gain demo credential constants and an admin-login mock option. Tests: seed unit tests updated (default passwords, hashed, password_protected grant); web suite + seed tests + quality gate pass.
…eader sign-in works Demo reader sign-in failed on fresh/seeded deployments for two reasons: - The seed only created a reader grant if a 'demo' book already existed and never provisioned one, so the grant was silently skipped (GOAP-244 demo accounts were not sign-in-ready). The seed now inserts a placeholder demo book (ON CONFLICT DO NOTHING) and always attaches the reader grant. - Web baked 'http://localhost:8787' as the API base when VITE_API_BASE_URL was unset (a banned pattern per docs/banned-patterns.md), so built deployments pointed at the browser's own localhost and every sign-in request failed in the console with 'Failed to fetch'. Built deployments now default to the same origin; local dev keeps the Wrangler fallback. Verified: seed unit tests 16/16; web suite 120 files / 1298 tests pass.
ADR-245 / GOAP-246: wire WCAG 3.3.8 eye-icon password toggle into all auth forms, replace the plaintext demo info line with a dual-action panel (one-click + autofill credentials), and add a rich feature-hero with mobile variant to both reader and admin login screens. Extracts subcomponents to fix a pre-existing 521-line violation on AdminLoginPage.tsx and deletes the duplicate login test suite.
Deploying do-epub-studio with
|
| Latest commit: |
ef043d1
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://8d59024b.do-epub-studio.pages.dev |
| Branch Preview URL: | https://feature-login-ux-redesign.do-epub-studio.pages.dev |
🚀 Performance Report🛠️ CI & Workflow
⚡ Turbo Task Performance
Cache Hit Ratio: 0% (0/7 tasks) 🧪 Test Stability
|
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 164 |
| Duplication | 76 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Codacy/pre-commit MD038: remove leading spaces inside code spans in GOAP-246 and LEARNINGS. Password toggle: icon-only below sm with aria-label carrying the accessible name; localized text at sm+ so long labels (fr/ru/de) cannot overflow the pr-12 reservation.
|
✅ Health of changed files: 5.2 → 5.7 (+0.5) 📋 At a glance Files & modules (3)
✅ Health gate: passed 📌 Before you merge
🎯 Blast radius (symbols whose signature this PR changed, and who calls them)
🔎 More signals (4)🗺️ Change map flowchart LR
subgraph PR ["Changed in this PR (2 modules)"]
m_apps["apps (21 files)"]:::changed
m_packages["packages (2 files)"]:::changed
end
classDef changed fill:#dbeafe,stroke:#1d4ed8,color:#1e3a5f
classDef warn fill:#fef3c7,stroke:#b45309,color:#78350f
classDef guard fill:#dcfce7,stroke:#15803d,color:#14532d
Solid arrows: code that imports the changed files (67 direct dependents, from the last indexed snapshot). Dashed: history/tests. 🔥 Hotspots touched (5)
2 more
🔗 Hidden coupling (3 files)
💀 Dead code (7 findings)
4 more
📊 See the full report for this PR |
Summary
feat(auth): redesign login ux with password toggle and autofill
What this PR adds (ADR-245 / GOAP-246)
sm+, icon-only witharia-labelbelowsmso long-locale labels (fr/ru/de) cannot overflow the input./helpstill lists credentials.lgon both screens.Changes
Related
plans/245-adr-login-ux-redesign.mdplans/246-goap-login-ux-redesign.mdagents-docs/LEARNINGS.md§ GOAP 246Type
feat
Checklist