Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
# Tasks — complete-react-auth
**Change ID**: complete-react-auth
**Package**: `@suaveplan/react-auth`
**Target path**: `packages/auth/react-auth/`
Pre-flight: `@suaveplan/types`, `@suaveplan/error`, `@suaveplan/events`, `@suaveplan/logger`, `@suaveplan/i18n`, `@suaveplan/webauthn`, `@suaveplan/oauth-client`, `@suaveplan/srp`, `@suaveplan/otp`, `@suaveplan/hibp`, `@suaveplan/password-strength`, `@suaveplan/password-generator`, `@suaveplan/react-ui` — all ✅ on Verdaccio.
---
## 0. Pre-flight (non-negotiable)
- [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each)
- [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
- [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest.
## 1. Scaffold
- [ ] Create directory tree per `design.md` § File layout.
- [ ] Write `package.json` at `0.1.0`, `"sideEffects": false`, `react ^19.0.0` peer, every internal dep as `workspace:^`, every external dep via catalog.
- [ ] Write `tsconfig.json` (extends `@suaveplan/typescript-config/browser-react.json`), `vitest.config.ts` (forks pool, fileParallelism false, istanbul 100/100/100/100), `playwright.config.ts` via `@suaveplan/testing-e2e` factory.
- [ ] Write `README.md` at package root — overview, install, quick-start (provider + sign-in form), Modules section linking every co-located `.md`.
## 2. Types + schemas + errors
- [ ] `src/types/auth-user.ts`, `auth-state.ts`, `auth-backend.ts`, `session.ts`, `idle-config.ts`, `permission-resolver.ts` — each with sibling `.md` (≥ 200 words).
- [ ] `src/schemas/schemas.ts` — Zod schemas for every hook option bag (`SignInOptions`, `SignUpOptions`, `UsePasskeyAutofillOptions`, `UseOAuthSignInOptions`, …). Sibling `.md`, `schemas.test.ts`.
- [ ] `src/errors/errors.ts` — `defineCodes("REACT_AUTH", [...])` for the 29 codes in `design.md` § Error code namespace. Export `ReactAuthError`. Sibling `.md`, `errors.test.ts` covering: every code reachable from a production path; translation helpers preserve `cause`.
## 3. Utilities
- [ ] `src/utils/compose-signals.ts` (+ `.md`, `.test.ts`) — `AbortController` composition (any abort → composed abort).
- [ ] `src/utils/is-ssr.ts` (+ `.md`, `.test.ts`).
- [ ] `src/utils/announce.ts` (+ `.md`, `.test.ts`) — ARIA live-region helper (creates a single shared `aria-live="polite"` node on first call).
## 4. Session — storage, broadcast, idle, refresh, forced-logout
- [ ] `src/session/storage/memory/memory.ts` (+ `.md`, `.test.ts`).
- [ ] `src/session/storage/local/local.ts` (+ `.md`, `.test.ts`).
- [ ] `src/session/storage/session/session.ts` (+ `.md`, `.test.ts`).
- [ ] `src/session/broadcast-channel.ts` (+ `.md`, `.test.ts`) — typed envelope, factory injection, SSR no-op.
- [ ] `src/session/auto-refresh.ts` (+ `.md`, `.test.ts`) — schedule via injected `Clock`; cancels on every state update.
- [ ] `src/session/idle-timer.ts` (+ `.md`, `.test.ts`) — pointer/key/visibility listeners; debounced; `onWarn`/`onTimeout`.
- [ ] `src/session/forced-logout.ts` (+ `.md`, `.test.ts`) — broadcasts + clears storage synchronously.
## 5. Provider + context
- [ ] `src/auth-provider/auth-context.ts` (+ `.md`, `.test.ts`).
- [ ] `src/auth-provider/use-auth-context.ts` (+ `.md`, `.test.ts`) — throws `REACT_AUTH.CONTEXT_MISSING` outside provider.
- [ ] `src/auth-provider/load-persisted-session.ts` (+ `.md`, `.test.ts`).
- [ ] `src/auth-provider/auth-provider.tsx` (+ `.md`, `.test.tsx`, `.stories.tsx`) — wires backend + storage + broadcast + idle + auto-refresh; deterministic SSR render; effect-only DOM access.
## 6. Lifecycle hooks
- [ ] `src/hooks/use-auth/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-user/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-is-authenticated/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-session/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-sign-in/` (+ `.md`, `.test.ts`) — supports password, SRP, passkey result handoff.
- [ ] `src/hooks/use-sign-up/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-sign-out/` (+ `.md`, `.test.ts`) — broadcasts `signed-out`.
- [ ] `src/hooks/use-refresh-token/` (+ `.md`, `.test.ts`).
## 7. Password hooks + components
- [ ] `src/hooks/use-change-password/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-password-reset/` (+ `.md`, `.test.ts`) — `request` + `confirm`.
- [ ] `src/components/password-strength-meter/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — wraps `password-strength.assessReactive`; cancels on unmount.
- [ ] `src/components/hibp-pwned-indicator/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — debounced ≥ 500 ms; SSR no-op; injected `HibpClient`.
- [ ] `src/components/password-input/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — show/hide, label association, `aria-describedby`, optional strength + HIBP slots.
- [ ] `src/components/password-generator-button/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — popover via `@suaveplan/react-ui` `<Popover>`; passphrase/chars/pin modes.
## 8. Passkey hooks + components
- [ ] `src/hooks/use-register-passkey/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-authenticate-with-passkey/` (+ `.md`, `.test.ts`) — modal mediation.
- [ ] `src/hooks/use-passkey-autofill/` (+ `.md`, `.test.tsx`) — folded from superseded autofill change; SSR-safe; `isConditionalMediationAvailable` feature-detect; composed `AbortController`; stable `abort`.
- [ ] `src/components/passkey-autofill-field/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — `<input autocomplete="username webauthn">` wrapper; blur cancels when no credential delivered.
- [ ] `src/components/passkey-list/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — lists from `backend.listPasskeys`; per-row revoke with accessible confirm dialog.
## 9. OAuth
- [ ] `src/oauth/provider-registry.ts` (+ `.md`, `.test.ts`) — `register / get / has / list / unregister`; descriptor includes label key + icon slot + scopes.
- [ ] `src/oauth/popup.ts` (+ `.md`, `.test.ts`) — centred-window helper; `postMessage` origin check; popup-blocked detection.
- [ ] `src/oauth/redirect.ts` (+ `.md`, `.test.ts`) — `sessionStorage` return-state persist; `window.location.assign`.
- [ ] `src/oauth/handle-callback.ts` (+ `.md`, `.test.ts`) — parses query, validates state, exchanges code, dispatches result; idempotent on remount.
- [ ] `src/hooks/use-oauth-sign-in/` (+ `.md`, `.test.ts`) — popup + redirect modes; PKCE via `@suaveplan/oauth-client`.
- [ ] `src/components/oauth-provider-button/` (+ `.md`, `.test.tsx`, `.stories.tsx`).
## 10. MFA
- [ ] `src/hooks/use-enroll-totp/` (+ `.md`, `.test.ts`) — `begin` + `finish`.
- [ ] `src/hooks/use-verify-totp/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-enroll-webauthn-second-factor/` (+ `.md`, `.test.ts`) — wraps `register` with `authenticatorSelection.authenticatorAttachment`.
- [ ] `src/hooks/use-recovery-codes/` (+ `.md`, `.test.ts`) — `generate` + `verify`.
- [ ] `src/components/totp-enrollment-panel/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — orchestrates secret display → caller-provided QR slot → code entry → recovery-codes reveal.
- [ ] `src/components/recovery-codes-panel/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — copy / download / acknowledge before dismiss.
## 11. Verification flows
- [ ] `src/hooks/use-email-verification/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-phone-verification/` (+ `.md`, `.test.ts`).
- [ ] `src/components/email-verification-view/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — resend cooldown timer.
- [ ] `src/components/phone-verification-view/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — `inputMode="numeric"`, `autocomplete="one-time-code"`.
## 12. Guards
- [ ] `src/hooks/use-permission/` (+ `.md`, `.test.ts`).
- [ ] `src/hooks/use-auth-guard/` (+ `.md`, `.test.ts`).
- [ ] `src/components/auth-guard/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — `withAuth` HOC alongside component.
- [ ] `src/components/permission-gate/` (+ `.md`, `.test.tsx`, `.stories.tsx`).
## 13. Error boundary
- [ ] `src/components/auth-error-boundary/` (+ `.md`, `.test.tsx`, `.stories.tsx`) — catches `SuaveplanError` whose code starts `REACT_AUTH.`; renders i18n-keyed fallback; re-throws everything else.
## 14. i18n
- [ ] `src/i18n/en-gb/index.ts` (+ `.md`) — canonical catalogue with every `react-auth.*` key used in the package.
- [ ] `src/i18n/cy-gb/index.ts` (+ `.md`) — full Welsh translation.
- [ ] `src/i18n/zh-cn/index.ts` (+ `.md`) — full Simplified Chinese translation.
- [ ] `src/i18n/parity.test.ts` — asserts every locale has the same key set as `en-GB`; fails CI on drift.
- [ ] `src/i18n/no-hardcoded-strings.test.ts` — scans `components/**/*.tsx` for hardcoded user-visible strings; allowlist limited to test fixtures.
## 15. Index + subpath exports
- [ ] `src/index.ts` — explicit named re-exports (rule 6a); namespace re-exports for `errors` and `schemas`.
- [ ] `package.json` `exports` map — one entry per subpath per `proposal.md`.
- [ ] Type-only re-exports separated via `export { type X }`.
## 16. Playwright E2E
- [ ] `e2e/fixtures/app.tsx` — minimal test app wiring an in-memory `AuthBackend`.
- [ ] `e2e/password-sign-in.spec.ts`, `sign-up.spec.ts`, `password-reset.spec.ts`, `change-password.spec.ts`.
- [ ] `e2e/passkey-register.spec.ts`, `passkey-autofill.spec.ts`, `passkey-modal-authenticate.spec.ts` (virtual-authenticator via Playwright CDP).
- [ ] `e2e/oauth-popup.spec.ts`, `oauth-redirect.spec.ts` — stubbed authorization endpoint.
- [ ] `e2e/totp-enroll-verify.spec.ts`, `recovery-codes.spec.ts`.
- [ ] `e2e/email-verification.spec.ts`, `phone-verification.spec.ts`.
- [ ] `e2e/multi-tab-sync.spec.ts` — two browser contexts share the same backend; sign-out in tab A propagates to tab B.
- [ ] `e2e/idle-timeout.spec.ts` — idle config fires `onTimeout` after configured ms; user is forced out.
- [ ] `e2e/error-boundary.spec.ts` — triggers a `BACKEND_ERROR`; verifies the boundary fallback renders.
- [ ] `e2e/rtl-locale.spec.ts` — renders with an RTL locale (e.g. `ar`) via the parent app; verifies `dir="rtl"` propagates.
- [ ] `e2e/accessibility.spec.ts` — `@axe-core/playwright` sweep across every canonical page; zero serious / critical violations.
## 17. Spec reconciliation (CLAUDE.md §13 step 0)
- [ ] Open `specs/react-auth/spec.md`. Walk every `### Requirement` and `#### Scenario`. For each `**Verified by:**` path, confirm the test file exists and the test name matches verbatim.
- [ ] Confirm every error code in `defineCodes("REACT_AUTH", …)` is reached from a real production path (not just a registry entry).
## 18. Pre-publish gates
- [ ] `bunx turbo lint typecheck test --filter=@suaveplan/react-auth` — green.
- [ ] `bunx turbo test:coverage --filter=@suaveplan/react-auth` — 100/100/100/100.
- [ ] `bunx turbo build --filter=@suaveplan/react-auth` — green.
- [ ] Banned-pattern scan zero (`@deprecated|TODO|FIXME|ts-ignore|ts-expect-error|\.skip|\.only|console\.log`).
- [ ] Barrel-shape scan zero (`export *` only in `src/index.ts` namespace forms).
- [ ] Test-runner import scan zero (`from "vitest"` / `from "bun:test"` outside the exempt allowlist).
- [ ] Missing-`.md` scan zero.
- [ ] Bare-version scan zero.
- [ ] Subpath export count matches feature-module count.
- [ ] React version check: `find . -path "*/node_modules/react/package.json"` returns a single version.
## 19. Root-doc refresh
- [ ] `bun scripts/folder-reorg/generate-manifest.ts` (refresh `MANIFEST.md`).
- [ ] `bun scripts/generate-missing.ts` (refresh `MISSING.yml`).
- [ ] Edit `STATUS.md` — move `@suaveplan/react-auth` from `–` to ✅; add summary paragraph.
- [ ] Edit `SUMMARY.md` — add per-package paragraph (features, deps, decisions).
- [ ] `bunx markdownlint-cli2 --fix` — touched files.
## 20. Supersede existing change folders
- [ ] `mv openspec/changes/enterprise-react-auth openspec/changes/_superseded-narrow-deferrals-2026-05-17/enterprise-react-auth` — fold under the existing supersede bucket.
## 21. Fold spec delta + archive
- [ ] Fold `specs/react-auth/spec.md` into `openspec/specs/react-auth/spec.md` (canonical home).
- [ ] `mv openspec/changes/complete-react-auth openspec/archive/<yyyy-mm-dd>-complete-react-auth/`.
- [ ] `bun scripts/publish.ts --package @suaveplan/react-auth`.