Sfoglia il codice sorgente

[Scope] Note recovery page StrictMode fix (useQuery dedupe)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User 2 mesi fa
parent
commit
b3c44ad5ce
1 ha cambiato i file con 1 aggiunte e 1 eliminazioni
  1. 1 1
      PROJECT_SCOPE.md

+ 1 - 1
PROJECT_SCOPE.md

@@ -485,7 +485,7 @@ Configure HTTP security headers at the Caddy reverse proxy level (not in next.co
 - [ ] 1.2 — Set up self-hosted Supabase Docker stack; replace ALL default secrets before first `docker compose up` (JWT_SECRET → regenerate ANON_KEY + SERVICE_ROLE_KEY together; replace POSTGRES_PASSWORD, DASHBOARD_USERNAME, DASHBOARD_PASSWORD); configure GoTrue: set `GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED=true`, disable email/phone/OAuth auth methods; create schema (users, groups, group_members, movies, landing_reel_posters tables) with CHECK constraints on display_name and group name; define and enable RLS policies on all tables with `WITH CHECK` clauses (see RLS section); initialize Supabase CLI migrations workflow — all schema changes via `supabase migration new`
 - [ ] 1.3 — Configure Supabase client in Next.js using `@supabase/ssr` (`createBrowserClient` for browser, `createServerClient` for server-side with `SUPABASE_INTERNAL_URL`); implement env var validation at startup via t3-env (`@t3-oss/env-nextjs`) with zod — server vars in `server` block, client vars in `client` block; create TMDB API proxy route (`/api/tmdb/*`) to keep API key server-side; set `include_adult=false` on all TMDB calls
 - [ ] 1.4 — Implement anonymous auth via `supabase.auth.signInAnonymously()`; display name input and optional avatar color picker; session managed by Supabase GoTrue via `@supabase/ssr` cookie-based handling (JWT issued automatically); verify GoTrue returns 200 (not 400) — confirm `GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED=true` is set
-- [ ] 1.5 — Implement recovery code generation (24 alphanumeric characters, 128-bit entropy), Argon2id hashing (explicit OWASP parameters: memory=19456 KiB, iterations=2, parallelism=1, output=32 bytes — do not use library defaults), and show-once display screen
+- [ ] 1.5 — Implement recovery code generation (24 alphanumeric characters, 128-bit entropy), Argon2id hashing (explicit OWASP parameters: memory=19456 KiB, iterations=2, parallelism=1, output=32 bytes — do not use library defaults), and show-once display screen. NOTE (2026-05-02, commits f71cb76 + a54a5ca): Fixed a post-signup race on the /recovery page where React 19 StrictMode double-mount caused the page to hang on "Generating your recovery code..." indefinitely (reload was required to see the code). Root cause: the original useMutation + useRef guard fired on the first mount instance; the second instance never observed the response. Fixed by replacing useMutation with useQuery (key: `recovery-code-generate`, staleTime/gcTime: Infinity, refetchOnMount: false) — TanStack Query dedupes the request across mount/remount/StrictMode and persists the result in cache. Server route (POST /api/auth/recovery/generate) unchanged.
 - [ ] 1.6 — Implement recovery code claim flow (enter code → verify against Argon2id hash → restore identity on new device); rate-limit claim endpoint (5 failed attempts per IP per 15-minute window); invalidate code after successful claim
 - [ ] 1.7 — Build Docker infrastructure: multi-stage Dockerfile (node:22-slim, non-root user, tini; builder stage installs `python3 make g++` for argon2 native build), docker-compose.yml orchestrating Next.js app + self-hosted Supabase stack + Caddy reverse proxy + Node.js cron container + pg_dump backup container (daily, 7-day retention), .dockerignore, /api/health endpoint; network security: Kong/Postgres ports internal only, Studio restricted to 127.0.0.1; Caddy persistent volumes for `/data` and `/config` (TLS certificates); Docker log rotation on all containers (max-size: 10m, max-file: 5); use Let's Encrypt staging for initial testing; deploy and confirm Supabase connection works in production
 - [ ] 1.8 — Add Sentry error monitoring (free tier); configure `beforeSend` to strip UUID path segments from error events; do not call `Sentry.setUser()` with user identifiers