Overview

The IR Retainer module provides a complete incident response management platform for SOCaaS providers. It tracks retainer contracts (Platinum/Gold/Silver tiers), manages individual engagement lifecycles from activation through closure, maintains forensic evidence chain-of-custody, and supports structured stakeholder communications. Post-incident reviews capture lessons learned and generate action items for continuous improvement.

Why This Module Is Needed

  • Managed security providers must track retainer hour consumption, SLA compliance, and contract timelines across multiple clients.
  • Incident response engagements follow a strict lifecycle (activated → triaging → containing → eradicating → recovering → closed) that requires structured tracking.
  • Regulatory and legal requirements demand forensic evidence chain-of-custody documentation.
  • Stakeholder communication during an active incident must be timely, consistent, and auditable.
  • Post-incident reviews (PIRs) are critical for root cause analysis and preventing recurrence.

What Was Proposed

  • Retainer contract management with tiered SLAs (Platinum: 30-min response / 500 hours, Gold: 60-min / 250 hours, Silver: 120-min / 100 hours).
  • Full engagement lifecycle with 6 phases: activated, triaging, containing, eradicating, recovering, closed.
  • Chronological timeline with typed entries (action, finding, decision, note) and phase tagging.
  • Digital evidence catalog with SHA-256 hashes and chain-of-custody tracking.
  • Stakeholder communication system with templates for initial notification, status updates, executive briefs, containment achieved, engagement closure, and war room standups.
  • Post-incident review (PIR) with root cause analysis, impact assessment, lessons learned, action items, and recommendations.
  • Dashboard with retainer usage metrics, engagement status breakdown, and mean time to contain/close.

What's Built

  • 3 demo retainer contracts: Platinum (500h, 30-min SLA), Gold (250h, 60-min SLA), Silver (100h, 120-min SLA)
  • 5 realistic demo engagements: ransomware outbreak, BEC/CEO impersonation, supply chain compromise, insider threat data exfiltration, cloud credential leak
  • Full 6-phase engagement lifecycle with automatic timestamp tracking (activated_at, first_response_at, contained_at, closed_at)
  • Chronological timeline with 14 demo entries across all engagements, typed as action/finding/decision
  • Evidence chain-of-custody with 8 demo items (disk images, memory dumps, malware samples, log files) with SHA-256 hashes
  • Stakeholder communications with 5 demo records (email notifications, status updates, Slack war room messages)
  • 6 communication templates: Initial Notification, Status Update, Executive Brief, Containment Achieved, Engagement Closure, War Room Standup
  • Post-incident review (PIR) creation with root cause, impact assessment, lessons learned, action items, recommendations
  • Dashboard summary with retainer usage stats, active/closed counts, mean time to contain/close, and severity/status breakdowns
  • Full CRUD for engagements with status transition API that auto-creates timeline entries
  • DB-first architecture with seamless demo-data fallback
  • Comprehensive frontend dashboard with retainer cards, engagement list, timeline viewer, communication templates, and engagement detail modals

Architecture

Next.js Frontend
FastAPI Router
IRRetainerService
PostgreSQL / Demo Data

Engagement Lifecycle

Activated
Triaging
Containing
Eradicating
Recovering
Closed

Data Flow

  1. Frontend pages call /api/v1/ir-retainer/* endpoints via the shared api client.
  2. The router validates inputs using Pydantic schemas (e.g. EngagementStatusUpdate restricts valid phase values via regex).
  3. The service attempts DB operations first. On failure, falls back to in-memory demo data with 3 retainers, 5 engagements, and associated timeline/evidence/comms.
  4. Status transitions (PUT /engagements/{id}/status) automatically set contained_at when entering "containing" and closed_at when entering "closed", and insert a timeline entry for the phase change.

Source Files

LayerPath
Routerplatform/api/app/routers/ir_retainer.py
Serviceplatform/api/app/services/ir_retainer.py
Models (6)platform/api/app/models/ir_retainer.py
Schemasplatform/api/app/schemas/ir_retainer.py
Frontend Dashboardplatform/frontend/src/app/ir-retainer/page.tsx
Frontend Engagementsplatform/frontend/src/app/ir-retainer/engagements/page.tsx
Frontend Engagement Detailplatform/frontend/src/app/ir-retainer/engagements/[id]/page.tsx
Frontend PIRplatform/frontend/src/app/ir-retainer/pir/page.tsx
Frontend Communicationsplatform/frontend/src/app/ir-retainer/communications/page.tsx

Routing

Frontend Routes

RouteDescription
/ir-retainerDashboard -- retainer cards with hour gauges, active engagements, recent timeline, communication templates
/ir-retainer/engagementsEngagement list with severity/status filters and create engagement action
/ir-retainer/engagements/[id]Engagement detail -- timeline, evidence, communications, phase transition controls
/ir-retainer/pirPost-Incident Review creation and viewing
/ir-retainer/communicationsCommunication templates and engagement communication history

API Endpoints

All endpoints are under /api/v1/ir-retainer with the ir-retainer tag.

# Retainers GET /api/v1/ir-retainer/retainers # List all retainer contracts GET /api/v1/ir-retainer/retainers/{retainer_id} # Get single retainer # Engagements GET /api/v1/ir-retainer/engagements # List all engagements POST /api/v1/ir-retainer/engagements # Create new engagement (retainer_id, title, severity, lead_analyst, team) GET /api/v1/ir-retainer/engagements/{engagement_id} # Get detail (timeline, evidence, comms, PIR) PUT /api/v1/ir-retainer/engagements/{engagement_id}/status # Update phase (auto-timestamps + timeline entry) # Timeline POST /api/v1/ir-retainer/engagements/{engagement_id}/timeline # Add timeline entry (phase, author, type, title, description) # Evidence POST /api/v1/ir-retainer/engagements/{engagement_id}/evidence # Add evidence (type, name, hash_sha256, collected_by) # Communications POST /api/v1/ir-retainer/engagements/{engagement_id}/communications # Send communication (type, subject, body, recipients) # Post-Incident Review POST /api/v1/ir-retainer/engagements/{engagement_id}/pir # Create PIR (summary, root_cause, impact, lessons, actions, recommendations) # Dashboard & Templates GET /api/v1/ir-retainer/summary # Dashboard summary (retainer stats, MTTC, MTTR, severity breakdown) GET /api/v1/ir-retainer/communication-templates # 6 pre-built communication templates

Prerequisites

  • FastAPI backend with async SQLAlchemy and PostgreSQL (or demo mode).
  • Next.js 14+ frontend with the shared api client.
  • Tenant middleware -- all endpoints read request.state.tenant_id.
  • Database migrations for 6 tables: ir_retainers, ir_engagements, ir_timeline, ir_evidence, ir_communications, ir_post_incident_reviews.

Data Model

IRRetainer

ColumnTypeNotes
idString(36) PKUUID
tenant_idString(36)Indexed
tierString(20)platinum / gold / silver
hours_allocatedIntegerTotal contract hours
hours_usedFloatHours consumed across engagements
response_sla_minutesInteger30 / 60 / 120 by tier
contract_startDateTimeContract start date
contract_endDateTimeContract expiry date
statusString(20)active / expired / suspended

IREngagement

ColumnTypeNotes
idString(36) PKUUID
retainer_idString(36) FKReferences ir_retainers.id
tenant_idString(36)Indexed
titleString(500)Engagement title
descriptionTextFull description
severityString(20)critical / high / medium / low
statusString(30)activated / triaging / containing / eradicating / recovering / closed
lead_analystString(255)Primary IR analyst
team_membersJSONArray of analyst names
hours_spentFloatHours consumed on this engagement
activated_atDateTimeWhen engagement was activated
first_response_atDateTimeFirst analyst action timestamp
contained_atDateTimeAuto-set on "containing" transition
closed_atDateTimeAuto-set on "closed" transition

IRTimeline

ColumnTypeNotes
idString(36) PKUUID
engagement_idString(36) FKReferences ir_engagements.id
timestampDateTimeWhen the event occurred
phaseString(30)Phase at time of entry
authorString(255)Analyst name
entry_typeString(20)action / finding / decision / note
titleString(500)Entry headline
descriptionTextFull details
metadataJSONFlexible metadata

IREvidence

ColumnTypeNotes
idString(36) PKUUID
engagement_idString(36) FKReferences ir_engagements.id
evidence_typeString(50)disk_image / memory_dump / log_file / pcap / malware_sample / screenshot / other
nameString(500)Filename or artifact name
hash_sha256String(64)SHA-256 integrity hash
collected_byString(255)Analyst who collected evidence
collected_atDateTimeCollection timestamp
chain_of_custodyJSONCustody transfer log

IRCommunication

ColumnTypeNotes
idString(36) PKUUID
engagement_idString(36) FKReferences ir_engagements.id
comm_typeString(30)email / slack / phone / status_update
subjectString(500)Message subject
bodyTextMessage body
recipientsJSONArray of email addresses or channels
sent_byString(255)Analyst who sent
sent_atDateTimeSend timestamp

PostIncidentReview

ColumnTypeNotes
idString(36) PKUUID
engagement_idString(36) FKReferences ir_engagements.id
tenant_idString(36)Indexed
summaryTextPIR executive summary
root_causeTextRoot cause analysis
impact_assessmentTextBusiness impact
lessons_learnedJSONArray of lesson strings
action_itemsJSONArray of action item objects
recommendationsJSONArray of recommendation strings
created_byString(255)Author

Relationships

  • IRRetainer → has many IREngagement
  • IREngagement → has many IRTimeline
  • IREngagement → has many IREvidence
  • IREngagement → has many IRCommunication
  • IREngagement → has many PostIncidentReview

UI Description

Dashboard (/ir-retainer)

IR Command Center

Summary stat cards (Total Retainers, Active Engagements, Hours Used/Remaining, Avg Response Time, Open Action Items). Retainer cards with tier badges (platinum/gold/silver), hour gauges, SLA info, and contract dates. Active engagement list with severity badges, phase indicators, and analyst assignments. Recent timeline feed. Communication template cards with copy-to-clipboard and send actions.

Engagements (/ir-retainer/engagements)

Engagement Management

List view of all engagements with severity (critical/high/medium/low) badges, status phase indicators, lead analyst, hours spent, and SLA deadline. Create new engagement modal with retainer selection, title, severity, and team assignment. Click-through to engagement detail.

Engagement Detail (/ir-retainer/engagements/[id])

Engagement Detail View

Full engagement header with phase badge and team roster. Chronological timeline with colour-coded entry types (action=blue, finding=amber, decision=purple, note=grey). Evidence table with file names, types, SHA-256 hashes, and collection metadata. Communication log with sent messages. Phase transition controls.

PIR (/ir-retainer/pir)

Post-Incident Review

Create and view post-incident reviews for closed engagements. Structured form fields for summary, root cause analysis, impact assessment, lessons learned (bulleted list), action items (with owner and deadline), and recommendations.

Communications (/ir-retainer/communications)

Communication Center

6 pre-built communication templates (Initial Notification, Status Update, Executive Brief, Containment Achieved, Engagement Closure, War Room Standup) with variable placeholders. Communication history for each engagement with type badges (email/slack/phone/status_update), recipients, and timestamps.