--- type: concept tags: [parking, architecture, devices, entry-flow] sources: [] updated: 2026-06-15 --- # Device Input Flow (button → backend → relay) How a physical button press drives the entry lane. The **backend is the source of truth**: the device only *reports* the press; the host decides and commands the relay. This is the host-in-the- loop flow the [[dingtian-relay]] makes possible (and the [[uhppote-controller]] could not). ## The path (no polling) ``` car arrives → driver presses button (input I_N, dry contact to GND) → device HTTP-pushes GET …/api/devices/dingtian//input//on → backend: emit internal device event (device-events bus) → backend entry flow: create + sign an entry event, print the ticket → backend: pulseOpen(N) over UDP → barrier opens → (on release) device pushes …/input//off ``` - **Push, not poll.** The device's `input_link_url` feature is configured (by the driver's `configureInputPush()`) to call the backend on each input edge — see [[dingtian-relay]]. The driver's poll path remains only as a dev/fallback aid. - **Per-input path** carries the input number in the URL (`…/input/3/on`), so routing needs no body parsing. Both edges (`on`/`off`) are sent. - **Internal event bus** (`device-events.ts`, a Node `EventEmitter`) decouples the HTTP/transport layer from business logic — drivers/pushes emit; the entry flow subscribes. Keeps the app [[device-adapter-pattern|device-agnostic]]. ## Trust model (important — flat network, no VLAN) The relay-control direction (host → device) is **unauthenticated UDP**, and the site is a **flat network with no VLAN** ([[network-isolation]] is not yet enforceable here). So we do **not** trust the device or the network. Instead: - **Every barrier open is a host decision, recorded as a signed event BEFORE the relay fires** ([[append-only-event-chain]]). If anyone opens the relay out-of-band (which the flat network allows), there is **no matching signed event → a detectable anomaly**. The anti-fraud guarantee is the **signed log**, not device/network auth. - The inbound push endpoint is intentionally **not behind the SPA's cookie/CSRF auth** (it's a machine call from the device). A **shared-secret / Basic-auth** on the push is available as defence-in-depth (the device supports it) — worth adding, but it is *not* the security boundary. - This sharpens under the [[autonomous-direction|unmanned]] roadmap: with no operator, tamper detection via the signed log matters more than perimeter auth. ## Status Input push **verified on hardware** (all 4 inputs, real presses reaching the backend). The entry flow itself (signed event + ticket print + `pulseOpen`) is the next build — see [[dingtian-relay]].