Files
parking_solution/wiki/decisions/open-questions.md
T
julian 1efa77bf56 devices: pool-of-spaces model — drop lane, per-relay direction
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.
2026-06-16 20:29:38 +02:00

4.6 KiB
Raw Blame History

type, tags, sources, updated, status
type tags sources updated status
decision
parking
decisions
open
parking-system-architecture
2026-06-15 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.