Item 1.4 — Register no longer issues an access+refresh token pair. The
prior flow set httpOnly cookies at register but the AuthMiddleware
refused them on every protected route until the user had verified
their email (`core/auth/service.go:527`). Users ended up with dead
credentials and a "logged in but locked out" UX. Register now returns
{user, verification_required: true, message} and the SPA's existing
"check your email" notice fires naturally.
Item 1.3 — `POST /auth/verify-email` reads the token from the
`X-Verify-Token` header in preference to the `?token=…` query param.
Query param logged a deprecation warning but stays accepted so emails
dispatched before this release still work. Headers don't leak through
proxy/CDN access logs that record URL but not headers.
Tests: 18 test files updated (sed `_, _, err :=` → `_, err :=` for the
new Register signature). `core/auth/handler_test.go` gets a
`registerVerifyLogin` helper for tests that exercise post-login flows
(refresh, logout). Two new E2E `@critical` specs lock in the defer-JWT
contract and the header read-path.
OpenAPI + orval regenerated to reflect the new RegisterResponse shape
and the verify-email header parameter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Created TwoFactorHandler with SetupTwoFactor, VerifyTwoFactor, DisableTwoFactor, GetTwoFactorStatus
- Added routes: POST /auth/2fa/setup, POST /auth/2fa/verify, POST /auth/2fa/disable, GET /auth/2fa/status
- Updated LoginResponse DTO to include requires_2fa flag
- Updated Login handler to check 2FA status and return requires_2fa flag when enabled
- Reused existing TwoFactorService (already had QR generation and TOTP verification)
- Added VerifyTOTPCode helper method to TwoFactorService
- All endpoints properly authenticated with RequireAuth middleware
Phase: PHASE-1
Priority: P0
Progress: 4/267 (1.5%)