Implementation-reality notes for the first shipped backend slice of Cases.
Cases are a durable backend object for grouping multiple reports around one incident and tracking:
- linked reports
- saved cluster snapshots
- suggested escalation targets
- status changes
- audit events
This first slice is intentionally conservative:
- polygon/geometry and nearby-report analysis are implemented
- case creation and report linking are implemented
- escalation target suggestion is implemented
- case-specific outbound email drafting, sending, and delivery tracking are implemented
- automatic case matching/reopen logic is not implemented yet
Owned by report-listener migrations:
saved_clusterscasescase_reportscase_clusterscase_escalation_targetscase_escalation_actionscase_email_deliveriescase_resolution_signalscase_audit_events
Migration step:
/Users/anon16/Downloads/cleanapp_back_end_v2/report-listener/database/migrate.go- step
0009_case_tables
These endpoints analyze a scope and return:
- reports in scope
- severity/time stats
- incident hypotheses
- suggested escalation targets
Routes:
POST /api/v3/clusters/analyzePOST /api/v3/clusters/from-reportPOST /api/v4/clusters/analyzePOST /api/v4/clusters/from-report
These routes require a bearer access token. report-listener now validates JWTs locally using the shared auth/token store.
Routes:
POST /api/v3/casesGET /api/v3/cases/:case_idPOST /api/v3/cases/:case_id/reportsPOST /api/v3/cases/:case_id/statusGET /api/v3/cases/:case_id/escalationsPOST /api/v3/cases/:case_id/escalations/draftPOST /api/v3/cases/:case_id/escalations/sendPOST /api/v4/casesGET /api/v4/cases/:case_idPOST /api/v4/cases/:case_id/reportsPOST /api/v4/cases/:case_id/statusGET /api/v4/cases/:case_id/escalationsPOST /api/v4/cases/:case_id/escalations/draftPOST /api/v4/cases/:case_id/escalations/send
The report-listener now acts as the public/authenticated case facade.
It:
- drafts a case escalation email from case title/summary/reports
- creates durable
case_escalation_actions - calls the email-service internal endpoint
- records per-recipient delivery truth in
case_email_deliveries
The email-service remains the actual SendGrid executor. It is not bypassed.
Internal email-service route:
POST /internal/case-escalations/send
Protected by:
INTERNAL_ADMIN_TOKEN
Case escalation API responses now expose:
- targets
- actions
- deliveries
- provider message ids
- sent timestamps
- per-recipient failures
Case writes are protected by:
/Users/anon16/Downloads/cleanapp_back_end_v2/report-listener/middleware/auth.go
This middleware expects:
Authorization: Bearer <access_token>
And validates using:
cleanapp-common/authx
report-listener must receive:
JWT_SECRET
The first clustering heuristic is intentionally explainable, not magical.
Reports are grouped using weighted similarity from:
- same classification
- similar severity
- shared incident language
- near-identical physical location
- same organization/brand when present
The response returns incident hypotheses with:
- representative report
- confidence
- severity
- urgency
- rationale list
- A polygon is a workspace scope, not automatically a case.
- New reports are not yet auto-matched into open cases.
report_clustersis not the canonical case backbone; the new case tables are.- Case escalation currently sends simple text/html summaries; richer attachment/memo generation is still future work.
- Add case detail views on web.
- Add automatic case matching/reopen suggestions during analysis.
- Make mobile case-aware after web workspace flow is stable.
- Improve case escalation drafting with richer memo/attachment generation.