Files
parking_solution/wiki/decisions/session-model.md
T
julian 8a8e74561d wiki: design the business layer (session, tariff, permit, vision, shift, ops)
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).
2026-06-15 17:41:38 +02:00

2.9 KiB

type, tags, sources, updated, status
type tags sources updated status
decision
parking
decisions
domain
business
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

  1. A session is a projection over the signed event log, not a mutable table. The append-only-event-chain events table stays the only source of truth; a parking-session is folded from vehicle_entry / vehicle_exit / payment / void events. A cache table is allowed for query speed but is always rebuildable and never authoritative.
  2. 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).
  3. 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).
  4. New signed event types: vehicle_entry, vehicle_exit, payment, void — extend the existing input_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