Incident War Room: un gestor de incidentes con la aprobación de SEV1 en el servidor
Una app de código abierto para equipos de guardia que exige dos firmas de responsables distintos para elevar un incidente a SEV1, con la regla aplicada en el servidor y no en la interfaz.

Un desarrollador ha publicado Incident War Room, una aplicación de gestión de incidentes para equipos de guardia, con el código en GitHub y una demo abierta al público. Lo interesante no es la app en sí, sino las dos cosas que su autor tuvo que arreglar por el camino: que la aprobación de un SEV1 no se pueda falsear desde el navegador y que dos aprobaciones simultáneas no cuenten como una sola.
La app se apoya en Next.js 16 con App Router y usa Sanity como backend entero. La línea de tiempo del incidente se actualiza en vivo mediante la API listen(), sin sondeo. Cuando alguien pulsa para elevar un incidente a SEV1, se abre una solicitud de aprobación que necesita el visto bueno de dos responsables de guardia diferentes antes de que la severidad cambie. Además genera una entrada en la página de estado, muestra el runbook correspondiente a la severidad y, al resolver, congela la línea temporal y pide a un LLM un borrador de postmortem con causa raíz y acciones.
El plugin no era una puerta
El plan inicial era usar sanity-plugin-workflow como barrera: sus transiciones mueven la solicitud de pendiente a aprobada o rechazada y se ven como un tablero Kanban en Studio. El problema es que esas transiciones solo se ejecutan en la interfaz de Studio, así que cualquiera con un token de escritura podía poner el estado en "approved" directamente. El tablero se quedó para visualizar dónde está cada escalado, pero la regla real se movió a una Server Action que es el único camino de código autorizado a cerrar la transición.
La primera versión de esa puerta también se podía burlar. El identificador del aprobador salía de un campo oculto del formulario y cada responsable tenía su propio botón, de modo que una sola persona podía aprobar en nombre de todos y empujar el SEV1 ella sola. Ahora el aprobador es quien dice la sesión firmada, tiene que ser responsable de guardia y no puede aprobar dos veces; la escritura usa ifRevisionId, de forma que dos aprobaciones en el mismo instante no se cuentan ambas como la primera.
Hay un detalle que le va a interesar a quien tenga Next.js 16 en el radar: el autor mantiene un AGENTS.md que obliga al agente a leer la documentación incluida en node_modules/next antes de escribir código, porque las APIs han cambiado. Así acertó con renombrados como el de middleware a proxy en lugar de escribir el Next.js del año pasado de memoria.
También hay trampas que solo aparecen al hacer clic. listen() ignora las proyecciones GROQ, así que los mensajes en vivo llegaban con el autor como referencia pelada y se mostraban como "Unknown responder", y el cliente descartaba los eventos que añadía el servidor.
El repositorio lleva documentación de esquema y arquitectura, y hay cuentas de prueba sembradas para reproducir el flujo de aprobación. Merece la pena por el patrón de autorización, no por la app: cualquier función que dependa de dos personas para autorizar algo debería vivir en el servidor y comprobar contra la sesión, y eso es exactamente lo que aquí se corrigió.

