wiki: split signed business ledger from device telemetry
Correction before schema work: the events table conflated the anti-fraud business ledger with device telemetry. Decision: ledger_events (signed, chained, reconciled) holds only business facts; device_events (unsigned, prunable) holds relay/printer/camera/reader/input telemetry. A raw button press is telemetry; the entry flow mints a signed vehicle_entry. Drops input_received-as-signed-event. New: decisions/event-streams-split, concepts/device-events; updated append-only-event-chain, index, log.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
---
|
||||
type: decision
|
||||
tags: [parking, decisions, integrity, devices, schema]
|
||||
sources: []
|
||||
updated: 2026-06-15
|
||||
status: open
|
||||
---
|
||||
|
||||
# Decision: Split the signed business ledger from device telemetry
|
||||
|
||||
Taken 2026-06-15, at the start of the business-layer schema work.
|
||||
|
||||
## The problem
|
||||
|
||||
The existing `events` table (signed, hash-chained — [[append-only-event-chain]]) had grown to carry
|
||||
**two unrelated concerns**: the financial/accountability ledger *and* raw device telemetry (button
|
||||
pushes recorded as `input_received`). They have opposite requirements — the ledger must be small,
|
||||
signed, and reconciled; telemetry is high-volume, churny, and disposable.
|
||||
|
||||
## Decision — two tables
|
||||
|
||||
- **`ledger_events`** — the signed, hash-chained, [[atecc608]]-signed **business ledger** (rename of
|
||||
`events`). Holds only business/accountability facts: `vehicle_entry`, `vehicle_exit`, `payment`,
|
||||
`void`, `shift_z_report`, and the witness-grade `barrier_open_command` / `barrier_open_observed` /
|
||||
`anomaly`. [[reconciliation]] runs against this; sessions/[[tariff]]/occupancy are projections of
|
||||
it.
|
||||
- **`device_events`** — **unsigned** operational telemetry (see [[device-events]]): relay fired,
|
||||
printer paper-out, camera offline, reader read, raw input edges. May rotate/prune. Never signed,
|
||||
never reconciled.
|
||||
|
||||
A raw button press is **telemetry** → `device_events`. The entry flow then mints a **signed
|
||||
`vehicle_entry`** in the ledger once a ticket prints + the barrier is commanded. So
|
||||
`input_received`-as-a-signed-event is **dropped** (it was transitional).
|
||||
|
||||
## Why
|
||||
|
||||
- Keeps the **signed ledger small and high-value** — fewer rows to sign, hash, verify, reconcile,
|
||||
and export; signal isn't drowned in device noise.
|
||||
- Right **durability semantics per stream**: the ledger is precious + append-only forever; telemetry
|
||||
can age out.
|
||||
- Clean separation matches the [[device-adapter-pattern]] philosophy — device chatter stays on the
|
||||
device side of the boundary.
|
||||
|
||||
## Consequences / migration (no production data yet)
|
||||
|
||||
- No `.sqlite` with real chain data exists, so renaming + restructuring is safe now (no signatures
|
||||
to invalidate). This is the moment to do it.
|
||||
- Code: rename `events` → `ledger_events`; `EventLog`/`canonicalize`/`verifyChain` and the
|
||||
`/api/events` routes follow the rename; add an unsigned `device_events` writer; move the Dingtian
|
||||
input-push handler to emit `device_events` (+ the entry flow signs `vehicle_entry`).
|
||||
- `ParkingEventType` in `packages/shared` splits into ledger types vs. a device-event type set.
|
||||
|
||||
## Open
|
||||
|
||||
- `device_events` retention/rotation policy.
|
||||
- Which device facts (if any) are witness-grade enough to *also* warrant a signed ledger entry
|
||||
(e.g. `barrier_open_observed` from a loop sensor) — see [[append-only-event-chain]] witness gap.
|
||||
Reference in New Issue
Block a user