Alertas de Seguridad
Alertas de Seguridad
Prefijo: /api/alertas-seguridad (tenant) y /api/admin/alertas-seguridad (Superadmin cross-tenant)
Requiere Auth: Sí
Permiso requerido: alertas_seguridad, *
Módulo de alertas de seguridad generadas cuando una cuenta acumula intentos fallidos de login (bloqueo por fuerza bruta). Las alertas permiten a soporte (Superadmin) ver todos los clientes (cross-tenant) y al admin de tenant ver solo las suyas.
Arquitectura: Las alertas se almacenan en la tabla alertas_seguridad (modelo AlertaSeguridad). Se disparan automáticamente desde el login cuando el bloqueo se activa.
Regla anti-spam: a lo sumo 1 alerta abierta por (tenant, usuario, nivel).
| Nivel | Umbral | Descripción |
|---|---|---|
MEDIA | 5 intentos fallidos consecutivos | Umbral suave — atención del admin del tenant |
CRITICA | 10 intentos fallidos consecutivos | ”Situación preocupante” — 2.ª alerta, visibilidad de soporte |
Al resolver una alerta, el siguiente umbral vuelve a activarse y crea una nueva.
Alertas del Tenant (Admin)
GET /api/alertas-seguridad [NUEVO]
Descripción: Lista las alertas de seguridad del tenant actual con paginación y filtros
Requiere Auth: Sí
Permiso requerido: alertas_seguridad, leer
Parámetros query:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
skip | int | ❌ | Número de registros a saltar (default 0) |
limit | int | ❌ | Máximo de registros a retornar (default 100) |
resuelta | bool | ❌ | Filtrar por estado: true (solo resueltas), false (solo pendientes) |
Respuesta exitosa: 200 OK
Response:
[ { "id": 1, "tenant_id": "2d97c7bf-824f-4fe3-a30b-f28cb9da6cba", "tipo": "BRUTE_FORCE", "nivel": "MEDIA", "descripcion": "Posible fuerza bruta en login: soporte@cliente.com con 5 intentos fallidos consecutivos desde IP 190.10.1.23", "usuario_id": 3, "usuario_correo": "soporte@cliente.com", "ip_equipo": "190.10.1.23", "intentos": 5, "resuelta": false, "resuelta_por": null, "resuelta_en": null, "creada_en": "2026-08-13T10:00:00" }]cURL:
curl "http://localhost/api/alertas-seguridad/?skip=0&limit=20&resuelta=false" \ -H "Authorization: Bearer <token>"GET /api/alertas-seguridad/count [NUEVO]
Descripción: Conteo de alertas de seguridad del tenant actual
Requiere Auth: Sí
Permiso requerido: alertas_seguridad, leer
Parámetros query:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
resuelta | bool | ❌ | Filtrar por estado antes de contar |
Respuesta exitosa: 200 OK
Response:
{ "total": 3, "pendientes": 2, "resueltas": 1}GET /api/alertas-seguridad/:alerta_id [NUEVO]
Descripción: Obtiene una alerta de seguridad del tenant actual por ID
Requiere Auth: Sí
Permiso requerido: alertas_seguridad, leer
Parámetros: alerta_id (path, int)
Respuesta exitosa: 200 OK
Errores: 404 (alerta no encontrada)
PATCH /api/alertas-seguridad/:alerta_id/resolver [NUEVO]
Descripción: Marca una alerta de seguridad del tenant actual como resuelta
Requiere Auth: Sí
Permiso requerido: alertas_seguridad, actualizar
Parámetros: alerta_id (path, int)
Respuesta exitosa: 200 OK — alerta con resuelta: true, resuelta_por y resuelta_en
Errores: 404 (alerta no encontrada)
Response:
{ "id": 1, "tenant_id": "2d97c7bf-824f-4fe3-a30b-f28cb9da6cba", "tipo": "BRUTE_FORCE", "nivel": "MEDIA", "descripcion": "Posible fuerza bruta en login: soporte@cliente.com con 5 intentos fallidos consecutivos desde IP 190.10.1.23", "usuario_id": 3, "usuario_correo": "soporte@cliente.com", "ip_equipo": "190.10.1.23", "intentos": 5, "resuelta": true, "resuelta_por": "admin@neoapp.com", "resuelta_en": "2026-08-13T11:00:00", "creada_en": "2026-08-13T10:00:00"}Alertas de Seguridad Globales (Superadmin / Soporte, cross-tenant)
GET /api/admin/alertas-seguridad [NUEVO]
Descripción: Todas las alertas de seguridad de TODOS los tenants (bandeja de soporte)
Requiere Auth: Sí (Superadmin rol=3)
Permiso requerido: N/A (solo Superadmin, bypass RBAC)
Parámetros query:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
skip | int | ❌ | Número de registros a saltar (default 0) |
limit | int | ❌ | Máximo de registros a retornar (default 100) |
resuelta | bool | ❌ | Filtrar por estado |
tenant_id | UUID | ❌ | Filtrar por tenant |
nivel | string | ❌ | Filtrar por nivel: MEDIA, CRITICA |
Respuesta exitosa: 200 OK — lista de alertas (mismo formato que la sección del tenant)
Errores: 403 (no es Superadmin)
GET /api/admin/alertas-seguridad/count [NUEVO]
Descripción: Conteo global de alertas de seguridad de todos los tenants
Requiere Auth: Sí (Superadmin rol=3)
Parámetros query:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
resuelta | bool | ❌ | Filtrar por estado |
tenant_id | UUID | ❌ | Filtrar por tenant |
nivel | string | ❌ | Filtrar por nivel |
Respuesta exitosa: 200 OK
Response:
{ "total": 42, "pendientes": 7, "resueltas": 35}PATCH /api/admin/alertas-seguridad/:alerta_id/resolver [NUEVO]
Descripción: Resuelve una alerta de seguridad de cualquier tenant (soporte)
Requiere Auth: Sí (Superadmin rol=3)
Parámetros: alerta_id (path, int)
Respuesta exitosa: 200 OK — alerta con resuelta: true y resuelta_por
Errores: 403 (no es Superadmin), 404 (alerta no encontrada)