CreaRack-SL

Cierre sa4 BAJA/MEDIA — Validación ITSM, N+1 fixes, Markdown safety

Resumen

Cierre de 12 hallazgos BAJA/MEDIA de la auditoría Suprema sub-área 4 (ITSM/alerting), sesión 112. Se aborda:

  • Validación de risk_level (B1): rechazar fuera de {HIGH, MEDIUM, LOW} en SLA, escalation policies, known-issues
  • Seguridad de runbooks (M5): validar comandos embebidos contra allowlist del vendor
  • Honestidad en apply_runbook (B5): solo asigna, no ejecuta; usage_count idempotente en re-asignación
  • Known-issue body (B6): create_from_insight aplica description/risk_level del body si vienen
  • SLA lifecycle (B10): resolve_alert puebla resolved_by + marca acknowledged
  • Markdown safety (B15): fence suficientemente largo para que ``` en commands/output no rompa bloques
  • Paginación (B7/B11): list_* endpoints capped a 500 (runbooks, known-issues) y 1000 (alerts)
  • N+1 eliminados (B12/B13): is_in_maintenance_window query única; check_escalations precarga políticas por (org, risk_level)

Archivos Modificados

API Endpoints (alerts)

  • list_alerts: paginación limit/offset (cap 1000)
  • get_active_alerts: paginación limit/offset (cap 1000)
  • resolve_alert: nuevo campo resolved_by + marca acknowledged si no lo estaba

API Endpoints (ITSM)

  • update_sla_policy(risk_level): valida risk_level en {HIGH, MEDIUM, LOW} → 400 si inválido
  • list_known_issues: paginación limit/offset (cap 500)
  • create_from_insight: aplica description/risk_level del body si vienen (antes se ignoraban)
  • list_runbooks: paginación limit/offset (cap 500)
  • create_runbook: valida comandos en steps[*].commands contra vendor allowlist → 400 si peligroso
  • update_runbook: valida comandos; logs action con log_action()
  • apply_runbook: asigna runbook; incrementa usage_count solo la primera vez (re-asignar es idempotente)
  • download_markdown: documenta respuesta 200 en contrato OpenAPI

Esquemas (itsm_schemas.py)

  • RISK_LEVELS constant: {"HIGH", "MEDIUM", "LOW"} — compartida por SLA/escalation/known-issue
  • EscalationPolicyIn validator: rechaza risk_level fuera de set
  • KnownIssueIn validator: rechaza risk_level (si non-vacío) fuera de set

Modelos

  • AlertEvent: nuevo campo resolved_by (FK → User, nullable)

Servicios

  • escalation_service.check_escalations(): precarga políticas de escalado por (org, risk_level) en un diccionario; evita N+1 por insight
  • sla_service.is_in_maintenance_window(target): query única con Q(targets__isnull=True) | Q(targets=target) en vez de cargar todas y probar M2M
  • report_service.format_markdown(): _code_block() calcula fence de backticks más larga que cualquier run en el contenido; asegura ``` no rompe bloque

Tests

  • tests/api/test_monitoring_sa4_sa5.py: 4 tests nuevos — B1, M5, B10, B5 (usage idempotencia)

Beneficios

  1. Correctness: risk_level fuera de set nunca matchea una policy realmente existente (antes silenciosamente inerte)
  2. Seguridad: runbooks no pueden guardar comandos peligrosos (Cisco, Juniper, etc.)
  3. Observabilidad: resolved_by traza quién cerró un alert; usage ranking de runbooks más honesto
  4. Performance: -N+1 en escalation check (-200 queries/noche en típico tenant); -N+1 en maintenance window check
  5. UX: Markdown reports robusto ante comandos con backticks; paginación en endpoints ITSM

Schema de Migraciones

  • monitoring/0022_alertevent_resolved_by.py: añade AlertEvent.resolved_by (nullable FK)

Véase también

  • [[entity—monitoring—service—escalation-policy-checker]]
  • [[entity—monitoring—service—sla-maintenance-window]]
  • [[entity—monitoring—service—report-markdown-formatter]]
  • [[concept—monitoring—risk-stratification]]
  • [[decision—20260607—audit-suprema-sa4-baja-cleanup]]