Files
MobilityOps/docs/demo-release/demo-data.md
NuklearRabbit 38f654b97a docs(demo): add demo concept, scenarios, data, guide and runbook docs
Documents the demo-productization work from this branch: the Northstar
Mobility fictional concept and scope, the five named scenarios and their
fixed records, the seed/date-anchoring strategy (including the real bug
it fixed), the in-app Demo Guide's design and the English-suggested-
questions decision, and an operational runbook covering 5/10-minute demo
flows, reset, Unraid redeploy and rollback. Updates README with current
test counts and pointers to the new docs.
2026-08-03 15:24:35 +02:00

84 lines
4.2 KiB
Markdown

# Demo data strategy
## Three separate concepts
It's important to keep these distinct — they solve different problems:
1. **Deterministic records** — every seeded entity has a stable public reference
(`BK-DEMO-RETURN`, `DQ-DEMO-DUPLICATE`, `MO-024`, `CUS-0012`, ...). These references
never change between seed generations or resets; they are what the five demo
scenarios, the Demo Guide, and `docs/13-seed-and-demo-scenarios.md` all link against.
2. **Date anchoring** — the mechanism that keeps "today"/"near-future"/"currently
overlapping" scenarios true to whenever the environment was actually last reset,
described below.
3. **The reset date** — the real wall-clock moment a reset actually happened. This
changes every time someone resets; it's the input to date anchoring, not a fixed
record.
## Generating the seed dataset
```bash
python seed/generate_seed.py --anchor 2026-08-01 --seed 20260801
```
This produces the committed CSVs in `seed/*.csv` with **absolute ISO timestamps**
authored relative to a fixed anchor date (`2026-08-01`). Target scale: 50 vehicles, 180
customers (including three duplicate pairs), ~245 historical/current/future bookings,
realistic inspections and maintenance history, and the fixed quality/workflow scenarios
described in [`demo-scenarios.md`](demo-scenarios.md). Names, towns and vehicle makes are
drawn from believable Flemish/Kempen-region pools; all emails use the `.test` domain.
## Date anchoring
`backend/app/seed_loader.py` defines:
```python
SEED_AUTHORED_ANCHOR = date(2026, 8, 1) # matches generate_seed.py's --anchor
```
Every seed/reset computes `shift = today - SEED_AUTHORED_ANCHOR` and applies it to every
seeded booking, inspection, maintenance and outbox timestamp before insertion. Public
references and entity relationships are never touched by the shift — only datetime
columns move. This means:
- `BK-DEMO-RETURN` always ends "today" (or very close to it) relative to whenever you
actually reset, not relative to the frozen 2026-08-01 authoring date.
- `BK-DEMO-NEXT` and the overlap-scenario bookings always read as "near future".
- The shift is recomputed fresh on every reset, so scenarios never decay as real time
passes between resets — this was a real, confirmed bug before this fix (see
`docs/demo-release/current-demo-gap-audit.md`, gap #3): the environment would drift
further out of sync with every day it wasn't reset, and a reset didn't fix it because
nothing re-anchored the underlying stored dates.
`load_seed()` returns the resolved `anchor_date` (real today) and `seeded_at` timestamp,
and records a `demo_data_seeded` audit event carrying both the resolved anchor and the
original authoring anchor, so the shift applied on any given reset stays traceable via
the audit trail.
`dashboard.py::_today()` uses real wall-clock UTC date (not a frozen setting) to filter
"today's movements", consistent with the shifted data.
## Reset
`POST /api/v1/demo/reset` (Operations Manager only, and only if `DEMO_ALLOW_RESET=true`)
clears all MobilityOps tables, reloads the seed with a fresh date shift, re-runs the
data-quality scan, and runs a server-side **scenario-integrity check**
(`scenario_integrity_report()` in `backend/app/services/demo_manifest.py`) confirming all
five named scenarios are actually present and ready — recorded in both the response body
and the `demo_reset` audit event's metadata. Reset only ever affects MobilityOps's own
tables; it never touches shared n8n, RAGcore, or MCP data, other containers, or volumes.
## Seed-validation tests
`backend/tests/test_seed.py` proves, after every reset:
- S1 (`BK-DEMO-RETURN`/`MO-024`) is active with no end odometer recorded yet.
- S2 (`CUS-0012`/`CUS-0178`/`DQ-DEMO-DUPLICATE`) is open with matching evidence.
- S4 (`MO-016`/`BK-DEMO-OVERLAP-A`/`-B`/`DQ-DEMO-OVERLAP`) genuinely overlaps in time.
- S5 (the seeded failed outbox event) is durably `failed` immediately after reset, not
silently auto-healed by the background dispatcher (which only claims `pending` rows).
- The date-anchoring shift and the `demo_data_seeded` audit marker are both correct.
`backend/tests/test_demo_manifest.py` additionally proves that all five manifest
scenarios report `ready: true` with no `blocked_reason` right after a fresh reset.