{
  "feature_id": "F-005",
  "agent": "qa",
  "verdict": "APPROVED",
  "summary": "Los 6 criterios de aceptación pasan con evidencia doble: suite automatizada (47 unit + 14 integration) y smoke live contra PostgreSQL real. Sin regresiones en F-001..F-004.",
  "acceptance_criteria": {
    "AC1_login_200_with_cookie": "PASS - integration 'login with valid credentials -> 200 + secure cookie' + curl live: HTTP 200 + Set-Cookie mdv_session=...; Max-Age=604800; Path=/; HttpOnly; Secure; SameSite=Lax",
    "AC2_wrong_password_401_no_enumeration": "PASS - integration compara bodies .error idénticos para wrong-password vs unknown-email; curl live confirma 401 INVALID_CREDENTIALS genérico en ambos",
    "AC3_argon2_never_plaintext": "PASS - integration: fila DB password_hash arranca con $argon2id$ y el plaintext no aparece en ningún valor serializado de la fila",
    "AC4_rate_limit_429": "PASS - integration: 10 fallos -> 429 TOO_MANY_ATTEMPTS + Retry-After > 0; live: 401×10 y luego 429 con retry-after: 900",
    "AC5_cookie_flags": "PASS - integration valida HttpOnly + SameSite=Lax + Secure + Max-Age sobre el header Set-Cookie; confirmado en vivo",
    "AC6_verify_green": "PASS - ./scripts/verify.sh OK tras el cierre de build+gates"
  },
  "regression": {
    "health_endpoint": "PASS (suite)",
    "error_envelope_v2_404": "PASS (suite) + foundation-only app sin pool mantiene /auth 404 (integration)",
    "config_fail_fast": "PASS (suite: DATABASE_URL missing, COOKIE_SECURE inválido reporta variable)",
    "feature_flags": "PASS (suite: unknown OFF, case-insensitive, runtime flip)",
    "migrations_lifecycle": "PASS (integration: fresh up full schema, second up no-op, full down limpio)"
  },
  "evidence": [
    "npm run lint / lint:boundaries (39 files) / typecheck / build: clean",
    "npm test: 47 passed | 14 skipped",
    "npm run test:integration: 14/14 passed",
    "curl live: register 201, login 200+cookie, wrong/unknown 401 idénticos, logout 204+clear, 429+Retry-After",
    "./scripts/verify.sh: OK"
  ],
  "notes": "Logout smoke verificado: cookie borrada (Max-Age=0 + Expires 1970) y fila de sesión con revoked_at IS NOT NULL en DB."
}
