diff --git a/.planning/phases/02-admin-area-interactive-features/02-01-SUMMARY.md b/.planning/phases/02-admin-area-interactive-features/02-01-SUMMARY.md new file mode 100644 index 0000000..0e904bc --- /dev/null +++ b/.planning/phases/02-admin-area-interactive-features/02-01-SUMMARY.md @@ -0,0 +1,92 @@ +--- +phase: "02-admin-area-interactive-features" +plan: 01 +subsystem: "auth" +tags: [next-auth, credentials, jwt, admin, session, middleware] +dependency_graph: + requires: [] + provides: [admin-session-auth, admin-login-page, proxy-admin-guard] + affects: [src/proxy.ts, src/lib/auth.ts] +tech_stack: + added: [next-auth@4] + patterns: [CredentialsProvider, JWT session strategy, edge proxy guard] +key_files: + created: + - src/lib/auth.ts + - src/app/api/auth/[...nextauth]/route.ts + - src/app/admin/login/page.tsx + modified: + - src/proxy.ts + - package.json + - package-lock.json + - .env.local +decisions: + - "Keep proxy export named 'proxy' (not 'middleware') — Next.js 16 renamed the middleware concept back to proxy, breaking the plan's rename instruction" + - "Wrap useSearchParams() in Suspense boundary — required by Next.js App Router for static prerendering" + - "Single admin user, env-var credentials only — no DB users table (stateless JWT)" +metrics: + duration: "~15 minutes" + completed: "2026-05-15T08:42:35Z" + tasks_completed: 2 + files_changed: 7 +--- + +# Phase 02 Plan 01: Auth.js Admin Session + Proxy Guard Summary + +Auth.js v4 CredentialsProvider with JWT sessions gates the entire /admin/* area using env-var credentials (no DB users table), with an edge proxy guard in src/proxy.ts that validates sessions via getToken() before any admin page code runs. + +## What Was Built + +### Task 1: next-auth@4 installation and auth config +- Installed `next-auth@4` (stable; v5 still RC as of 2026-05-15) +- Created `src/lib/auth.ts` — NextAuthOptions with CredentialsProvider reading `ADMIN_EMAIL` + `ADMIN_PASSWORD` from env vars; JWT session strategy (stateless, no DB adapter) +- Created `src/app/api/auth/[...nextauth]/route.ts` — NextAuth catch-all handler (GET + POST) +- Updated `.env.local` with `NEXTAUTH_URL`, `NEXTAUTH_SECRET` (32-byte base64), `ADMIN_EMAIL`, `ADMIN_PASSWORD` + +### Task 2: Proxy guard and login page +- Extended `src/proxy.ts` with `/admin/*` session guard using `getToken()` from `next-auth/jwt` +- `/admin/login` and `/api/auth/*` exempted from the guard (pass-through) +- Unauthenticated `/admin/*` requests redirect to `/admin/login?callbackUrl=` +- `/c/:path*` client token validation logic preserved verbatim from Phase 1 +- matcher updated: `["/admin/:path*", "/c/:path*"]` +- Created `src/app/admin/login/page.tsx` — email+password Client Component with `signIn('credentials')`, inline error display ("Email o password non corretti."), redirect on success + +## Commits + +| Task | Commit | Description | +|------|--------|-------------| +| 1 | 5d363a6 | feat(02-01): install next-auth@4, configure CredentialsProvider auth | +| 2 | 69f8a7e | feat(02-01): extend proxy.ts with admin session guard, add login page | + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Next.js 16 proxy export name is 'proxy', not 'middleware'** +- **Found during:** Task 2 first build attempt +- **Issue:** The plan instructed renaming the export to `middleware` (Next.js 15 convention), but this project runs Next.js 16.2.6, which introduced the `proxy` concept and requires the function to be named `proxy`. The build failed with: "Proxy is missing expected function export name" +- **Fix:** Kept the export name as `proxy` — consistent with the existing Phase 1 file and Next.js 16 API +- **Files modified:** `src/proxy.ts` + +**2. [Rule 1 - Bug] useSearchParams() requires Suspense boundary in App Router** +- **Found during:** Task 2 second build attempt +- **Issue:** `useSearchParams()` in a Client Component causes a build failure during static page generation without a Suspense boundary. Error: "useSearchParams() should be wrapped in a suspense boundary at page /admin/login" +- **Fix:** Extracted the form into `AdminLoginForm` component; wrapped it in `` inside the default export `AdminLoginPage` +- **Files modified:** `src/app/admin/login/page.tsx` + +## Known Stubs + +None — all implemented functionality is complete and functional. + +## Threat Surface Scan + +No new security surface beyond what was planned in the threat model: +- T-02-01: Mitigated — CredentialsProvider validates against env vars server-side +- T-02-02: Mitigated — JWT signed with NEXTAUTH_SECRET, verified via getToken() on every /admin request +- T-02-03: Mitigated — ADMIN_PASSWORD stored only in .env.local (gitignored) and Vercel secrets +- T-02-04: Accepted — /api/auth/* exempt by design, NextAuth handles its own CSRF +- T-02-05: Accepted — No rate limiting in v1 + +## Self-Check: PASSED + +All created files exist on disk. Both task commits (5d363a6, 69f8a7e) verified in git log.