Volver a la wiki

Barra de Integridad F3: Veredicto "Cambio Real" abre incidencia CNS/ITSM

Barra de Integridad F3: Veredicto “Cambio Real” abre incidencia CNS/ITSM

Versión: 1.61.0 (2026-07-17)
Ámbito: Racks · Monitoring (CNS/ITSM)
Impacto usuario: Ninguno fuera de org 1 (módulo solo activo en org 1, calibración #202)

Resumen ejecutivo

Cuando un usuario de la Barra de Integridad (radar de sincronización planos ↔ red) emite un veredicto “Cambio real” en la cola de reconciliación, el sistema ahora abre automáticamente una incidencia AIInsight en el CNS/ITSM existente con:

Al reconocer (acknowledge) la incidencia en Observatory, un hook des-silencia el IntegrityAck vinculado → el próximo probe re-verifica el sujeto contra el plano:

Límite honesto v1: Solo hay incidencia si el sujeto tiene target de monitorización (FK obligatoria en AIInsight que CNS derreferencia por todas partes). Si no lo tiene, la API responde {queued: false, reason: "subject has no monitoring target"} y la página lo muestra.

Arquitectura y flujo

1. Veredicto “Real change” en el endpoint /api/racks/integrity/ack

POST /api/racks/integrity/ack
{
  "kind": "matched_stale" | "undocumented",
  "verdict": "real_change",
  "device_id" | "profile_id": <id>,
}

↓ (200 OK)
{
  "ok": true,
  "ack_id": <id>,
  "muted_until": "ISO8601",
  "gate": {...},
  "itsm": {
    "queued": true | false,
    "reason"?: "subject has no monitoring target"
  }
}

Nota: El campo itsm es None para otros veredictos (false_alarm, plan_updated).

2. Puente: racks/services/integrity_itsm.py

Responsabilidades:

3. Tarea Huey: racks/tasks.open_integrity_drift_ticket(ack_id)

@db_task()
def open_integrity_drift_ticket(ack_id):
    # Best-effort: si falla (rate limit, proveedor caído), el aviso sigue en cola.
    integrity_itsm.open_drift_ticket(ack_id)

Rationale: La llamada al proveedor de IA y recomputo de contexto pueden tomar segundos. No caben en el request del click del usuario (que debe ser <100ms). Por eso se encola en background con Huey — el campo itsm en la respuesta dice {"queued": true} siempre que el target exista.

4. Servicio: monitoring/services/insight_service.create_drift_insight()

Nueva función especializada para tickets documentales (drift):

async def create_drift_insight(
    *,
    target: MonitoringTarget,
    anomaly_description: str,
    evidence: dict,
    subject_label: str,
    provider_name: str = "static",
) -> AIInsight:
    """Ticket ITSM de drift documental sin comandos ni maintenance-window."""

Diferencias vs. create_insight() operativo:

Aspectocreate_insight()create_drift_insight()
Ventana mantenimiento✅ Sí (anomalía operativa)❌ No (no afecta al equipo)
Comandos✅ Propuestos por IA❌ Siempre [] (nunca Apply)
is_actionable✅ Si hay comandos❌ Siempre False
TTL (expires_at)4 horas (por defecto)14 días (DRIFT_TICKET_TTL_DAYS)
RiskLevelHIGH/MEDIUM según IALOW (siempre)
CategoríaCONNECTIVITY/PERFORMANCE/etcOTHER

Reutilización sin duplicación: Se extrajo _analyze_with_fallback() de create_insight() para que ambas usen la misma lógica de IA + fallback a reglas estáticas.

5. Hook en acknowledge_insight() (monitoring/services/insight_service.py)

# Al reconocer una incidencia (usuario en Observatory):
def acknowledge_insight(insight: AIInsight, user=None, notes: str = ""):
    insight.status = AIInsight.Status.ACKNOWLEDGED
    insight.acknowledged_at = timezone.now()
    insight.acknowledged_by = user
    insight.save()
    
    # Barra de Integridad F3 — des-silenciar acks vinculados
    unmuted = IntegrityAck.objects.filter(
        insight=insight, 
        muted_until__gt=now
    ).update(muted_until=now)

Efecto: El próximo probe de integridad re-verifica el sujeto sin esperar a la caducidad original del silenciamiento (típicamente 30 días).

6. Nuevas migraciones

Migración racks/migrations/0018_integrityack_insight.py:

AddField(
    model_name="integrityack",
    name="insight",
    field=models.ForeignKey(
        "monitoring.AIInsight",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="integrity_acks",
    ),
)

FK nullable → permite acks sin incidencia (p.ej. sujeto sin target).

Internacionalización (i18n)

Completada: 28 strings JS + 11 de plantilla al catálogo (djangojs.po/django.po).

Testing

8 tests nuevos en tests/racks/test_integrity_itsm.py (proveedor IA: “static” offline):

139 tests de regresión CNS verdes en Docker.

Observaciones y deuda

Véase también

Subir