Shipped in Phase B: emailVerified gate in Credentials authorize(), verification token model (24h, hashed, single-use), signup issues verify email without session, /verify-email route, grandfather script, and Playwright happy-path E2E. Resend UI and token edge-case E2E spun out.
Status: done (2026-05-24) · Source: [[Projects/personal-finance-notion/context/audit-2026-05-17-auth|Auth audit 2026-05-17 §C2]]
emailVerified on userModel (Date | null, Auth.js convention)src/lib/models/emailVerificationTokenModel.tssrc/lib/actions/emailVerification.ts — issueEmailVerificationToken, verifyEmail, requestEmailVerificationsrc/lib/actions/auth.ts → awaitingVerification only (no session)EmailNotVerified in src/auth.tstests/grandfather-email-verified.mjstests/e2e/email-verify.spec.ts — signup → blocked login → verify → sign inemailVerified field addedemail-verify