Order display status is a read-time derivation, not a persisted column
SUPERSEDED by ADR-0012 (2026-07-09). Pran's #950 makes the canonical statuses the DB literal set, so the status IS now stored (derive-then-store) — not read-time-only. What survives: the single provider-agnostic pure classifier, no per-provider branches, and netting/reconciliation never depending on display wording. What's reversed: "never stored". Read ADR-0012 first.
We show users a richer order status than the DB Order.status enum can express — a single
"partially matched" primary plus a remainder disposition sub-message ("X still to match" /
"Y lapsed" / "Y cancelled by you"), and the fully-lapsed / fully-cancelled / fully-voided terminal
states. We derive this Display Status at read-time (the /orders serializer + the WS
order:status payload) from the Size Vector already persisted on the order
(sizeMatched / sizeRemaining / sizeLapsed / sizeCancelled + settlementOutcome + hasLiveRemainder
- requested stake). It is never stored, and reconciliation and netting must never depend on it (Bhargav, 2026-07-08).
Considered options
- Stored, indexed
display_statuscolumn (write on the same order-update tx). Rejected: forces a migration + backfill + a second write path that can drift from the derivation, and — the deciding factor — it invites reconciliation/reporting to couple to display wording, which we explicitly want to keep independent going forward. - Read-time pure derivation (chosen): zero migration, always consistent with the source columns, trivially reversible, and structurally impossible for netting/reconciliation to depend on.
Consequences
- Admin/ops cannot
WHERE display_status = …in SQL. Acceptable: such filters operate on the raw size/lifecycle columns, or client-side over already-fetched rows. If a hard SQL-filter need ever appears, the same pure function can back a Postgres generated column with no logic change. - The derivation must be a single pure
deriveDisplayStatus(sizeVector) → DisplayStatuswith no per-provider branches — each adapter's only job is to normalize its wire payload into the Size Vector. A new provider adds a normalizer, never a status rule.