Files
project.linkedcorp.net/docs/ARQUITECTURA-INVENTARIO.md
T
Milton Gonzalez e25c2c3b35 feat: version 2.15.0 -- menu Equipos (inventario de TI con agente GLPI)
Ingesta POST /api/inventory (JSON/XML, token de instalacion), upsert por deviceid,
historial de cambios, pestañas Resumen/Equipos/Software/Agentes, detalle con buscador
por pestaña y casilla para ocultar actualizaciones/drivers/componentes del software.
Migraciones 023 y 024. Diseño en docs/ARQUITECTURA-INVENTARIO.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 19:05:00 -05:00

72 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Arquitectura de inventario — menú "Equipos"
Diseño del módulo Equipos de Project. Se trajo de `linkedtrack.linkedcorp.net` (que sigue como
producto aparte, sin cambios) y se reescribió siguiendo las reglas de Project: mismo login, roles,
auditoría, UI Fluent y una sola base `project_linkedcorp`.
## Decisión de fondo
| Opción | Veredicto |
|---|---|
| Servidor GLPI completo | Descartado: demasiada administración para solo inventariar. |
| Agente 100% propio | Descartado: reescribir el sondeo de hardware (WMI, EDID, SNMP) es frágil y caro. |
| **Agente GLPI oficial + colector propio dentro de Project** | **Elegido.** El agente recolecta; Project recibe, guarda y muestra. |
## Flujo
```
GLPI Agent (cada PC/servidor) --POST inventario--> https://project.linkedcorp.net/api/inventory
(ingest.js: token -> inflar -> parsear JSON/XML
-> normalizer.js -> upsert por deviceid
-> diff en device_changes)
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
agente lo manda como contraseña Basic (`user`/`password` del `agent.cfg`), `Bearer`,
`X-Ingest-Token` o `?token=`. Sin token válido → `401`.
- **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).
- **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`.
- **Baja lógica:** `status = retired`; un reporte nuevo NO reactiva un equipo dado de baja.
- **Crudo para depurar:** último reporte por equipo en `storage/inventories/<hash>.json|xml`
(se sobrescribe; descarga `GET /api/devices/:id/raw`).
## Normalización
`backend/src/modules/devices/normalizer.js`: el JSON nativo y el XML (en mayúsculas) comparten
nombres de campo, así que el XML se pasa a minúsculas y ambos usan el mismo mapeo. Todo campo
ausente queda `null` (el formato varía por versión del agente y SO). Tipo de equipo
(`desktop/laptop/server/virtual/printer/network/other`) se infiere de `chassis_type`, `vmsystem`,
nombre del SO e `itemtype`. Lo que no tiene columna (impresoras/red SNMP, antivirus, video,
batería) se guarda en `devices.extra_json`.
## Instalar el agente en un equipo
1. Superadmin/admin: menú **Equipos → Agentes → Generar token** (se muestra una sola vez).
2. En el equipo, instalar GLPI Agent (MSI en Windows; `.deb`/`.rpm`/tarball en Linux) con:
```
server = https://project.linkedcorp.net/api/inventory
user = project
password = <token>
tag = <opcional>
```
Windows (instalador): `SERVER=… USER=project PASSWORD=<token>`.
3. Forzar un envío: `glpi-agent --force` (Linux) / "Forzar inventario" en la página del agente
(`http://localhost:62354`) en Windows. El equipo aparece en **Equipos** al primer POST.
## Pendientes / por verificar con un agente real
- Confirmar que el agente acepta la respuesta del handshake tal cual (si no, ajustar `ingest.js`).
- Capturar un JSON real (`glpi-agent --local=/tmp/inv --json`) y contrastar campos con
`normalizer.js` (hoy basado en el formato documentado del agente).
- Impresoras/red por SNMP (`netinventory`): solo se guarda lo básico + `extra_json`; falta una
vista propia cuando haya un caso real.
- Panel de impresoras con contador de páginas/tóner y export CSV: fase 2.