{"slug": "incident-war-room-an-incident-response-tool-where-the-approval-gate-and-the-ai-t", "title": "Incident War Room: an incident-response tool where the approval gate and the AI can't be faked out", "summary": "A developer built Incident War Room, a real-time incident-response app for on-call teams using Next.js 16 and Sanity as the backend, with an escalation approval gate enforced in a Server Action rather than the UI so a single responder cannot push a SEV1 through alone. The project, created for the dev.to × Sanity \"Path Two\" hackathon with Claude Code, uses Sanity Workflows and the App SDK for live updates and includes an LLM-generated root-cause feature that is instructed to answer \"unknown\" rather than guess.", "body_md": "*This is a submission for the [Sanity Challenge, Path Two: Vibe-Code Something Strange](https://dev.to/challenges/sanity-2026-09-16)*\n\n**Incident War Room** is an incident-response app for on-call teams. When\n\nsomething breaks at 2 AM, everything about the incident lives on one page:\n\nIt's built with Next.js 16 (App Router) and Sanity as the whole backend.\n\n**Live app:** [https://incident-war-room-nine.vercel.app](https://incident-war-room-nine.vercel.app)\n\n**Try the gate yourself** (all passwords are `demo1234`):\n\n`alice@example.com` (prefilled), open the sample incident and click `dana@example.com`, open the same incident and approve. It flips to SEV1 / escalated and a status page entry appears.`bob@example.com` (an engineer): you can't approve at all.\nA real-time incident-management app built for the dev.to × Sanity\n[\"Path Two\" hackathon](https://dev.to/challenges/sanity-2026-09-16). Next.js\n16 on the front end, Sanity as the backend — using **Sanity Workflows** and\nthe **Sanity App SDK** for real functionality, not as checkbox features.\n\n**Live demo:** [https://incident-war-room-nine.vercel.app](https://incident-war-room-nine.vercel.app)\n**Sanity project:** `am9ihg1w` / dataset `production`\n**Login:** seeded test accounts in `docs/testing-credentials.md`\n\n`listen()` API, no polling.`escalationApproval` request needing sign-off from `src/app/incidents/[id]/actions.ts`), not just hidden in the UI: the\napprover is always the logged-in responder, must be an on-call lead, and\ncan't approve twice, so one person can't push a SEV1 through alone.`pending → approved/rejected`\nas a Kanban board in Studio (`sanity-plugin-workflow`). Once…\nThe schema is documented in `docs/schema.md` and the design in\n\n`docs/architecture.md`.\n\nI built the whole thing with **Claude Code**. Before any code, I had it\n\nwrite planning docs (`docs/overview.md`, `docs/architecture.md`,\n\n`docs/schema.md`) so each later prompt had a fixed target: a schema, the\n\nrules for the escalation gate, and what \"real\" use of Workflows and the\n\nApp SDK meant. My rule for both bonus features was that a judge should be\n\nable to try to break them.\n\n**Where the model got stuck, and how I corrected it:**\n\n`AGENTS.md` that\ntells the agent to read the docs bundled in `node_modules/next` before\nwriting code, because APIs changed. That's how it got things like\n`middleware` being renamed to `proxy` right, instead of writing\nlast year's Next.js from memory.`status: \"approved\"`\ndirectly. The Kanban board stayed, to track where each escalation stands,\nbut the real rule moved into a Server Action (`approveEscalation`) that\nis the only code path allowed to finish the transition.`runbook` schema existed\nin Studio, but nothing in the app read it, and the page title was still\n\"Create Next App\". Asking the agent \"what's unused or unfinished?\" found\nmore than asking it to \"add a feature\".`ifRevisionId` so two approvals at the same moment can't both count\nas \"the first\".`author` as a bare reference and showed \"Unknown responder\"; events the\nserver added (escalation, resolution) didn't show up because the client\nkept its first list; and the page showed two different clocks (UTC from\nthe server on Vercel, local time from the browser). All fixed, all found\nby driving the live site with Playwright, not by reading code.\n**Reaching past the Studio:**\n\n`pending → approved / rejected`), shown as a Kanban board in Studio.\nOnce the Server Action counts two approvals, it flips the incident to\nSEV1 / escalated, creates a `statusPageEntry`, adds a timeline event and\ncan POST to an external status page webhook.`@sanity/sdk-react`. One GROQ query gives live mean time to resolution,\nopen incidents by severity and pending approvals. It started read-only,\nwhich felt like decoration, so it can now approve escalations too, using\nthe `openai/gpt-oss-120b`) for a root cause and up\nto three action items, told to say \"unknown\" instead of guessing. A\ncustom Studio input (`RootCauseInput.tsx`) adds a \"Regenerate with AI\"\nbutton, so an editor can ask for another draft at any time.`am9ihg1w`\n`production`\nSchema types: `incident`, `timelineEvent`, `responder`,\n\n`escalationApproval`, `statusPageEntry`, `postmortem`, `runbook`.\n\nTwo modeling decisions I'd defend:\n\n`timelineEvent` documents that reference the\nincident, two posts in the same second never conflict, and the app\nsubscribes to them with `incident._ref`.` postmortem.timelineSnapshot` as\nplain objects, so later edits to the live timeline can't quietly change\nwhat the postmortem says happened.", "url": "https://wpnews.pro/news/incident-war-room-an-incident-response-tool-where-the-approval-gate-and-the-ai-t", "canonical_source": "https://dev.to/anishisbusy/incident-war-room-an-incident-response-tool-where-the-approval-gate-and-the-ai-cant-be-faked-out-5ee0", "published_at": "2026-09-26 18:05:38+00:00", "updated_at": "2026-09-26 18:31:15.061066+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "large-language-models"], "entities": ["Sanity", "Next.js", "Claude Code", "Vercel", "dev.to", "Sanity App SDK", "Playwright", "openai/gpt-oss-120b"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/incident-war-room-an-incident-response-tool-where-the-approval-gate-and-the-ai-t", "markdown": "https://wpnews.pro/news/incident-war-room-an-incident-response-tool-where-the-approval-gate-and-the-ai-t.md", "text": "https://wpnews.pro/news/incident-war-room-an-incident-response-tool-where-the-approval-gate-and-the-ai-t.txt", "jsonld": "https://wpnews.pro/news/incident-war-room-an-incident-response-tool-where-the-approval-gate-and-the-ai-t.jsonld"}}