Descripción general
En v1.63.0, Integrity deja de ser una página propia (/integrity/) y se muda a pestaña 4 de Observatory (junto a Overview, CNS e ITSM). El cambio es de UX y arquitectura; el motor y la API de Integrity siguen intactos.
Contexto de la decisión
El flujo de trabajo de Integrity es:
- Integrity detecta un cambio (Plan updated / Real change / False alarm)
- CNS lo filtra (descarta ruido)
- ITSM abre un ticket de incidencia
- El técnico reconcilia el plano
Todos estos pasos viven en superficies vecinas del mismo módulo (Monitoring). El usuario (técnico en la “sala de control”) ve el mismo contexto para las tres herramientas. Por eso, agrupar todo en Observatory como pestañas hermanas reduce la fricción: el técnico no cambia de página. El botón “Integrity” de la cabecera desaparece.
Qué cambió
Cambios de UX
| Antes | Después |
|---|---|
| Integrity es botón en la barra superior | Integrity es pestaña 4 de Observatory |
/integrity/ es página propia con layout | /integrity/ es redirect a /monitoring/?tab=integrity |
| Ver Integrity requería dejar Observatory | Todo vive en una sola vista |
Cambios de código
racks/views.py — integrity_view():
- Antes: rendería
racks/integrity.htmlcon contexto{"can_edit": bool(org) and has_permission(...)} - Después: redirect a
/monitoring/?tab=integrity(los bookmarks vuelven automáticamente) - Gating: el middleware que bloquea
/integrity/sigue funcionando — una org sin módulo recibe 403 antes del redirect
monitoring/views.py — observatory_view():
- Añade contexto
integrity_can_edit = bool(org) and has_permission(request.user, "racks", "edit") - La pestaña se pinta en el template solo si se cumple esa condición (y el módulo está activado)
templates/monitoring/observatory.html:
- Añade una cuarta tab (pestana) a la barra de tabs:
<div class="tab-item" data-tab="integrity"> - La tab es module-gated: solo se pinta si
{% ifmodule "integrity" %} - El contenedor
id="integrity-root"vuelve a existir (antes estaba enracks/integrity.html) - Carga
integrity.jsyintegrity.cssen la misma página
templates/racks/integrity.html (removida):
- Archivo completamente eliminado
- Su markup completo (header, summary, queue, racks, undocumented) se mudó a
observatory.htmldentro del contenedor#integrity-root - Mismo contenido, otro parent
static/js/pages/integrity.js:
- Auto-guardado nuevo: si
#integrity-rootno existe (módulo Integrity desactivado en la org), el script no falla — solo verificaif (rootEl) - Se ejecuta desde Observatory, no desde su propia página
- Mismo
load()y mismosendVerdict()
static/js/pages/observatory.js:
- Añade soporte para
?tab=integrityen la URL - Nuevo branch:
else if (urlTab === 'integrity') { this.switchTab('integrity'); }
static/css/pages/integrity.css:
- Cambio de level de headings (porque ahora es una pestaña, no una página):
.integrity-header h1→.integrity-header h2(ahora es subtítulo de Observatory, no página propia).integrity-block h2→.integrity-block h3(secciones internas)
base.html (template global):
- Se elimina el botón “Integrity” de la barra superior (grupo de navegación modular)
Tests
tests/racks/test_integrity_api.py:
test_page_and_api_open_with_module(): verifica que GET/integrity/devuelva 302 (redirect) a/monitoring/?tab=integrity(no 200)test_observatory_renders_integrity_tab_with_module()(nuevo): verifica que/monitoring/contengadata-tab="integrity"eid="integrity-root"cuando la org tiene el módulotest_observatory_hides_integrity_tab_without_module()(nuevo): verifica que/monitoring/NO contenga esa pestaña sin el módulo
Fix de CI (config/settings/test.py)
Los 2 tests nuevos renderizan observatory.html, que incluye {% vite_asset %}. En local, el manifest se construye al hacer build de Vite. En CI, los shards de backend no compilan frontend, así que el manifest no existe y los tests rompían.
Solución: config/settings/test.py ahora configura django-vite con dev_mode=True — el template no lee manifest, emite la URL del dev server.
Arquitectura post-v1.63.0
/monitoring/ (GET)
├── observatory_view() — nueva lógica: añade integrity_can_edit
├── template: observatory.html
│ ├── tab: Overview
│ ├── tab: CNS
│ ├── tab: ITSM
│ └── tab: Integrity (module-gated con {% ifmodule "integrity" %})
│ ├── static/js/pages/integrity.js
│ ├── static/css/pages/integrity.css
│ └── fetches /api/racks/integrity/overview + /api/racks/integrity/ack
/integrity/ (GET)
├── integrity_view() — ahora solo redirect
└── 302 → /monitoring/?tab=integrity
/api/racks/integrity/overview (GET)
├── Sin cambios
└── racks.api.integrity.overview()
/api/racks/integrity/ack (POST)
├── Sin cambios
└── racks.api.integrity.ack_finding()
Backward compatibility
- URLs viejas:
/integrity/sigue funcionando (redirect 302) - Bookmarks: los bookmarks a
/integrity/siguen válidos (automáticamente redirigen) - Gating por módulo: intacto — una org sin “integrity” recibe 403 antes de llegar al redirect
- API:
/api/racks/integrity/*sin cambios - Traducciones: mismo msgid en ambas páginas —
.poespañol sigue siendo válido sin tocar
Impacto del usuario
- Si tienes módulo Integrity: la pestaña aparece automáticamente en Observatory;
/integrity/te redirige allí - Si NO tienes módulo Integrity: Observatory no muestra la pestaña;
/integrity/devuelve 403 como antes - Si tenías bookmark a
/integrity/: sigue funcionando (redirect) - Si tenías button de Integrity en la barra: desaparece; ahora es una pestaña dentro de Observatory
Véase también
- [[entity—racks—endpoint—integrity-overview-ack]] — APIs de Integrity: GET overview y POST ack
- [[entity—racks—endpoint—integrity-ack]] — Endpoint específico: registrar veredicto de reconciliación
- [[concept—saas—module-gating]] — mecanismo de gating por módulo que protege la pestaña
- [[entity—racks—service—integrity]] — motor interno que calcula fidelidad y detecta cambios
- [[entity—racks—service—integrity-itsm]] — puente que abre tickets ITSM desde la cola de reconciliación