Files
dh-inspeccion-v2/docs/PHASE_A2.md

2.1 KiB

DH Inspección V2 — Fase A2

Versión

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

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

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

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.