Pivot from the hardware/integrity layer to the parking operation. All wiki-only; no code yet. Core principle throughout: business entities are projections over the signed append-only event log, never mutable tables. New concepts: parking-session, tariff (composable/versioned, FX-ready), shift (manned-only Z-report), capacity-occupancy, validation-discounts, reporting-analytics, clock-integrity, ticket-encoding, anti-passback. New entities: permit, opencv-anpr-service, blocklist. Decisions: session-model, vision-service (host-side ANPR + vehicle verification; scoped AGPL exception for the isolated service). Updates: append-only-event-chain (new event types + vision witness), local-jwt-auth (drop 8h expiry -> until logout; code change pending), lpr-camera (host-side recognition supersedes edge-AI), standing-decisions (AGPL exception), open-questions (+FX, +pay-station money corners, backup). Deferred + flagged: intercom/help-call, receipts/refunds/change, FX engine, lane topology (#1).
2.9 KiB
type, tags, sources, updated, status
| type | tags | sources | updated | status | ||||
|---|---|---|---|---|---|---|---|---|
| decision |
|
2026-06-15 | open |
Decision: Parking Session Model
The starting decision for the business layer, taken 2026-06-15 as the project pivots from the (now hardware-verified) device/integrity layer to the parking operation.
Decisions
- A session is a projection over the signed event log, not a mutable table. The
append-only-event-chain
eventstable stays the only source of truth; a parking-session is folded fromvehicle_entry/vehicle_exit/payment/voidevents. A cache table is allowed for query speed but is always rebuildable and never authoritative. - Transient-first, mixed site. Model the casual pay-for-duration session + tariff first; layer permit holders on top as a second identity source that short-circuits payment (entry-exit-readers).
- Pay-on-foot / pay station. Payment is decoupled from exit: the customer pays at a central station; the exit lane only validates the session is paid and within the walk-back grace window before opening (parking-session lifecycle). Matches the autonomous-direction roadmap and sharpens open-questions #3 toward an unmanned pay station (PCI scope still kept out of the app via a certified terminal).
- New signed event types:
vehicle_entry,vehicle_exit,payment,void— extend the existinginput_received. Recorded in append-only-event-chain.
Why (rejected alternative)
A mutable sessions table carrying amountOwed / paidStatus as the source of truth was
rejected: it reopens the exact fraud vector the system exists to close (threat-model — the
insider edits the row, marks it paid, pockets the cash). Making "paid" a signed payment
event means it can't be forged and can't be silently deleted (a deletion breaks the chain). The
projection approach costs a fold/cache but keeps the anti-fraud guarantee intact end-to-end.
What this unblocks
Closes the dangling thread from device-input-flow ("the entry flow itself is the next
build"): input_received → signed vehicle_entry → ticket print → pulseOpen, then the
pay-station and exit-validation flows. Schema (packages/db) + shared types follow the
parking-session + tariff design pages.
Open / next
- Rate card, currency, grace windows, caps — operator/procurement input (tariff).
- Tariff versioning (effective-dated) for historical repricing.
- permit data model + lapsed-mid-stay handling.
- Wire payment capture to a concrete pay-station terminal (open-questions #3) — kept abstract (payment = an independent signed event referencing a session) until procurement settles.
- Reconciliation of sessions/payments against an external authority remains open-questions #4
- the unbuilt witness/reconciliation gap in append-only-event-chain.