---
module: incident.incident-management
title: Incident Management
tab: Internal
order: 20
audience: internal
---

> Ops/support/admin view for the Incident Management screen (`IncidentList.svelte`). Served by **hiveops-incident** (port 8080, NGINX `/api/incident/`). All facts below grounded in source as of 2026-07-01.

## Who can do what

Read/list is open to any authenticated user. **Every mutating action requires `hasAnyRole('MSP_ADMIN','BCOS_ADMIN')`** (`@PreAuthorize` on `IncidentManagementController`):

| Action | Endpoint | Role gate |
|--------|----------|-----------|
| Assign / reassign / unassign | `POST /api/incident-management/{id}/assign` · `/reassign` · `/unassign` | admin |
| Workflow transition (Start/Resolve/Close/Reopen/Park) | `POST /api/incident-management/{id}/transition` | admin |
| Add note | `POST /api/incident-management/{id}/notes` | admin |
| Bulk close | `POST /api/incident-management/bulk/update` | admin |
| Link / unlink / group | `POST /api/incident-management/{id}/link` · `DELETE .../link/{linkedId}` · `POST .../group` | admin |
| Create incident (manual) | `POST /api/incident-management` or `POST /api/incidents` | admin |

If an admin reports "buttons do nothing / 403 on save," first confirm their JWT actually carries `MSP_ADMIN` or `BCOS_ADMIN` — a plain customer role can load the list but cannot transition or assign.

## First things to check when it misbehaves

1. **List empty / won't load** — the grid calls `GET /api/incidents/paginated`. Check the incident service is up: `curl http://localhost:8080/actuator/health` on the services VM. A 401/403 through NGINX usually means a missing/expired JWT, not a data problem.
2. **"No new incidents appearing for a device"** — the device may be **parked**. Any incident in `PARKED` status silences that device: `IncidentAutoCreationService.isDeviceParked()` suppresses all auto-creation (device events, log-errors, AGENT_OFFLINE) until the device is un-parked (issue #219). This is intended, not a bug — un-park the incident to resume auto-creation.
3. **Auto-created incidents not arriving at all** — auto-creation is driven by Kafka, not by the UI. Incidents are created by consumers of `hiveops.device.events` (`DeviceEventConsumer`) and `hiveops.aria.threats` (`AriaThreatEventConsumer`). If none are appearing fleet-wide, check Kafka connectivity (`KAFKA_BOOTSTRAP_SERVERS`) and consumer group lag for `hiveops-incident-device-sync` / `hiveops-incident-aria`.
4. **Wrong institution / stale device name on a row** — the row's device metadata comes from the `device_summary` mirror, fed by `hiveops.device.events` from **hiveops-devices**. There is no reconciler; a stale mirror means devices didn't publish. Fix at the source (devices), not here.
5. **Can't close an incident** — two guards:
   - The incident has **unfixed linked children** — `assertNoUnfixedChildren()` blocks closing a primary while linked child incidents remain unfixed.
   - **Possible Fraud** incidents require a note before closing — this is enforced **in the frontend** (`fraud-close-modal` in `IncidentList.svelte`), so it only applies via the UI, not direct API calls.
6. **Transition rejected (400)** — the target status must be a valid edge in the workflow (`workflowStateService.getTransition(from, to)`) and, if the transition `requiresAssignment`, the incident must already have an assignee. Assign first, then Start/Resolve.

## Common failure modes + fixes

| Symptom | Likely cause | Fix |
|---------|-------------|-----|
| 403 on assign/transition/note | JWT lacks `MSP_ADMIN`/`BCOS_ADMIN` | issue a token with the right role |
| New tickets not raised for one device | device is parked (#219) | un-park its `PARKED` incident |
| No incidents fleet-wide | Kafka down / consumer lag | check `KAFKA_BOOTSTRAP_SERVERS`, consumer groups |
| Stale device name/institution on row | `device_summary` mirror stale | fix in hiveops-devices (source of truth) |
| Close button blocked | unfixed linked children or fraud-note missing | fix children first / add note in UI |
| Service can't reach DB | `DB_URL` misconfigured | it's a **single full JDBC URL** (`DB_URL`), not split host/port/name; default points at a stale `hiveops_incident` DB and MUST be overridden to `hiveiq_incident` |

## Notes for support

- Real-time list updates use a STOMP WebSocket topic `/topic/incidents/status-changed`; the "Auto-refresh" toggle also re-polls `/api/incidents/paginated`. If a user sees stale data, have them refresh — polling is the reliable path.
- Agents never write here directly. All agent journal/heartbeat traffic goes through **hiveops-agent-proxy** → incident `/api/internal/**` (secured by `X-Internal-Secret`). A gap in incoming events is an agent-proxy / agent problem, not an incident-UI problem.
- Adoons (AI) rule suggestions surface via `adoons.rule-suggestion.*` topics and separate rule screens — not part of this list view.
