The case-status vocabulary has three coexisting generations
There is no single source of truth for what a case's status can be. Three naming generations coexist in the live system:
| Where | Values used |
|---|---|
src/lib/workflow-config.ts (CaseStatus) | INTAKE, PRELIMINARY_INQUIRY, CHARGES_ISSUED, CONSULTATION_PORTAL, RESPONSE_WINDOW, EVIDENCE_PHASE, BODIES_OPINION, FINAL_REPORT, CLOSED, SUSPENDED, ARCHIVED (8 operational + 3 terminal) |
useWorkflow.ts runtime guards | additionally special-cases legacy aliases INQUERITO_PREVIO and NOTA_CULPA |
seed-test-data edge function | DRAFT, INTAKE, PRELIMINARY_INQUIRY, FORMAL_PROCEEDING, CHARGES_NOTICE, CLOSED |
Postgres case_status enum | ~24 values accreted across three migrations (see below) |
The database case_status enum was:
- v1:
new,in_progress,under_review,closed - v2 (destructive
DROP+CREATEwith a data remap):DRAFT,INTAKE,PRELIMINARY_INQUIRY,FORMAL_PROCEEDING,CHARGES_NOTICE,EMPLOYEE_RESPONSE,EVIDENCE_PHASE,DECISION_DRAFT,DECISION_ISSUED,CLOSED,SUSPENDED,CANCELLED - v3 (
ADD VALUE×11):FORMAL_OPEN,PREPARE_CHARGES,CHARGES_REVIEW,CHARGES_ISSUED,CONSULTATION_PORTAL,RESPONSE_WINDOW,BODIES_CHECK,BODIES_OPINION,FINAL_REPORT,DECISION_REVIEW,ARCHIVED
Postgres enums cannot drop values, so every legacy value is still a legal state in
the column. The column DEFAULT is 'DRAFT' — a value workflow-config.ts does not
model at all.
The tacit assumption: that a case's status is one of the 8 the UI knows about. In
reality the DB will happily hold FORMAL_PROCEEDING, new, or DECISION_ISSUED, and
the UI's STATUS_LABELS[status] lookup returns undefined for those — blank badges,
broken timelines, getFilteredTransitions returning [] (a stuck case).
What breaks: any rebuild that models status as a clean 8-value enum will choke on real historical rows. Migration of existing data requires an explicit mapping table across all three generations, and a decision on the orphan states.
Rebuild implication
Define one canonical status set, write an explicit legacy→canonical map, and migrate the
column with a CHECKed conversion. Do not assume the data is clean.