Overview — what it does
Security ▸ Problem Resolution manages security incident and breach response as a single case board with a five-stage pipeline:
open → investigating → cause_identified → resolved → closed
Every case carries a 500-report structure (direct cause / root cause / resolution / preventive action) and an auditable timeline. This screen mirrors the Service ▸ Problem Resolution controller: it shares the same infr_incident table but filters on area='security' to keep security cases separate from service incidents.
Cases reach this board through two tracks:
- Manual entry — an operator creates the case. Selectable sources:
manual·agency·quarantine. - Diagnostics promotion —
fail + critfindings from Security Diagnostics are automatically promoted into cases (source=detection). This is a system-only source that operators cannot pick by hand.
This console does not touch remote crontab or firewalls directly. It is a workflow tool that records and tracks the human response process. Actual block/quarantine actions live in Blocklist and Auto-block.
When to use
- To promote a confirmed breach suspicion from IDS/AI detection (Threats, Detections · JA3) into a formal case with an investigation and resolution trail.
- To track agency cooperation requests or breach reports (CERT, law enforcement).
- To manage a host from quarantine through recovery and re-deployment.
- To receive hardening/rootkit risks flagged
fail+critby Security Diagnostics as auto-created cases and assign follow-up. - To compute MTTR and cumulative downtime after the fact, and document direct/root causes and preventive actions.
Layout
KPI strip
| KPI | Definition |
|---|---|
| total | Total cases where area='security' |
| active | Sum of open + investigating + cause_identified |
| resolved | Sum of resolved + closed |
| MTTR | Mean minutes for cases having both occurred_at and resolved_at |
| downtime | Sum of downtime_min across all cases |
| uptime target | OpsPolicy::slaDefaults()['uptime_target'] |
Case board
Cases are sorted by:
- Status rank —
open→investigating→cause_identified→resolved→closed - Severity rank —
crit→warn→info - Newest first —
iddescending
Each card shows the title, severity, status, source badge, linked project/service, occurrence time, downtime, and event count.
Detail modal
Opening a case splits into two panes:
- Report — summary, direct cause, root cause, resolution, preventive-action fields.
- Timeline —
infr_incident_eventhistory (created, note, status change, …) in chronological order.
Clicking the status pipeline at the top opens a step-transition dialog that shows "what to do at this stage" guidance and lets you update that stage's report fields inline.
How to use
Create a case (manual)
- Click [Add case] at the top.
- Enter title (required), severity, and source (
manual/agency/quarantine). - Optionally set project, service, URL, occurrence time, impact, downtime (minutes).
- [Save] — a new case is created with
status=open,area=security,detected_at=now(), and acreatedevent is written to the timeline.
detectionis not offered in the source list — it is a system-only source that Security Diagnostics generates automatically.
Status transitions (pipeline)
Click the target status in the detail modal's pipeline. Recommended work per stage:
| Stage | What to do at this stage |
|---|---|
| open | Reset to intake (before analysis) |
| investigating | Confirm symptoms, scope impact, write the summary |
| cause_identified | Determine and record the direct cause + background (root) cause |
| resolved | Record the recovery method + preventive action |
| closed | Verify actions/prevention are applied, then close the case |
Server-side transition rules:
- Moving to
resolvedfillsresolved_atwithnow()if it was empty. - Moving to
closeduses the closed-at value from the dialog if provided; otherwise it defaults tonow()when no value exists. - When the status actually changes, a
status_change(from→to) event is written to the timeline; supplying a note also adds anoteevent.
Collaboration notes
Adding a note in the detail modal records a kind=note event on the timeline. There is no separate note table — notes are consolidated into infr_incident_event.
Delete
Deleting a case also deletes its infr_incident_event rows and is written to the audit log. (The original diagnostics scan behind a promoted case is independent and is not deleted.)
Auto-resolution of promoted cases
When Security Diagnostics ingests a probe result, DiagnosticsService::reconcileCases() reconciles cases per host:
- A
fail + critfinding → upserts an open case keyed byfingerprint(a recurrence incrementsoccurrence_count). - When a later scan passes / drops that item → the open case is auto-resolved (
status=resolved,resolved_at,resolution=auto-resolved text) with astatus_changetimeline event.
Auto-resolution only fires when the diagnostic check passes again. Manually created cases (
manual/agency/quarantine) are never auto-resolved — an operator must transition them through the pipeline.
Data sources
Tables
| Table | Role |
|---|---|
infr_incident |
Case body (filtered area='security'). Status, severity, source, 500-report fields, occurred/resolved/closed times, fingerprint, occurrence_count |
infr_incident_event |
Case timeline (created, note, status change, …) |
infr_project |
Project list for linking |
infr_service |
Service list for linking |
Enumerations
STATUSES = [open, investigating, cause_identified, resolved, closed]
SEVERITIES = [info, warn, crit]
SOURCES = [manual, pulse, alert, agency, quarantine, detection] # all
manual-selectable sources = [manual, agency, quarantine]
OPEN_STATUSES (dedup targets) = [open, investigating, cause_identified]
AREAS = [service, security] # shared-table split axis
Report fields (500 structure)
| Field | Meaning |
|---|---|
summary |
Symptom / impact summary |
direct_cause |
Immediate cause (e.g. MySQL Too many connections) |
root_cause |
Background / root cause (e.g. script connection leak) |
resolution |
Recovery applied during the incident |
action_taken |
Preventive action for the future |
downtime_min |
Downtime (minutes) — source of the downtime KPI |
impact |
Affected scope |
API endpoints
| Method · path | Purpose |
|---|---|
GET /security/resolution |
Initial board render |
GET /security/resolution/live |
Polling refresh (cases, KPI, timestamp) |
POST /security/resolution/save |
Create / update a case |
POST /security/resolution/transition |
Status transition (+ optional note / report update) |
POST /security/resolution/note |
Add a collaboration note |
POST /security/resolution/delete |
Delete a case |
Access
- Read: the whole Security group is protected by the
infr.level:2middleware. Only level 2 and above (staff=5 · admin=10) can enter; demo (1) is blocked. - Write (save/transition/note/delete): the controller's
canWrite()re-checks the sessioninfr_user_level >= 2. Below that returns403(resolution.err.forbidden). - Audit: every write is recorded in
infr_audit_log—sec.incident_create·sec.incident_update·sec.incident_transition·sec.incident_delete. Transitions store{from,to}, saves store{title,severity}in the meta. See Audit log.
Troubleshooting & FAQ
Q. A case I see on the Service board is missing here.
Both boards share the same infr_incident table but split on area. This screen shows area='security' only. Find service incidents in Service ▸ Problem Resolution.
Q. I can't create a case with the detection source.
Expected. detection is a system-only source that Security Diagnostics auto-creates from fail+crit findings. Manual entry offers only manual, agency, quarantine.
Q. An auto-promoted case flipped itself to resolved.
When the underlying diagnostic check passes on a later scan, reconcileCases() auto-resolves the open case: resolution is filled with the auto-resolved text and a status-change event is added.
Q. MTTR is blank.
MTTR is only computed for cases that have both occurred_at and resolved_at. Cases without an occurrence time, or not yet resolved, are excluded.
Q. Can I set a past closed-at time?
Yes. Enter a value in the closed-at field of the close dialog (same interface as occurrence time) and it is saved verbatim. Leave it empty and the server fills now() only if no value exists yet.
Q. Does deleting a case remove its diagnostics scan? No. A promoted case and its source diagnostics scan are independent. Deleting a case removes only its linked timeline events.
Related
- Security Diagnostics — the source that auto-promotes
fail+critfindings into this board. - Service Problem Resolution — the service (
area='service') mirror of the same workflow. - Security Overview — the threat→detection→response defense-funnel narrative.
- Threats · Detections · JA3 — sources of breach candidates to promote into cases.
- Audit log — the persistent record of case write actions.
