Commits. f21f71d Day-1 audit fixes (C4 + H4) · d5b94ce Phase A migration.
The bespoke rotating-refresh-family JWT stack is gone. Auth.js v5 with the Credentials provider now sits on a JWT-strategy session (sliding 7-day expiry, 24-hour update window). Headline numbers from d5b94ce: 20 files changed, 539 insertions, 1184 deletions — a net reduction of ~640 lines.
New:
src/auth.config.ts — edge-safe NextAuthConfig. Session/JWT module augmentation pins session.user to { userId, email, name, role, newUser, currency }.src/auth.ts — Node entrypoint. Credentials authorize() ports the bcrypt + lockout + per-email rate limit logic from the old actions/user.ts:login. Custom CredentialsSignin subclasses surface error codes (credentials, account_locked, rate_limited).src/app/api/auth/[...nextauth]/route.ts — mounts handlers so next-auth/react works.src/middleware.ts — NextAuth(authConfig).auth wrapper. Public/protected redirects with callbackUrl, plus the four security headers (HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy).Replaced (kept public shape):
src/lib/auth.ts — was ~470 lines of crypto/refresh-family/blacklist; now a 60-line shim. getUserData() calls auth(). UserData type and mappedUserData() preserved.src/components/auth/AuthContext.tsx — <SessionProvider> plus a useAuth() compat hook over useSession()/signIn()/signOut(). The ~10 consumer components compile unchanged.src/lib/actions/auth.ts — signup() now createUser → signIn("credentials", ...). loginAction/logoutAction stubbed with deprecation.src/lib/actions/user.ts — updateNewUserStatus no longer re-issues a token; client refreshes via update({ newUser }).Deleted:
src/lib/auth-cookies.ts, src/lib/auth-edge.tssrc/lib/utils/tokenBlacklist.ts, src/lib/utils/refreshTokenSession.tssrc/lib/models/tokenBlacklistModel.ts, src/lib/models/refreshTokenSessionModel.tssrc/lib/utils/api-client.ts::fetchCurrentUserJWT_SECRET_KEY / JWT_REFRESH_SECRET_KEY env vars (replaced by AUTH_SECRET)| Item | Status after 2026-05-18 |
| ------------------------- | -------------------------------------------- |
| C1 Password reset | Superseded → Phase B |
| C2 Email verification | Superseded → Phase B |
| C3 Signup enumeration | Partial mask in d5b94ce; full fix Phase B |
| C4 API error leakage | ✅ Done — f21f71d |
| H1 CSP | Phase C |
| H2 Login timing | Phase C |
| H3 Blacklist race | ✅ Moot — file deleted in d5b94ce |
| H4 PWA cache leak | ✅ Done — f21f71d |
| M1 Legacy cookie reads | Superseded by Auth.js |
| M2 Role field | Phase C decision |
| M3 Dual JWT secrets | Superseded by Auth.js (single AUTH_SECRET) |
| M4 CSRF posture | Improved by Auth.js defaults |
| M5 Logger stringifier | Phase C |
| L1 Integration API tokens | Elevated to Phase C |
| L2–L7 | Backlog unchanged |
userId field or writing a thin mongoose adapter. Phase A is Credentials-only and Credentials doesn't need an adapter — that decision is deferred to Phase B when Google OAuth lands (the OAuth flow needs to persist accounts/verificationTokens collections).emailVerified + image schema additions deferred. Same reason: only needed once OAuth + verification land.tests/e2e/auth.spec.ts rewrite not needed. The spec is fully black-box (form fill + URL assertions); it works as-is against Auth.js. global.setup.ts likewise — only requires AUTH_SECRET in the env./api/auth/signout didn't fully round-trip; the in-browser flow via next-auth/react::signOut() is what the compat layer uses and was verified manually by the user.npx tsc --noEmit clean for all touched files (four pre-existing errors in integrations.routes.test.ts:42 and transaction.ts:1612-1614 unchanged). End-to-end curl smoke covering: unauth redirect with callbackUrl, public /login, bad-credentials with code=credentials, good-credentials with authjs.session-token cookie, augmented session JSON, /api/user/current parity through the shim, authed protected access, authed /login back-redirect.
AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET + Google Cloud Console setup), custom mongoose adapter (decision 2026-05-18 (b)), Resend transport (RESEND_API_KEY + MAIL_FROM), password-reset token model + flow with sessionsValidAfter-based revocation (decision 2026-05-18 (b)), email-verification token model + flow, auto-link on verified-email match in signIn callback (decision 2026-05-18, revised from earlier "block"), full enumeration-safe signup.src/app/api/user/current/route.ts is preserved for the tests/e2e/api-unauthorized.spec.ts 401 contract — could be removed if we update that test.