Skip to content

feat: demo login entry points + help links (GOAP-244 / ADR-244) - #991

Merged
d-oit merged 11 commits into
mainfrom
plan/demo-login-help-goap
Aug 19, 2026
Merged

feat: demo login entry points + help links (GOAP-244 / ADR-244)#991
d-oit merged 11 commits into
mainfrom
plan/demo-login-help-goap

Conversation

@d-oit

@d-oit d-oit commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Summary

Implements ADR-244 / GOAP-244: Demo Login and Help Entry Points — visible one-click demo access plus a help/how-to-use link on both auth screens, with server-side fail-closed controls.

Worker — POST /api/demo/reader-login + POST /api/demo/admin-login

  • Mint sessions for the reserved demo accounts (ADR-233) without any browser-shipped passwords.
  • Fail-closed gates before any session: DEMO_LOGIN_ENABLED === '1', non-production environment, created_by_demo = 1, account not disabled/compromised, and (reader) demo book + live grant / (admin) global_role = admin.
  • All failure paths return a generic 403 DEMO_DISABLED — no account-existence disclosure.
  • Reader session returns the same DTO as /api/access/request; admin session the same DTO as /api/admin/login.

Web

  • LoginPage — "Use reader demo" button + demo error alert (rendered only when VITE_DEMO_LOGIN_ENABLED=1), plus a help link when VITE_HELP_URL is a valid URL.
  • AdminLoginPage — mirror "Use admin demo" button + help link.
  • New apps/web/src/config/demo-config.ts — validates VITE_HELP_URL via URL constructor, rel="noopener noreferrer" on external targets.

i18n

  • 6 new keys (login.demoReader, login.demoSigningIn, login.helpLink, admin.login.demoAdmin, admin.login.demoSigningIn, admin.login.helpLink) added to all 13 locale catalogs.

Governance fix

  • scripts/check-adr-index.mjs now treats GOAP execution records sharing a number with an ADR as siblings per ADR-083 §2 (the GOAP-244 + ADR-244 case). Only ADR rows participate in duplicate detection. Added scripts/__tests__/check-adr-index.test.mjs.

Verification

  • Worker: 439 tests pass (55 files); Web: 1292 tests pass (119 files).
  • ./scripts/quality_gate.sh (CI-equivalent, QUALITY_GATE_NO_SMOKE=1) — passed.
  • Root pnpm lint and pnpm typecheck — passed.
  • ADR index validator — passed.

Notes

  • Frontend demo buttons are UI-only; the Worker gate is authoritative.
  • No plaintext demo credentials, real personal data, or hardcoded deployment-specific URLs are added.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 15, 2026

Copy link
Copy Markdown

Deploying do-epub-studio with  Cloudflare Pages  Cloudflare Pages

Latest commit: 94393df
Status: ✅  Deploy successful!
Preview URL: https://f544e16a.do-epub-studio.pages.dev
Branch Preview URL: https://plan-demo-login-help-goap.do-epub-studio.pages.dev

View logs

@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown

🚀 Performance Report

🛠️ CI & Workflow

Metric Value Limit Trend Status
Total CI Duration 4.27 min 15.00 min -
Pnpm Cache Hit Hit - -

⚡ Turbo Task Performance

Task Duration (s) Cache Status Trend Status
@do-epub-studio/reader-core#build 0.00 MISS - 🔄
@do-epub-studio/schema#build 0.00 MISS - 🔄
@do-epub-studio/shared#build 0.00 MISS - 🔄
@do-epub-studio/testkit#build 0.00 MISS - 🔄
@do-epub-studio/ui#build 0.00 MISS - 🔄
@do-epub-studio/web#build 0.00 MISS - 🔄
@do-epub-studio/worker#build 0.00 MISS - 🔄

Cache Hit Ratio: 0% (0/7 tasks)

🧪 Test Stability

Metric Value Trend Status
Total Tests 0 - -
Failed Tests 0 -
Flaky Rate 0.00% -

@github-actions github-actions Bot added documentation Improvements or additions to documentation area:web area:worker tests labels Aug 15, 2026
@codacy-production

codacy-production Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 114 complexity · 64 duplication

Metric Results
Complexity 114
Duplication 64

View in Codacy

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.

@owl-watch owl-watch Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦉 OwlWatch reviewed this change — 1 new finding(s).

Comment thread apps/web/src/features/auth/LoginPage.tsx Outdated
@repowise-bot

repowise-bot Bot commented Aug 15, 2026

Copy link
Copy Markdown

✅ Health of changed files: 5.0 → 5.5 (+0.4)
🚨 Change risk: high, riskier than 97% of this repo's commits.

📋 At a glance
1 file changed health · 5 hotspots touched · 5 new findings introduced · 1 co-change pair left out · 5 files with recent fix history · 9 dead-code findings.

Files & modules (2)
  • apps (9 files)
    • .../i18n/ru.ts
    • .../lib/env.ts
    • .../auth/LoginPage.test.tsx
    • .../i18n/de.ts
    • .../i18n/fr.ts
    • .../i18n/en.ts
    • .../auth/LoginPage.tsx
    • .../src/App.tsx
    • .../api/core.ts
  • scripts (2 files)
    • scripts/seed-demo-accounts.mjs
    • scripts/check-adr-index.mjs

✅ Health gate: passed

📌 Before you merge

  • Run apps/tests/a11y-advanced.spec.ts, apps/tests/accessibility-audit.spec.ts, apps/tests/catalog-admin-flows.spec.ts, .../reader/ReaderPage.test.tsx (+16 more): they import the changed files
  • .../reader/ReaderPage.tsx changed together with .../i18n/de.ts in 14 past commits and isn't in this PR

🎯 Blast radius (symbols whose signature this PR changed, and who calls them)

  • mockAdminApi in apps/tests/fixtures.ts signature changed. Called by 5 symbols outside this PR: apps/tests/a11y-advanced.spec.ts::__module__, apps/tests/accessibility-audit.spec.ts::__module__, apps/tests/catalog-search.spec.ts::__module__ (+2 more)
🔎 More signals (4)

🗺️ Change map

flowchart LR
  subgraph PR ["Changed in this PR (3 modules)"]
    m_apps_tests["apps/tests (1 file)"]:::changed
    m_apps_web["apps/web (16 files)"]:::changed
    m_apps_worker["apps/worker (5 files)"]:::changed
  end
  d_apps_web["apps/web"]
  m_apps_worker -->|1 file| d_apps_web
  classDef changed fill:#dbeafe,stroke:#1d4ed8,color:#1e3a5f
  classDef warn fill:#fef3c7,stroke:#b45309,color:#78350f
  classDef guard fill:#dcfce7,stroke:#15803d,color:#14532d
Loading

Solid arrows: code that imports the changed files (64 direct dependents, from the last indexed snapshot). Dashed: history/tests.

🔥 Hotspots touched (5)

  • .../i18n/ru.ts: 16 commits/90d, 15 dependents
  • .../lib/env.ts: 5 commits/90d, 58 dependents
  • scripts/check-adr-index.mjs: 1 commits/90d, 0 dependents
2 more
  • .../auth/LoginPage.test.tsx: 3 commits/90d, 0 dependents
  • .../i18n/de.ts: 39 commits/90d, 19 dependents

🔗 Hidden coupling (3 files)

  • .../i18n/de.ts co-changes with .../reader/ReaderPage.tsx (14×, 🟡 notable), not in this PR.
  • .../i18n/fr.ts co-changes with .../reader/ReaderPage.tsx (14×, 🟡 notable), not in this PR.
  • .../i18n/en.ts co-changes with .../reader/ReaderPage.tsx (14×, 🟡 notable), not in this PR.

💀 Dead code (10 findings)

  • 💀 scripts/check-adr-index.mjs scriptDir (confidence 0.65)
  • 💀 scripts/check-adr-index.mjs repoRoot (confidence 0.65)
  • 💀 scripts/check-adr-index.mjs fileIdx (confidence 0.65)
7 more
  • 💀 scripts/check-adr-index.mjs errors (confidence 0.65)
  • 💀 scripts/check-adr-index.mjs numbers (confidence 0.65)
  • 💀 scripts/check-adr-index.mjs sections (confidence 0.65)
  • 💀 .../api/core.ts DEFAULT_TIMEOUT_MS (confidence 0.65)
  • 💀 .../api/core.ts MAX_RETRIES (confidence 0.65)
  • 💀 .../api/core.ts INITIAL_BACKOFF_MS (confidence 0.65)
  • ✅ Removed: repoRoot in scripts/check-adr-index.mjs

📊 See the full report for this PR
Your repo map with this PR's blast radius lit up, every caller of the contracts it changes, and health before and after. No sign-in. · ⭐ Star Repowise · 📥 Install bot · Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot · Updated 2026-08-19 19:45 UTC

d-oit added 11 commits August 19, 2026 21:44
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.
@d-oit
d-oit force-pushed the plan/demo-login-help-goap branch from 5f8fd8f to 94393df Compare August 19, 2026 19:44
@d-oit
d-oit merged commit 07f53a7 into main Aug 19, 2026
28 checks passed
@d-oit
d-oit deleted the plan/demo-login-help-goap branch August 19, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:web area:worker ci documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant