Files
2026-05-27 23:29:53 +01:00

4.0 KiB

Tasks: enterprise-react-auth-whitelabel

Change ID: enterprise-react-auth-whitelabel Package: @suaveplan/react-auth-whitelabel Target path: react/auth/react-auth-whitelabel Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/react-translate


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 proposal layout.
  • Write package.json at 0.1.0 with "sideEffects": false, exports map.
  • Dependencies: @suaveplan/error workspace:^, @suaveplan/react-translate workspace:^, @hookform/resolvers catalog:forms, react-hook-form catalog:forms, clsx catalog:ui, tailwind-merge catalog:ui, zod catalog:forms, tslib catalog:build.
  • Write tsconfig.json, vitest.config.ts, scripts.

2. Error codes and types

  • Define AuthWhitelabelError extending SuaveplanError; codes: AUTH_WL_CONTEXT_MISSING, AUTH_WL_INVALID_BRANDING.
  • Define TenantBranding: { logoUrl?: string; primaryColor?: string; secondaryColor?: string; fontFamily?: string; companyName?: string }.
  • Write TenantBrandingSchema Zod schema.
  • Define AuthConfig, AuthUser, AuthContextValue, BrandingContextValue, BrandingProviderProps, AuthProviderConfig + AuthProviderProps.

3. BrandingContext + BrandingProvider

  • Provides TenantBranding via context; validates on mount via TenantBrandingSchema; throws AuthWhitelabelError(AUTH_WL_INVALID_BRANDING) on invalid.
  • Hooks: useBranding(): BrandingContextValue, useLogo(): string | undefined, useTenantBranding(): TenantBranding.
  • Write test + md.

4. AuthContext + AuthProvider

  • Manages user: AuthUser | null, isAuthenticated.
  • login(credentials), logout(), loginWithProvider(providerUrl) — uses onNavigate(url) callback (not direct window.location.href).
  • useAuth(), useUser(), useIsAuthenticated() hooks throw AuthWhitelabelError(AUTH_WL_CONTEXT_MISSING) outside provider.
  • Write auth-context.test.tsx (≤500 lines): login, logout, loginWithProvider calls onNavigate, context missing. { timeout: 5000 }.
  • Write auth-context.md.

5. Form components

For each (LoginForm, RegisterForm, PasswordResetForm):

  • react-hook-form + @hookform/resolvers/zod; useTranslation for all labels/errors/buttons.
  • Respects BrandingProvider — applies primaryColor, fontFamily via CSS variables.
  • Write <form>.test.tsx (≤500 lines): valid submit, invalid submit errors, branding applied. { timeout: 5000 }.
  • Write <form>.stories.tsx: default, custom-branding, loading, error, playground.
  • Write <form>.md.

PasswordResetForm: supports mode: 'request' | 'confirm' switching between PasswordResetRequestValues and PasswordResetConfirmValues.


6. E2E (3 files)

  • e2e/login-form.spec.ts — fill email + password, submit → onLogin called.
  • e2e/register-form.spec.ts — fill all fields, submit → onRegister called.
  • e2e/password-reset-form.spec.ts — request mode: fill email, submit; confirm mode: fill passwords, submit.

7. Verify and publish

  • bunx turbo lint typecheck test --filter=@suaveplan/react-auth-whitelabel — green.
  • bunx turbo test:coverage --filter=@suaveplan/react-auth-whitelabel — 100%.
  • bun scripts/publish.ts --package @suaveplan/react-auth-whitelabel.
  • Archive change folder.