Skip to content

Commit 2ff2f83

Browse files
Merge pull request #169 from ManoManoTech/feat/direct-incident-closure
Feat/direct incident closure
2 parents f8c3b3e + aac2b17 commit 2ff2f83

35 files changed

+2598
-30
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Incident Status Workflow
2+
3+
This document describes the exact incident status workflow implemented in FireFighter.
4+
5+
## Overview
6+
7+
The incident status workflow differs based on the incident priority:
8+
9+
- **P1/P2 incidents**: Require post-mortem completion in PRD environment
10+
- **P3/P4/P5 incidents**: Do not require post-mortem
11+
12+
## Workflow Transitions
13+
14+
### P1/P2 Incidents (Priority 1-2 in PRD Environment)
15+
16+
```
17+
OPEN → [INVESTIGATING, CLOSED (with reason)]
18+
INVESTIGATING → [MITIGATING, CLOSED (with reason)]
19+
MITIGATING → [MITIGATED]
20+
MITIGATED → [POST_MORTEM]
21+
POST_MORTEM → [CLOSED]
22+
```
23+
24+
**Key Rules for P1/P2:**
25+
- **Post-mortem is mandatory** for P1/P2 incidents in PRD environment
26+
- **Cannot skip POST_MORTEM status** - must go through it before closing
27+
- **From MITIGATING**: Can only go to MITIGATED, not to POST_MORTEM or CLOSED
28+
- **From MITIGATED**: Can only go to POST_MORTEM, not directly to CLOSED
29+
- **Closure with reason**: Only allowed from OPEN and INVESTIGATING statuses
30+
31+
### P3/P4/P5 Incidents (Priority 3+ or Non-PRD)
32+
33+
```
34+
OPEN → [INVESTIGATING, CLOSED (with reason)]
35+
INVESTIGATING → [MITIGATING, CLOSED (with reason)]
36+
MITIGATING → [MITIGATED]
37+
MITIGATED → [CLOSED]
38+
```
39+
40+
**Key Rules for P3+:**
41+
- **No post-mortem required** - POST_MORTEM status is not available
42+
- **Direct closure**: Can close directly from MITIGATED without intermediate steps
43+
- **Closure with reason**: Only allowed from OPEN and INVESTIGATING statuses
44+
45+
## Closure Reason Requirements
46+
47+
A closure reason form is **required** when closing an incident directly from:
48+
- **OPEN** status
49+
- **INVESTIGATING** status
50+
51+
This applies to **all priority levels** (P1-P5).
52+
53+
## Implementation Details
54+
55+
### Status Values
56+
- `OPEN = 10`
57+
- `INVESTIGATING = 20`
58+
- `MITIGATING = 30` (labeled as "Mitigating")
59+
- `MITIGATED = 40` (labeled as "Mitigated")
60+
- `POST_MORTEM = 50`
61+
- `CLOSED = 60`
62+
63+
### Form Logic Location
64+
The workflow logic is implemented in:
65+
- **Form**: `src/firefighter/incidents/forms/update_status.py`
66+
- **Enum**: `src/firefighter/incidents/enums.py`
67+
- **Tests**: `tests/test_incidents/test_forms/test_workflow_transitions.py`
68+
69+
### Priority Detection
70+
P1/P2 incidents requiring post-mortem are detected by:
71+
```python
72+
requires_postmortem = (
73+
incident.priority
74+
and incident.environment
75+
and incident.priority.needs_postmortem
76+
and incident.environment.value == "PRD"
77+
)
78+
```
79+
80+
## Testing
81+
82+
Comprehensive workflow tests are located in:
83+
- `tests/test_incidents/test_forms/test_workflow_transitions.py` - Complete workflow validation
84+
- `tests/test_incidents/test_forms/test_update_status_workflow.py` - Legacy tests (some skipped)
85+
- `tests/test_slack/views/modals/test_update_status.py` - Slack integration tests
86+
87+
## Migration Notes
88+
89+
This workflow was implemented to replace a previous more permissive workflow that allowed invalid transitions. The new implementation:
90+
91+
1. **Restricts transitions** to exactly match the business workflow requirements
92+
2. **Enforces post-mortem** completion for P1/P2 incidents in PRD
93+
3. **Simplifies P3+ workflow** by removing unnecessary post-mortem steps
94+
4. **Validates closure reasons** for early-stage closures
95+
96+
## Related Files
97+
98+
- **Forms**: `src/firefighter/incidents/forms/update_status.py`
99+
- **Enums**: `src/firefighter/incidents/enums.py`
100+
- **Slack Integration**: `src/firefighter/slack/views/modals/update_status.py`
101+
- **Utilities**: `src/firefighter/slack/views/modals/utils.py`
102+
- **Tests**: `tests/test_incidents/test_forms/test_workflow_transitions.py`

0 commit comments

Comments
 (0)