Incidents Module

Complete

Overview

The Incidents module manages the full lifecycle of security incidents in the ThreatOps SOCaaS platform. When alerts are escalated -- either by analysts or by the autonomous SOC engine -- they become incidents that require coordinated investigation, containment, and resolution.

This module tracks MITRE ATT&CK tactics and techniques, affected assets, indicators of compromise (IOCs), assigned analysts, and resolution timelines. It supports the NIST incident response lifecycle: detection, investigation, containment, eradication, resolution, and closure.

What Was Proposed

What's Built

Incident CRUD (create, read, update)✓ Complete
6-stage lifecycle (new through closed)✓ Complete
MITRE ATT&CK tactic/technique mapping✓ Complete
Multi-SIEM source tracking✓ Complete
Analyst assignment✓ Complete
IOC and affected asset fields✓ Complete
Statistics endpoint✓ Complete
List page with severity/status/tactic filters✓ Complete
Detail page with response actions✓ Complete
Auto-set resolved_at/closed_at timestamps✓ Complete
Demo data fallback when DB unavailable✓ Complete

Architecture

API Router

File: app/routers/incidents.py — Prefix: /api/v1/incidents

GET    /api/v1/incidents/                 # List incidents (filters: severity, status, mitre_tactic, source_siem)
POST   /api/v1/incidents/                 # Create a new incident
GET    /api/v1/incidents/stats            # Statistics (total, open, critical counts)
GET    /api/v1/incidents/{incident_id}    # Get incident detail
PATCH  /api/v1/incidents/{incident_id}    # Update incident (auto-sets resolved_at/closed_at on status change)

How It Connects

The incidents router is a standard FastAPI CRUD router scoped by request.state.tenant_id. Every query filters by tenant. When an alert is escalated (via the alerts bulk action), it can be linked to an incident via the Alert.incident_id foreign key.

The PATCH endpoint intelligently handles lifecycle transitions: setting resolved_at when status becomes "resolved" and closed_at when status becomes "closed", but only if those timestamps are not already set.

When the database is unavailable, the router returns 8 realistic demo incidents covering ransomware, data exfiltration, BEC, supply chain, insider threat, C2, credential theft, and zero-day scenarios.

Frontend Pages

List View (src/app/incidents/page.tsx): Fetches from GET /api/v1/incidents/. Shows a filterable table with severity, status, and MITRE tactic dropdowns. Each incident title links to the detail page.

Detail View (src/app/incidents/[id]/page.tsx): Fetches from GET /api/v1/incidents/{id}. Shows a 2/3 + 1/3 column layout with incident details, response actions, MITRE ATT&CK info, and IOCs.

Routing

LayerPath
/incidentsFrontend list page (Next.js App Router)
/incidents/[id]Frontend detail page (dynamic route)
/api/v1/incidentsAPI prefix (FastAPI router)

Prerequisites

Data Model

Model: app/models/incident.py — Table: incidents (extends TenantScopedBase)

FieldTypeDescription
idString(36) PKUUID primary key
tenant_idString(36) FKTenant scope
titleString(500)Incident title (required)
descriptionTextDetailed description
severityEnum(IncidentSeverity)critical / high / medium / low / informational
statusEnum(IncidentStatus)new / investigating / containment / eradication / resolved / closed
mitre_tacticString(100)MITRE ATT&CK tactic name
mitre_techniqueString(20)MITRE technique ID (e.g., T1059.001)
source_siemString(50)Source SIEM platform
assigned_toString(36) FKAssigned analyst (FK to users.id)
resolutionTextResolution description
affected_assetsJSONList of affected systems/assets
iocsJSONIndicators of compromise
acknowledged_atDateTimeWhen an analyst acknowledged
resolved_atDateTimeResolution timestamp (auto-set)
closed_atDateTimeClosure timestamp (auto-set)
created_atDateTimeCreation timestamp
updated_atDateTimeLast update timestamp

UI Layout

List Page (/incidents)

Detail Page (/incidents/[id])