# 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` ``; 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`) — `` 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/-complete-react-auth/`. - [ ] `bun scripts/publish.ts --package @suaveplan/react-auth`.