Turborepo (pnpm workspaces) with all dependencies pinned to latest mutually-compatible versions: turbo 2.9, TypeScript 6, Fastify 5, React 19, Vite 8, better-sqlite3 12 + Drizzle ORM 0.45. Layout: - apps/server Fastify backend (local JWT auth + role guard, /health) - apps/web React 19 + Vite 8 operator SPA - packages/db Drizzle schema on SQLite/WAL; append-only events + users - packages/devices reader/printer/relay adapter interfaces (intent-only relay) - packages/shared shared domain types Architecture constraints from the design wiki are encoded in the scaffold: append-only hash-chained + signed event log, device-agnostic adapters, "a barrier is not a door" (relay expresses intent only), fully-local offline-first auth. wiki/ is an LLM-maintained Obsidian knowledge base (28 pages) ingested from the architecture & design notes, with its own maintenance schema. Verified: pnpm install, full turbo build (5/5), server boots and serves /health, drizzle-kit generates the initial migration.
1.7 KiB
type, tags, sources, updated
| type | tags | sources | updated | |||||
|---|---|---|---|---|---|---|---|---|
| concept |
|
|
2026-06-14 |
UHPPOTE UDP Protocol (the weakness)
The uhppote-controller communicates over UDP port 60000 with no authentication and no encryption. Anyone who can place a packet on that LAN can send an "open" command to any door. This is the security issue — not safety (safety is the barrier operator's, per barrier-not-a-door). (See parking-system-architecture §6.)
Mitigation: network-isolation is mandatory. The security boundary is the network because it cannot be the device.
Why you can't fix it in firmware
The open-source uhppoted ecosystem is protocol reverse-engineering only — clients speaking
the existing UDP protocol. No source, SDK, schematic, or toolchain to build/flash custom
firmware. The controller accepts only the manufacturer's official firmware images. You
cannot configure or patch your way to authentication on this hardware.
Unauthenticated commands that undermine the log
The record-level log is append-only, but these don't touch individual records:
| Vector | Command | Effect |
|---|---|---|
| Blinding | record-special-events false |
Stops logging door events going forward |
| Wipe | restore-default-parameters |
Factory reset — clears config + event state |
| Rollover | (generate events / fall behind) | Finite circular buffer; old events overwritten |
| Time skew | set-time |
Corrupts / backdates timestamps |
| Index desync | set-event-index |
Moves the retrieval pointer; naive ingestion skips events |
The defensive response is event-log-ingestion. The preventive alternative is the esp32-custom-controller.