1efa77bf56
A parking lot is one pool of spaces with a flexible set of entry/exit
points — no "lane". Direction is a property of each RELAY inside an access
controller; readers/cameras bind to a controller relay and inherit it.
Schema:
- drop `lane` from ledger_events, device_events, sessions
- rename lane_devices -> devices (no lane/direction columns)
- access config.relays=[{relay,direction,button?}]; reader/camera
config.controllerId+relay binding
- fresh 0000_baseline migration (history reset; dev data was throwaway)
Signed ledger:
- remove `lane` from canonicalize(); bump signer keyId sw-hmac-v1 -> v2
(v1 events won't verify under v2 — intentional, gated per-event by keyId)
Server:
- new device-resolve.ts (replaces lane-map.ts): relayForButton,
relayForDevice, firstRelayByDirection, devicesByDirection
- entry-flow: button terminal -> its relay; exit/permit: reader's bound
relay; dispatcher resolves the bound relay + inherited direction
- camera snapshots fire by direction site-wide, async, never block open
- DeviceConfig widened to nested JSON for relays[]
Web:
- wizard: no lane selector; add controllers (relay map + entry-button
terminal) first, then bind readers/cameras/printers to a controller relay
Wiki: new entry-exit-points.md (replaces lane-direction); reworked
entry-exit-readers, parking-session, first-run-setup, device-registry,
append-only-event-chain, device-events; removed stale lane/LaneMap mentions.
65 lines
4.6 KiB
Markdown
65 lines
4.6 KiB
Markdown
---
|
||
type: decision
|
||
tags: [parking, decisions, open]
|
||
sources: [parking-system-architecture]
|
||
updated: 2026-06-15
|
||
status: open
|
||
---
|
||
|
||
# Open Questions / Next Steps
|
||
|
||
**Not yet decided**, and they drive everything else — settle before procurement. (See
|
||
[[parking-system-architecture]] §10.)
|
||
|
||
1. **Lane topology.** One host per lane, or one central host driving networked devices in each
|
||
lane? Decides how many controllers, printers, UPSs, and [[sqlite]] instances exist, and the
|
||
failure blast radius. (A single central host is a single point of failure for *all* lanes.)
|
||
2. **Failure modes.** Define per direction what happens to barriers on host/power/network loss —
|
||
particularly **fail-open on exit** for egress safety. Currently unaddressed. See
|
||
[[fail-state-safety]].
|
||
3. **Payment subsystem.** Manned booth (P2PE terminal + cash drawer) vs unmanned pay station;
|
||
confirm **PCI scope is kept out of the application** via a standalone certified terminal
|
||
(see [[bom]]).
|
||
4. **Reconciliation channel.** Even if "offline," establish *some* periodic path (USB, hotspot,
|
||
manager visit) to reconcile the signed log against an external authority — the real anti-fraud
|
||
control. See [[reconciliation]].
|
||
5. **Durability / backup.** Backup strategy for the [[sqlite]] database + recovery plan; "sync
|
||
later" currently leaves a disk failure as **total revenue-history loss**. _(Confirmed in-scope
|
||
to design, 2026-06-15.)_ Because the DB is the signed [[append-only-event-chain]], a backup must
|
||
preserve the chain intact (a restored copy must still `verifyChain`); options include SQLite
|
||
WAL/online-backup snapshots to a second disk/USB + the periodic external export that doubles as
|
||
the [[reconciliation]] channel (#4). Encryption at rest already applies ([[disk-os-hardening]]).
|
||
Design TBD.
|
||
6. **Secure-element integration.** Confirm [[atecc608]] wiring/usage on the host (event
|
||
signing). The [[esp32-custom-controller]] command-authentication use is **deferred — not
|
||
being implemented for now** (access control is the [[dingtian-relay]] behind
|
||
[[network-isolation]]); revisit only if prevention-grade device auth becomes a requirement.
|
||
7. **JWT signing: symmetric vs. asymmetric key.** _(Raised by the commit security review, not the
|
||
source doc.)_ Auth currently uses a symmetric HMAC secret (`@fastify/jwt`, see
|
||
[[local-jwt-auth]]) — the same secret signs *and* verifies, so it must live on every host that
|
||
validates tokens. Consider rotating to an **asymmetric key (RS256 / EdDSA)** so the server
|
||
holds only the **public key** to verify; the private signing key can then live in the
|
||
[[atecc608]] or a key-management step. This mirrors the "store only the public key" property
|
||
already used for [[atecc608]] event signing and the [[challenge-response-auth]] scheme —
|
||
compromising a verifying host yields nothing that can forge a token. Decide before
|
||
multi-host / multi-lane deployment (see #1 lane topology), since that's when shared-secret
|
||
distribution becomes the liability.
|
||
8. **Exchange-rate (FX) system.** _(Raised by the [[tariff]] design, 2026-06-15.)_ Currency is
|
||
selectable per tariff version and the money model is FX-ready (`payment` stores currency + a
|
||
reserved `fxRate`), but **no conversion is built**. If multi-currency pricing/charging is ever
|
||
needed, it requires an **offline** rate source (rates can't depend on the network —
|
||
[[offline-first]]), a base currency, and a rounding policy. Deferred; nothing blocks adding it
|
||
later without migrating stored amounts.
|
||
9. **Pay-station money corners — receipts & refunds/change.** _(Raised by the scope sweep,
|
||
2026-06-15; deferred until pay-station hardware is chosen.)_ Not yet designed: **receipts / VAT
|
||
invoices** (fiscal receipt with tax number + sequential numbering may be legally required — could
|
||
change what the `payment` event must store) and **refunds / overpayment / change** (cash change,
|
||
"exact change only", a refund as a signed reversal event). Both depend on the unmanned-vs-manned
|
||
payment subsystem (#3) and the note/coin/card acceptor hardware. Revisit at procurement.
|
||
10. **Snapshot retention.** _(Raised by the [[entry-exit-points]] camera-snapshot build, 2026-06-16.)_
|
||
Entry/exit snapshots are stored as BLOBs in the [[sqlite]] `snapshots` table. This grows the
|
||
single DB file fast (~100–300 KB per image × every entry **and** exit), and SQLite doesn't
|
||
reclaim deleted-blob pages without `VACUUM`. **Undecided:** pruning policy (age-based vs.
|
||
total-size cap), VACUUM cadence, and how this interacts with the #5 backup strategy (blobs
|
||
bloat every backup). Until decided, snapshots accumulate unbounded. See [[entry-exit-points]].
|