ticket: site metadata header + scannable Albanian ticket; widen barcode
- site_config gains optional park identity (park_name, operator_name, nius, address, phone, email); additive Drizzle migration 0001. GET/PUT /api/site-config read/write the full config (PUT partial patch, admin only); SiteSettings + SetupWizard expose the fields. - renderTicket() prints an Albanian header sourced from site_config, the all-numeric 13-digit ticket id (12 random + Luhn) as Code128, large digits, and a lost-ticket footer. CP852 codepage so ë/ç render. - Widen the Code128 module width 2->3 and height 80->100 dots so the short-range "Simple" QR/barcode reader decodes reliably (was barely reading at module width 2 on the 80mm head). See wiki/concepts/site-metadata.md and ticket-encoding.md.
This commit is contained in:
@@ -21,14 +21,35 @@ 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.
|
||||
- **All-numeric** (as-built 2026-06-17) — so ANY legacy 1D barcode scanner reads it and an operator
|
||||
can hand-key it. Random (not sequential), so "all-numeric" does not weaken the unguessable
|
||||
property. Format: **13 digits = 12 cryptographically-random digits + 1 Luhn check digit**
|
||||
(10^12 space → negligible collisions at lot scale; the Luhn digit lets manual entry reject a typo
|
||||
rather than fail as "session not found"). `newTicketId()` in `apps/server/src/entry-flow.ts`;
|
||||
validate with `validateTicketCode()` (gate MANUAL entry only — a scanned/looked-up id already in
|
||||
the ledger is authoritative regardless of format).
|
||||
- **Format is a property of minting, not the schema** — `identity` / `sessions.id` are free-form
|
||||
`text`, so changing the id format is a code change with **no migration**. Legacy `T-<uuid>` ids
|
||||
(pre-2026-06-17) remain valid keys and coexist with numeric ones.
|
||||
- **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
|
||||
## Encoding: Code128 numeric barcode — 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.
|
||||
- The [[rongta-printer]] prints the ticket id as a **1D Code128 barcode** (the all-numeric code),
|
||||
with the **same code in large human-readable digits below it**, then the entry time. Code128 over
|
||||
QR for the primary symbology because the booth's reader hardware is unknown and a legacy 1D laser
|
||||
scanner is the lowest common denominator — and the printed digits mean total reader failure still
|
||||
leaves a hand-keyable code. A **QR for phone/imager scanning may be added later behind an admin
|
||||
toggle** (deferred — see Open).
|
||||
|
||||
> **As-built (2026-06-17).** `renderTicket()` in [[rongta-printer]]
|
||||
> (`packages/devices/src/drivers/printer-rongta.ts`) emits the Code128 via ESC/POS `GS k` (code set
|
||||
> B) — **rendered by the printer firmware**, so there is no image-rendering step and no new
|
||||
> dependency (keeps the MIT/Apache/BSD constraint). Resilience rationale: the booth's reader is
|
||||
> uncertain, so the id is carried in two independently-readable forms (1D barcode / printed digits).
|
||||
> The "operator scans with a phone" path reuses the
|
||||
> existing dispatch flow ([[entry-exit-readers]]) and is tracked separately (not yet built).
|
||||
- **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`.
|
||||
@@ -51,7 +72,14 @@ isn't captured or is low-confidence (recognition is advisory — [[opencv-anpr-s
|
||||
|
||||
## Open
|
||||
|
||||
- QR symbology/error-correction level + what else prints (site name, tariff summary, help number).
|
||||
- Primary symbology **decided**: Code128 set B over the all-numeric id (as-built above). Still open:
|
||||
what *else* prints (site name, tariff summary, help number).
|
||||
- **Optional QR (deferred)** — an admin toggle to ALSO print a QR for phone/imager users. The
|
||||
`code128()`/`qrCode()` ESC/POS helpers were prototyped 2026-06-16; QR was dropped 2026-06-17 in
|
||||
favor of "1D barcode + hand-keyable numeric code" because the booth's reader hardware is unknown.
|
||||
Revisit when mobile scanning is wanted.
|
||||
- **Phone-scan fallback** (operator scans a ticket with a phone when a reader is down) — designed
|
||||
but not built: an authenticated route feeding the same dispatcher + a minimal mobile scan UI.
|
||||
- Scanner hardware (imager model; same unit at pay station and exit?).
|
||||
- Lost/damaged ticket → the lost-ticket path ([[parking-session]], [[tariff]] admin-arbitrary
|
||||
amount).
|
||||
|
||||
Reference in New Issue
Block a user