|
| 1 | +# Incident Closure Workflow |
| 2 | + |
| 3 | +This document describes the complete incident closure workflow in FireFighter, including the different paths and requirements for closing incidents based on priority and status. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +FireFighter supports multiple ways to close incidents, with different requirements based on the incident's priority level and current status. The workflow ensures that critical incidents (P1/P2) follow proper post-mortem procedures, while allowing more streamlined closure for lower priority incidents. |
| 8 | + |
| 9 | +## Workflow Diagram |
| 10 | + |
| 11 | +```mermaid |
| 12 | +graph TD |
| 13 | + A[Incident Created] --> B[Opened] |
| 14 | + B --> C[Investigating] |
| 15 | + C --> D[Mitigating] |
| 16 | + D --> E[Mitigated] |
| 17 | +
|
| 18 | + %% P1/P2 PRD Path (Post-mortem Required) |
| 19 | + E --> F{P1/P2 in PRD?} |
| 20 | + F -->|Yes| G[Post-mortem] |
| 21 | + G --> H[Closed] |
| 22 | +
|
| 23 | + %% P3+ Path (No Post-mortem Required) |
| 24 | + F -->|No| H |
| 25 | +
|
| 26 | + %% Closure with Reason (Any Priority) |
| 27 | + B -->|Reason Required| I[Closure Reason Form] |
| 28 | + C -->|Reason Required| I |
| 29 | + I --> H |
| 30 | +
|
| 31 | + %% Normal Workflow Closure |
| 32 | + E -->|Normal Close| H |
| 33 | + G -->|Normal Close| H |
| 34 | +
|
| 35 | + %% Status Labels |
| 36 | + B[Opened<br/>⚠️ Reason required for closure] |
| 37 | + C[Investigating<br/>⚠️ Reason required for closure] |
| 38 | + D[Mitigating] |
| 39 | + E[Mitigated] |
| 40 | + G[Post-mortem<br/>✅ Can close normally] |
| 41 | + H[Closed<br/>📁 Channel archived] |
| 42 | + I[Closure Reason<br/>🗃️ Mandatory form] |
| 43 | +``` |
| 44 | + |
| 45 | +## Closure Methods |
| 46 | + |
| 47 | +### 1. Normal Workflow Closure |
| 48 | + |
| 49 | +**Path**: `Mitigated` → `Closed` (or `Post-mortem` → `Closed` for P1/P2) |
| 50 | + |
| 51 | +- **When**: Incident has been properly resolved through the normal workflow |
| 52 | +- **Requirements**: |
| 53 | + - Status must be `Mitigated` or higher |
| 54 | + - For P1/P2 in PRD: Must complete post-mortem first |
| 55 | +- **Triggered via**: |
| 56 | + - `/incident close` command |
| 57 | + - Update status to "Closed" (when allowed) |
| 58 | + |
| 59 | +### 2. Closure with Reason |
| 60 | + |
| 61 | +**Path**: `Opened/Investigating` → `Closure Reason Form` → `Closed` |
| 62 | + |
| 63 | +- **When**: Incident needs to be closed without following the complete workflow |
| 64 | +- **Use cases**: |
| 65 | + - Duplicate incidents |
| 66 | + - False alarms |
| 67 | + - No actual anomaly |
| 68 | + - User error |
| 69 | +- **Requirements**: |
| 70 | + - Mandatory closure reason selection |
| 71 | + - Optional reference to related incident/link |
| 72 | + - Closure message explaining the decision |
| 73 | +- **Triggered via**: |
| 74 | + - `/incident close` command (shows reason form automatically) |
| 75 | + - Update status to "Closed" from early statuses (shows reason form automatically) |
| 76 | + |
| 77 | +## Priority-Based Rules |
| 78 | + |
| 79 | +### P1/P2 Incidents in PRD Environment |
| 80 | + |
| 81 | +- **Post-mortem Required**: Must complete post-mortem before normal closure |
| 82 | +- **Workflow**: `Mitigated` → `Post-mortem` → `Closed` |
| 83 | +- **Direct Closure**: Still available from `Opened/Investigating` with reason |
| 84 | + |
| 85 | +### P3/P4/P5 Incidents |
| 86 | + |
| 87 | +- **Post-mortem Optional**: Can close directly from `Mitigated` status |
| 88 | +- **Workflow**: `Mitigated` → `Closed` |
| 89 | +- **Direct Closure**: Available from `Opened/Investigating` with reason |
| 90 | + |
| 91 | +## Status Restrictions |
| 92 | + |
| 93 | +### From "Opened" or "Investigating" |
| 94 | + |
| 95 | +- ❌ **Cannot close normally** without reason |
| 96 | +- ✅ **Can close with reason** (mandatory closure reason form) |
| 97 | +- **All priorities** follow the same rule |
| 98 | + |
| 99 | +### From "Mitigating" or "Mitigated" |
| 100 | + |
| 101 | +- ✅ **Can close normally** (P3+ incidents) |
| 102 | +- ❌ **Cannot close normally** (P1/P2 in PRD - must go through post-mortem) |
| 103 | + |
| 104 | +### From "Post-mortem" |
| 105 | + |
| 106 | +- ✅ **Can close normally** (all priorities) |
| 107 | + |
| 108 | +## Closure Reason Types |
| 109 | + |
| 110 | +When closing with a reason, the following options are available: |
| 111 | + |
| 112 | +- **DUPLICATE**: Duplicate of another incident |
| 113 | +- **FALSE_POSITIVE**: False alarm - no actual issue |
| 114 | +- **SUPERSEDED**: Superseded by another incident |
| 115 | +- **EXTERNAL**: External dependency/known issue |
| 116 | +- **CANCELLED**: Cancelled - no longer relevant |
| 117 | + |
| 118 | +*Note: "RESOLVED" is excluded from early closure reasons as it's reserved for normal workflow closure only.* |
| 119 | + |
| 120 | +## Technical Implementation |
| 121 | + |
| 122 | +### Key Components |
| 123 | + |
| 124 | +1. **UpdateStatusForm.requires_closure_reason()**: Determines when closure reason is needed |
| 125 | + - Location: `src/firefighter/incidents/forms/update_status.py` |
| 126 | + |
| 127 | +2. **IncidentClosureReasonForm**: Handles closure reason input |
| 128 | + - Location: `src/firefighter/incidents/forms/closure_reason.py` |
| 129 | + |
| 130 | +3. **ClosureReason Enum**: Defines available closure reasons |
| 131 | + - Location: `src/firefighter/incidents/enums.py` |
| 132 | + |
| 133 | +4. **Modal Utils**: Circular import resolution and modal routing |
| 134 | + - Location: `src/firefighter/slack/views/modals/utils.py` |
| 135 | + |
| 136 | +5. **Slack Integration**: Modal handlers for closure reason collection |
| 137 | + - Close Modal: Redirects to reason form when needed |
| 138 | + - Update Status Modal: Shows reason form for early closure attempts |
| 139 | + |
| 140 | +### Closure Reason Detection Logic |
| 141 | + |
| 142 | +The system determines if a closure reason is required based on the incident's current status: |
| 143 | + |
| 144 | +```python |
| 145 | +@staticmethod |
| 146 | +def requires_closure_reason(incident: Incident, target_status: IncidentStatus) -> bool: |
| 147 | + """Check if closing this incident to the target status requires a closure reason.""" |
| 148 | + if target_status != IncidentStatus.CLOSED: |
| 149 | + return False |
| 150 | + |
| 151 | + current_status = incident.status |
| 152 | + |
| 153 | + # Require reason if closing from Opened or Investigating (for any priority) |
| 154 | + return current_status.value in [IncidentStatus.OPEN, IncidentStatus.INVESTIGATING] |
| 155 | +``` |
| 156 | + |
| 157 | +### Database Fields |
| 158 | + |
| 159 | +Closure reason information is stored in the incident model: |
| 160 | + |
| 161 | +- `closure_reason`: Selected reason code (ClosureReason enum) |
| 162 | +- `closure_reference`: Optional reference to related incident or external link |
| 163 | + |
| 164 | +## User Experience |
| 165 | + |
| 166 | +### Slack Commands |
| 167 | + |
| 168 | +- **`/incident close`**: |
| 169 | + - Shows normal close form if status allows |
| 170 | + - Shows closure reason form if closing from early status |
| 171 | + - Shows error message if prerequisites not met |
| 172 | + |
| 173 | +- **`/incident update`**: |
| 174 | + - Shows normal update form |
| 175 | + - Intercepts "Closed" selection from early statuses |
| 176 | + - Automatically pushes closure reason form when needed |
| 177 | + |
| 178 | +### Modal Flow |
| 179 | + |
| 180 | +1. User attempts to close incident |
| 181 | +2. System checks current status and requirements |
| 182 | +3. Routes to appropriate modal: |
| 183 | + - Normal close form (if status allows) |
| 184 | + - Closure reason form (if early status) |
| 185 | + - Error message (if prerequisites not met) |
| 186 | + |
| 187 | +## Benefits |
| 188 | + |
| 189 | +- **Streamlined Process**: Single workflow for all closure scenarios |
| 190 | +- **Proper Documentation**: Reasons captured for audit and analysis |
| 191 | +- **Flexibility**: Supports both rigorous and quick closure paths |
| 192 | +- **Consistency**: Same logic applies across all interfaces |
| 193 | +- **User-Friendly**: Automatic detection and routing to correct form |
0 commit comments