Files
parking_solution/wiki/log.md
T
julian 77606da2c9 UHPPOTE hardware bring-up + entry-flow blocker
Brought up the real UHPPOTE controller (serial 225088491, fw 09120) end to end
and recorded a procurement-level blocker.

Verified on hardware:
- discovery (LAN scan), host-commanded openDoor on doors 1 & 2 (physically
  actuated; reason="remote open door"), and live button capture
  (reason="push button ok").

Driver/networking fixes (packages/devices/src/drivers/access-uhppote.ts):
- broadcast to subnet-directed address (lib doesn't enable SO_BROADCAST for the
  global 255.255.255.255 -> EACCES);
- Config broadcast must match the target's subnet for unicast reply routing
  (fixes the health-check timeout: 5s -> 24ms ready);
- discover across all local subnets, dedupe by serial;
- serialize all controller I/O (concurrent calls collided on UDP :60001).

Server/UX:
- load .env via node --env-file-if-exists (vars weren't being read before);
- SETUP_AUTH_BYPASS hardened: env-gated, dev + loopback only, fails closed
  otherwise; surfaced as catalog.authBypass so the wizard drops the token field;
- .env.example documents all vars; inline favicon stops a 404.
- apps/server/scripts/: uhppote-listen (live events, restores prior listener)
  and uhppote-relay (guarded door-open test).

BLOCKER (wiki/decisions/access-controller-button-flow.md): the controller's
push-button input auto-opens the relay in firmware with no report-without-open
mode, so ticket-first entry (button -> print -> open, fail-closed) is impossible
as wired. UHPPOTE can't do it on that input; ZKTeco *might* via a programmable
aux input + PULL SDK but that's unverified and needs a new driver. Entry-lane
hardware decision paused to focus on the business side.

wiki: access-controller-button-flow (blocker), zkteco-controller (stub +
assessment), uhppote-controller callout, index + log.
2026-06-14 10:29:43 +02:00

75 lines
4.7 KiB
Markdown

# Wiki Log
Append-only chronological record. Each entry: `## [YYYY-MM-DD] <op> | <subject>`.
Query with `grep "^## \[" log.md | tail -5`.
## [2026-06-14] ingest | Parking System — Architecture & Design Notes
First source ingested. Bootstrapped wiki scaffolding (CLAUDE.md schema, index.md,
overview.md, log.md). Created source summary, 14 entity pages, 9 concept pages, and
decision records (settled decisions + 6 open questions). Source is a dense design
doc covering stack, threat model, device architecture, UHPPOTE access control, the
custom ESP32 controller alternative, readers, and a reference BOM.
## [2026-06-15] decision | JWT key choice + ESP32 deferred
From app work, not a new source. Added [[open-questions]] #7 (symmetric vs.
asymmetric JWT signing key — raised by the commit security review; prefer RS256/EdDSA
so verifying hosts hold only a public key, mirroring the ATECC608 / challenge-response
property). Marked [[esp32-custom-controller]] `status: deferred` per decision not to
implement device-level auth for now (access control stays on UHPPOTE + network
isolation); noted in [[open-questions]] #6. Updated [[local-jwt-auth]] (hardened secret
handling + 8h expiry, asymmetric-key pointer) and the index.
## [2026-06-15] decision | Device-agnostic registry + first-run setup
From app work. Made the [[device-adapter-pattern]] selectable: added a
[[device-registry]] (catalog of drivers per category) and a [[first-run-setup]]
flow so the admin picks a device per lane at install. Categories: access
(ZKTeco / ESP32 relay), reader (Wiegand / TCP-IP), camera (Hikvision / Dahua,
snapshot-on-event), printer. Added a `CameraDevice` interface; new `lane_devices`
+ `setup_state` tables (migration 0001); admin-only setup endpoints. Stub drivers
for now (no real vendor protocols yet). Verified catalog + assign + validation +
auth end to end.
## [2026-06-15] decision | UHPPOTE library chosen + real driver
Researched Node options for the UHPPOTE controller. Chose the official
**`uhppoted`** npm package (MIT, actively maintained, full API incl. openDoor,
get-event(s)/event-index, set-listener, restore-default — covers the whole
[[event-log-ingestion]] design). Rejected: raw-dgram DIY (reinvents the lib),
node-red-contrib-uhppoted (wrong model), Go REST sidecar (extra runtime). Added
it to @parking/devices and implemented a real `uhppote` [[uhppote-controller]]
access driver (pulseOpen→openDoor, healthCheck→getStatus), registered in the
catalog. CJS interop: default-import + destructure. Verified it builds, appears
in the catalog, and degrades to "offline" gracefully without hardware. Real
on-VLAN test still pending.
## [2026-06-15] feature | Device discovery (UHPPOTE scan in setup)
The frontend had no way to find a UHPPOTE — but the controllers self-announce via
UDP broadcast. Added a generic [[device-discovery]] capability: optional
`DiscoverableDriver.discover()` on the registry, implemented by the `uhppote`
driver via `getDevices`. New admin-only `GET /api/setup/discover/:driverId`
(health-checks each found device); catalog now returns a `discoverable` list.
SetupWizard gains a "Scan for controllers" button that lists found devices with
health badges and auto-fills serial + host on selection. Verified: catalog flags
uhppote; discover runs and fails gracefully without hardware (broadcast EACCES);
non-discoverable driver → 400; no token → 401. Modeled generically so cameras
(ONVIF) can add discovery later.
## [2026-06-15] test+blocker | UHPPOTE hardware bring-up + entry-flow blocker
Brought up the real UHPPOTE (serial 225088491, fw 09120) end to end. Fixed the
networking path: WSL2 mirrored mode, then driver bugs — subnet-directed broadcast
(the lib doesn't enable SO_BROADCAST for global 255.255.255.255), broadcast must
match the target's subnet for unicast reply routing (health-check timeout fix),
multi-subnet discovery, and serialized I/O (concurrent calls collided on :60001).
Added .env loading (Node --env-file), env-gated+fail-closed SETUP_AUTH_BYPASS, and
an authBypass flag so the wizard drops the token field. Test scripts in
apps/server/scripts/ (uhppote-listen, uhppote-relay).
VERIFIED on hardware: discovery; host-commanded openDoor doors 1&2 (physical +
reason="remote open door"); button presses live (reason="push button ok").
BLOCKER FOUND: the controller push-button input auto-opens the relay in firmware —
no command to report-without-opening — so ticket-first entry (button→print→open)
is impossible as wired. UHPPOTE can't do it on that input; ZKTeco *might* via a
programmable aux input + PULL SDK but that's unverified and needs a new driver.
Recorded in [[access-controller-button-flow]] + [[zkteco-controller]]. Entry-lane
hardware decision paused to focus on the business side.