Fixture Bundle — Byte-Stable Demo Data
What it is
A deterministic export of the backend seed plus derived artefacts, copied verbatim into kxinspect_frontend_flutter/assets/fixtures/ and committed. Fixture mode needs no server or network — widgets render against these bytes.
Layout
assets/fixtures/
├── app_state.json # aggregate snapshot: bookings, inspections, tasks, charges, notifications
├── manifest.json # {"files": {"app_state.json": sha256, "media/att_*.png": sha256, ...}}
├── media/
│ ├── att_ct_chg003_01.png
│ ├── att_ph_chg001_01.png/.t.png # thumbnail companion (`_t`)
│ ├── att_rpt_001.pdf / att_rpt_002.pdf
│ └── … (seed photo set, deterministic)
└── vectors/
├── charge_state_vectors.json # 30 (status×event) rows with actor + acceptanceOrigin
├── deadline_vectors.json # leap-day, offset-change, -1s/0s/+1s inclusive tests
└── namespace_vectors.json # storage namespace fingerprints
Backend source:
kxinspect_backend_python/app/seed/*.json (6 files)
kxinspect_backend_python/app/static/photos/
kxinspect_backend_python/app/domain/charge_state.py:state_vectors()
kxinspect_backend_python/app/domain/deadline.py:deadline_vectors()
kxinspect_backend_python/scripts/export_fixtures.py (writer + sorter)
manifest.json hashes are sha256(fileBytes) hex; verify_fixture_manifest.py (and Dart helper CheckEvidence) fail on mismatch.
Generation
cd kxinspect_backend_python
uv run python scripts/export_fixtures.py --output /tmp/bundle
uv run python scripts/verify_fixture_manifest.py --bundle /tmp/bundle
# copy into frontend and commit
cp -R /tmp/bundle/* ../kxinspect_frontend_flutter/assets/fixtures/
Export sorts keys, normalizes newlines, and trims non-deterministic whitespace. No timestamp is embedded except the frozen referenceNow — re-export is byte-identical if seed + domain code + vectors are unchanged.
Consumption
| Consumer | Reads |
|---|---|
FixtureHttpClientAdapter | app_state.json bytes as mocked HTTP GET /hub, GET /charges/:id etc.; fabricates stateEpoch/storeRevision deterministically |
FixtureBundle (lib/core/database/fixture_bundle.dart) | app_state.json → LocalStore.applySnapshot seed on first launch |
LocalStore vectors replay | charge_state_vectors.json vs Dart lifecycle |
| Widget goldens | media/ thumbs for KxImage fallback proof |
Invariants
att_*ids are opaque; clients must not parse hex.- Every
ItemAction.chargeIdnon-null → realCHG-*. - Every
Charge.bookingId→ realBKG-*(hub filter relies on it). - Every referenced
downloadUrl/thumbnailUrllast segment appears inmanifest.json.
Changing a photo without re-exporting or without updating manifest.json fails tool/check_evidence.dart and the frontend contract test.
Why committed
Reviewers flutter run -d chrome --dart-define=DATA_SOURCE=fixture without checkout of the Python repo or network. The bundle is the offline oracle for CI goldens and unit tests.
See also
- Verification:
uv run python scripts/verify_fixture_manifest.py - Contract:
docs/contract-v1.md §Data & Fixtures - Frontend freshness:
tool/check_evidence.dartSHA guard forsubmission.yaml