Technical documentation
Modelo de datos
10.1 Entidades principales (PostgreSQL)
TENANT
├── id (uuid, PK)
├── name, slug, timezone
├── is_active, license_config
└── → USER (1:N)
└── → DATASOURCE (1:N)
└── → RESOURCE (1:N)
└── → INCIDENT (1:N)
USER
├── id (uuid, PK), tenant_id (FK)
├── email, hashed_password (bcrypt)
├── role → ROLE (FK)
└── is_active, mfa_config, timezone_preference
DATASOURCE
├── id (uuid, PK), tenant_id (FK)
├── name, type (zabbix|snmp|webhook|syslog)
├── config JSONB (url, credentials cifradas con Fernet)
└── is_active, last_sync
RESOURCE
├── id (uuid, PK), tenant_id (FK), datasource_id (FK)
├── name, host, type (server|network|vm|container)
├── status (monitored|unmonitored|ghost|purged)
├── groups JSONB, tags JSONB
└── ghost_since, created_at, updated_at
ALERT
├── id (uuid, PK), tenant_id (FK), resource_id (FK)
├── host, message, severity (disaster|high|average|warning|info)
├── status (active|resolved|suppressed)
└── tags JSONB, timestamp
INCIDENT
├── id (uuid, PK), tenant_id (FK)
├── consecutive_id (entero legible, ej. #42)
├── title, status (open|investigating|resolved|closed)
├── severity (critical|high|medium|low)
├── root_cause_score (float), root_cause_candidate_host_id
├── correlation_type (Regex|Temporal|Topology|AIOps)
├── grouped_alert_ids JSONB
├── ack_user, ack_date
├── summary (snapshot LLM)
└── created_at, resolved_at, updated_at
IAM
├── PERMISSION (id, name, description)
├── ROLE (id, name, tenant_id)
└── ROLE_PERMISSION_MAPPING (role_id, permission_id)
AUDIT_LOG
├── id (uuid, PK), tenant_id (FK), user_id (FK)
├── action, resource_type, resource_id
└── timestamp, ip_address, details JSONB
10.2 Entidades EOE (schema separado)
FLOW
├── id, tenant_id, name, version
├── definition JSONB (nodos ReactFlow + edges)
└── is_active, created_at
EXECUTION
├── id, flow_id, tenant_id
├── status (pending|running|completed|failed)
├── trigger_data JSONB, result JSONB
└── started_at, completed_at
TRE_RULE
├── id, tenant_id, name, priority
├── trigger JSONB (tipo: alert|incident|anomaly|schedule)
├── conditions JSONB (expresiones CEL)
└── actions JSONB (conector + params)
APPROVAL
├── id, execution_id, tenant_id
├── status (pending|approved|rejected|expired)
└── approver_user_id, decided_at
10.3 Almacenamiento en OpenSearch
Índice evaiops-events-{tenant_id}-{YYYY.MM}:
{
"id": "uuid",
"tenant_id": "uuid",
"timestamp": "ISO8601",
"source_type": "syslog|snmptrap|webhook",
"host": "hostname",
"severity": "critical|high|medium|low|info",
"message": "raw message text",
"tags": {},
"normalized": true,
"collector_id": "uuid"
}
10.4 Grafos en Neo4j
Nodos: Resource, Service, Zone, DataCenter
Aristas: CONNECTED_TO, DEPENDS_ON, HOSTED_IN, PART_OF
El Topology Inference Engine construye el grafo usando 6 dimensiones:
- Hostgroups compartidos
- Prefijo de nombre de host
- Patrones de alerta simultánea
- Subnet IP compartida
- Tags de datasource
- Historial de co-incidencia
10.5 Migraciones
Las migraciones de esquema se gestionan con Alembic:
alembic upgrade head
alembic current
alembic revision --autogenerate -m "descripcion_corta"
alembic downgrade -1 && alembic upgrade head
Migración actual: 0023_correlation_rule_summary (Junio 2026).
Ver historial: backend/alembic/versions/
