Domain Specification: Case Management¶
Validated against PRD v1.0 — All FR-CM-* requirements implemented here. See Traceability Matrix.
1. Context Overview¶
Bounded Context: casemanagement
Responsibility: Manage investigation cases — lifecycle, assignment, evidence, notes, escalation, decisions. Single-pane analyst workspace.
Owns: Case aggregate root.
Depends On: Workflow Orchestration (case creation, state sync), RBAC (role-based access), Notification (alerts), Audit (logging).
Events Published: CaseCreated, CaseAssigned, NoteAdded, EvidenceAttached, DecisionMade, CaseClosed.
2. Case Lifecycle¶
stateDiagram-v2
[*] --> CREATED
CREATED --> ASSIGNED : auto/supervisor assigns
ASSIGNED --> IN_PROGRESS : analyst starts work
IN_PROGRESS --> PENDING_REVIEW : analyst submits
IN_PROGRESS --> ESCALATED : risk/sanctions/PEP trigger
IN_PROGRESS --> WAITING_EXTERNAL : document requested
PENDING_REVIEW --> DECIDED : reviewer decides
DECIDED --> CLOSED : audit check
ESCALATED --> IN_PROGRESS : escalation handled
WAITING_EXTERNAL --> IN_PROGRESS : docs received
| From | To | Trigger | Actor |
|---|---|---|---|
| CREATED | ASSIGNED | Case auto-assigned or supervisor assigns | System / Supervisor |
| ASSIGNED | IN_PROGRESS | Analyst opens and starts work | Analyst |
| IN_PROGRESS | PENDING_REVIEW | Analyst submits for review | Analyst |
| IN_PROGRESS | ESCALATED | Escalation triggered (risk score, sanctions hit, PEP) | System |
| PENDING_REVIEW | DECIDED | Reviewer makes decision | Reviewer |
| DECIDED | CLOSED | Final audit check complete | System |
| Any | WAITING_EXTERNAL | Document requested from customer | Analyst |
3. API Contracts¶
3.1 Get Analyst Queue¶
GET /api/v1/cases?status=ASSIGNED,IN_PROGRESS&assignedTo={userId}&page=1&limit=20
Authorization: Bearer <jwt>
Response 200:
{
"items": [
{
"caseId": "uuid",
"caseType": "ONBOARDING_REVIEW",
"customerName": "ACME Holdings B.V.",
"customerType": "CORPORATE",
"riskBand": "MEDIUM",
"state": "ASSIGNED",
"priority": "MEDIUM",
"escalationLevel": 0,
"slaDeadline": "2025-06-02T12:00:00Z",
"slaRemaining": "18h 30m",
"createdAt": "2025-06-01T10:00:00Z",
"tags": ["PEP_EXPOSURE"]
}
],
"total": 12,
"page": 1
}
3.2 Get Case Detail (Analyst Workspace)¶
GET /api/v1/cases/{caseId}
Authorization: Bearer <jwt>
Response 200:
{
"caseId": "uuid",
"caseType": "ONBOARDING_REVIEW",
"state": "IN_PROGRESS",
"customer": { /* full customer profile */ },
"riskAssessment": { /* current risk rating */ },
"screeningResults": [ /* all screening results */ ],
"ownershipGraph": { /* network analysis output */ },
"documents": [ /* all uploaded documents */ ],
"notes": [
{ "noteId": "uuid", "author": "KYC Analyst", "content": "...", "createdAt": "..." }
],
"decisions": [ /* decisions made so far */ ],
"auditTrail": [ /* recent audit events */ ],
"availableActions": ["ADD_NOTE", "REQUEST_DOCUMENT", "APPROVE", "REJECT", "ESCALATE"]
}
3.3 Add Case Note¶
POST /api/v1/cases/{caseId}/notes
Authorization: Bearer <jwt>
Request: { "content": "Verified UBO structure. All beneficial owners identified. Ownership chain matches corporate registry." }
Response 201: { "noteId": "uuid", "createdAt": "2025-06-01T13:00:00Z" }
3.4 Reassign Case¶
PATCH /api/v1/cases/{caseId}
Authorization: Bearer <jwt> (SUPERVISOR role required)
Request: { "assignedTo": "user-uuid", "reason": "Workload balancing — Analyst A has 15 cases, Analyst B has 5" }
Response 200: { "caseId": "uuid", "assignedTo": "user-uuid", "reassignedAt": "2025-06-01T14:00:00Z" }
3.5 Make Decision¶
POST /api/v1/cases/{caseId}/decisions
Authorization: Bearer <jwt>
Idempotency-Key: <uuid>
Request:
{
"decisionType": "APPROVED",
"rationale": "All KYC checks passed. Screening clear. Risk MEDIUM — acceptable for lending product."
}
Response 201: { "decisionId": "uuid", "caseState": "DECIDED" }
3.6 Supervisor Dashboard¶
GET /api/v1/cases/summary?supervisorId={userId}
Authorization: Bearer <jwt>
Response 200:
{
"teamStats": [
{ "analystId": "uuid", "name": "Jane Doe", "activeCases": 8, "avgAgeHours": 12.5, "slaBreachRisk": 1 },
{ "analystId": "uuid", "name": "John Smith", "activeCases": 15, "avgAgeHours": 28.3, "slaBreachRisk": 3 }
],
"totalCases": 23,
"byState": { "ASSIGNED": 5, "IN_PROGRESS": 12, "PENDING_REVIEW": 4, "ESCALATED": 2 },
"slaAtRisk": 4,
"slaBreached": 1
}
4. Escalation Model¶
| Level | Role | Trigger Examples | SLA |
|---|---|---|---|
| L1 | KYC Analyst | Standard review, document validation | 24h |
| L2 | Senior Analyst | Ownership complexity >3 levels, identity mismatch, analyst uncertainty | 12h |
| L3 | EDD Analyst | HIGH risk band, PEP exposure, sanctions POTENTIAL_MATCH | 48h |
| L4 | FCC Reviewer | Policy exception, sanctions CONFIRMED_MATCH, prohibited jurisdiction | 24h |
| L5 | Executive / Legal | Critical sanctions, law enforcement request, executive override | 8h |
Escalation chain preserved in audit trail. Each escalation level records: who escalated, to whom, timestamp, reason.
5. Error Handling¶
| Scenario | Behavior |
|---|---|
| Reassign to self | 400 Bad Request. "Cannot reassign case to yourself." |
| Approve own escalation (SoD) | 403 Forbidden. "Analyst who investigated cannot approve. Escalate to FCC Reviewer." |
| Close without decision | 422 Unprocessable. "Case must have at least one decision before closing." |
| SLA breached without action | Auto-escalates to supervisor queue. Notification sent. |
| Case not found | 404. "Case {id} not found or you do not have access." |
Spec validated against PRD v1.0 requirements FR-CM-01 through FR-CM-05.