# DH Inspección V2 — Fase A2 ## Versión ```text v0.2.1 · Fase A2 · Autenticación y sesiones ``` La leyenda se muestra en el footer del frontend. El health de la API también informa `version: 0.2.1` y `phase: A2`. ## Endpoints ```text POST /api/v3/auth/login POST /api/v3/auth/refresh POST /api/v3/auth/logout GET /api/v3/auth/me POST /api/v3/auth/change-password ``` `GET /api/v3/health` continúa siendo el único endpoint público sin datos de negocio. ## Seguridad - passwords con Argon2id; - respuesta genérica para credenciales inválidas; - 5 intentos fallidos y 15 minutos de bloqueo por defecto; - rate limiting por IP; - access token JWT HS256 corto; - refresh token opaco, rotativo y persistido únicamente como HMAC-SHA256; - cookies `HttpOnly`, `Secure` y `SameSite=Strict`; - defensa CSRF de doble envío para operaciones mutables con cookies; - validación estricta del origen web configurado; - sesiones revocables y detección de reutilización; - sanitización de passwords, hashes, tokens, cookies y secretos en auditoría; - `X-Request-ID` en respuestas y eventos de auditoría. El navegador no utiliza `localStorage` ni `sessionStorage` para tokens. ## Migración A2 ```text PhaseA2SessionSecurityIndexes1786548005000 ``` Agrega índices para `users.locked_until` y `auth_sessions.replaced_by_session_id`. No elimina ni transforma datos A1. ## Primer administrador La CLI `npm run bootstrap:admin`: - funciona únicamente en una terminal interactiva; - oculta la contraseña mientras se escribe; - exige entre 12 y 128 caracteres; - evita crear un segundo administrador por bootstrap; - usa una transacción y un advisory lock para impedir ejecuciones simultáneas; - asigna el rol `admin` sembrado en A1; - registra el evento `SYSTEM_BOOTSTRAP_ADMIN_CREATED`; - nunca imprime la contraseña ni su hash. ## Variables nuevas ```text WEB_ORIGIN JWT_ACCESS_SECRET REFRESH_TOKEN_PEPPER ACCESS_TOKEN_TTL_SECONDS REFRESH_TOKEN_TTL_SECONDS AUTH_MAX_LOGIN_ATTEMPTS AUTH_LOCKOUT_SECONDS ACCESS_COOKIE_NAME REFRESH_COOKIE_NAME CSRF_COOKIE_NAME ``` Los dos secretos deben ser diferentes y tener al menos 64 caracteres.