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.8 KiB
type, tags, sources, updated, status
| type | tags | sources | updated | status | |||||
|---|---|---|---|---|---|---|---|---|---|
| concept |
|
2026-06-15 | open |
Ticket Encoding & Scanning
How a transient parking-session's ticket id is printed, carried by the customer, and read back at the pay station and exit. This is the physical backbone of the transient flow — the thing that links entry → pay → exit when there's no plate.
The ticket id is the session key
At entry the system mints a vehicle_entry event with a ticket id (identity) and prints a
ticket the customer keeps. That same id is read back later to find the session. Properties the id
must have:
- Opaque + unguessable — a random id (not a sequential count an attacker could iterate to claim someone else's cheaper session). Sequential physical stock numbering is a separate reconciliation aid (reconciliation pre-numbered stock), not the scan key.
- Single logical session — scanning it at the pay station finds the open session; after payment it's the proof-of-paid the exit checks.
Encoding: QR (preferred) — printed by the booth dispenser
- The rongta-printer prints the ticket id as a 2D barcode (QR) plus human-readable text and entry time. QR over 1D barcode: denser, tolerant of crumpling/partial reads, easy for a cheap camera/imager to read.
- Scan points (both host-side reads — entry-exit-readers):
- Pay station — customer scans the ticket → host finds the session → shows fee → takes
payment (tariff, pay-on-foot) → appends
payment. - Exit lane — customer scans the (now paid) ticket → host validates paid + within
gracePeriodExit→vehicle_exit→pulseOpen.
- Pay station — customer scans the ticket → host finds the session → shows fee → takes
payment (tariff, pay-on-foot) → appends
- The scanner is a device behind an adapter (device-adapter-pattern): a new
ReaderDevicekind (QR/barcode imager) — likely the sameIdentitySource = "ticket"/"qr"path. Keeps the app device-agnostic; hardware model is procurement (bom, open-questions).
Ticketless alternative (plate as the ticket)
Where the opencv-anpr-service/LPR captures the plate, the plate can be the session key instead of a printed ticket — drive in, plate read, drive to pay station and enter plate (or it's looked up), pay, exit by plate. No paper. The two can coexist per lane (entry-exit-readers "both share a relay"); a printed QR ticket is the fallback when a plate isn't captured or is low-confidence (recognition is advisory — opencv-anpr-service).
Open
- QR symbology/error-correction level + what else prints (site name, tariff summary, help number).
- Scanner hardware (imager model; same unit at pay station and exit?).
- Lost/damaged ticket → the lost-ticket path (parking-session, tariff admin-arbitrary amount).