# TESTS — F-005 Identity: register, login, sessions ## Unit — src/modules/identity/tests/login-rate-limiter.test.ts 1. Allows attempts below threshold; records failures 2. Blocks with retryAfterMs after 10 consecutive failures (AC4 logic) 3. Success resets the counter 4. Cooldown expiry re-allows attempts ## Unit — src/modules/identity/tests/session-token.test.ts 1. Tokens are unique and URL-safe 2. hashSessionToken is deterministic sha256 hex and never equals the raw token ## Integration — src/app/tests/identity.itest.ts (real PostgreSQL, fresh DB per run) 1. register: 201 + body {id, email, createdAt}; DB row stores $argon2id$ hash; plaintext password appears nowhere in the row (AC3) 2. register duplicate email: 409 EMAIL_ALREADY_REGISTERED 3. register invalid payload: 400 VALIDATION_ERROR 4. login valid: 200 + mdv_session cookie with HttpOnly; SameSite=Lax; Secure; Max-Age (AC1, AC5) 5. login wrong password: 401 INVALID_CREDENTIALS; unknown email returns byte-identical error body (AC2) 6. rate limit: 10 failed logins then next attempt -> 429 TOO_MANY_ATTEMPTS + Retry-After header (AC4) 7. logout: 204 + cookie cleared; session row revoked; second logout still 204 (idempotent) 8. buildApp without pool: /auth/login is 404 (foundation-only app preserved) ## QA live - register/login/logout over HTTP with curl; cookie flags visible in Set-Cookie - verify.sh green (AC6)