feat: version 3.0.0 -- Correcciones de auditoria de seguridad, accesibilidad y redundancia

Permisos (superadmin, viewer, busqueda, tareas recurrentes), bootstrap atomico,
revocacion de JWT por version de sesion (028), control optimista de edicion (029),
logo sin SVG + CSP, ingesta endurecida, correos escapados, borradores, paginacion
de proyectos, accesibilidad de dialogos/controles e i18n.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-10-23 11:36:02 -05:00
parent 8ed1d63505
commit e65111a7f4
112 changed files with 2285 additions and 651 deletions
+10 -1
View File
@@ -24,13 +24,22 @@ Navegador (superadmin/admin/it_manager) --JWT--> /api/devices -> menú "Equipos
- **Handshake:** el agente primero manda un `contact` (JSON) o `PROLOG` (XML). Se responde sin
guardar nada (`{"status":"ok","expiration":"24"}` o `<REPLY><RESPONSE>SEND</RESPONSE>…`).
- **Ingesta autenticada por token**, no por JWT: tabla `inventory_tokens` (solo hash sha256). El
- **Ingesta autenticada por token**, no por JWT: tabla `inventory_tokens` (hash sha256 para validar
y copia cifrada para recuperar el instalador). El
agente lo manda como contraseña Basic (`user`/`password` del `agent.cfg`), `Bearer`,
`X-Ingest-Token` o `?token=`. Sin token válido → `401`.
- Compatibilidad: `?token=` sigue aceptado para agentes instalados; la aplicación censura ese
parámetro en sus logs. El proxy inverso debe censurarlo también en sus propios access logs.
- **Pendiente de seguridad:** hoy un instalador puede usar el mismo token en varios equipos.
Vincular automáticamente token y `deviceid` rompería esos agentes ya instalados. Antes de
activarlo se necesita inventariar instalaciones y migrar a un token por equipo; luego añadir
la asociación y rechazar inventarios de otro `deviceid`.
- **Rutas:** `POST /api/inventory` (propia; pasa por el Custom Location `/api` de NPM sin cambios)
y alias `POST /front/inventory.php` (ruta nativa de GLPI). Se montan ANTES de `express.json`
porque usan cuerpo crudo.
- **Límites:** cuerpo máx. 15 MB (`INVENTORY_MAX_BYTES`), inflado máx. 4× (anti zip-bomb).
- Cada IP tiene límite de 120 peticiones/minuto; máximo dos ingestiones simultáneas. El token se
valida antes de leer el cuerpo y el parseo se ejecuta en un worker con límite de tiempo.
- **Upsert por `deviceid`** (estable), nunca por hostname. Componentes se reemplazan completos en
una transacción; el diff (RAM, disco agregado/retirado, software instalado/desinstalado, SO,
hostname) queda en `device_changes`.