Files
parking_solution/wiki/concepts/setup-relay-test.md
T
julian 35e593ab63 docs(wiki): DT-008 phantom-scan diagnosis + backfill bypass/relay-test concept pages
Two independent wiki updates bundled (all docs):

1. dingtian-dt008-reader.md: phantom optical decodes on the park-buzi EXIT
   reader (empty pre-opening site, low-sun afternoons). Chain of evidence:
   READ log lines carry the reader's own serial (H05MA5B0) → physical device,
   not a network source; snapshot shows nobody present; code shapes are the
   giveaway (6-digit numerics = checksum-less Interleaved 2-of-5, lone "C" =
   Code39/Codabar artifact) → 1D engine decoding sun-made stripe patterns
   (striped arm, fence shadows, glare). No fraud exposure (11-digit Luhn ids
   can't match); noise only. Fix on the entity page: vendor-tool symbology cut
   to QR+Code128 + min decode length, BOTH readers; config lives ON the device
   → re-apply after any factory reset/swap. Deliberately NOT filtering
   impossible codes server-side — probe recording is the anomaly path's job.

2. Backfilled two shipped-but-undocumented features (six code files already
   linked the first page as if it existed):
   - concepts/entry-presence-bypass.md — admin drops a FAULTY presence signal
     (granular radar/camera by decision, not a master switch); every flip is a
     signed config_change; persists till off; tickets stamped presenceBypassed;
     radar-bypass cooldown tradeoff; "the admin is not the adversary, but
     trusted never means invisible".
   - concepts/setup-relay-test.md — admin-only commissioning pulse, signed
     barrier_open_command BEFORE the fire so a test open never reads as the
     out-of-band-open fraud signal; saved controllers/declared relays only;
     radarAlert lamps excluded; pulseOpen only.
   Cross-linked from operator-issued-entry.md, cataloged in index.md, logged.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
2026-07-04 19:00:49 +02:00

2.5 KiB

type, tags, sources, updated, status
type tags sources updated status
concept
parking
setup
devices
integrity
admin
2026-07-04 settled

Setup relay test (signed, admin-only barrier pulse)

Commissioning a lane needs a way to prove wiring: does relay N on this controller actually lift this barrier? Before this feature (built 2026-07-01) the only way was to fake a credential or short an input — both of which pollute the flows they exercise. Now the Setup controller section offers a per-relay Test button that pulses the relay directly.

The design constraint: a test open must be SIGNED

The core anti-fraud rule (append-only-event-chain) is that a physical barrier open with no matching signed command is THE fraud signal. An unsigned test pulse would therefore read as fraud in any reconciliation of controller logs vs. ledger. So the test signs a barrier_open_command BEFORE the pulse fires — same ordering invariant as every real open:

  • source: "manual" (a deliberate human action, same as an operator barrier open), identity: relay-test:<controllerId>:<relay>,
  • payload: reasonPayload("setup.relayTest", { operator, relay, controller }) + relayTest: true so reconciliation and the feed can tell a test from an intervention.
  • No EventLog available (boot ordering) → the endpoint refuses (503) rather than fire unsigned.

Guardrails

  • Admin-only (site:update) + CSRF — the operator (the threat-model adversary) cannot pulse barriers from Setup.
  • Saved controllers only, and only relays the saved config declares (unknown relay → 400, unknown controller → 404, nothing signed on any refusal). No free-form "pulse anything" seam.
  • radarAlert (lamp) relays are excluded in the UI — they are aux outputs, not barriers (button-light-indicator); the test drives pulseOpen only, so barrier-not-a-door holds (intent-only; the barrier firmware owns the close).
  • UI confirms before firing (Test → confirm dialog → pulse), per-relay buttons in the controller assignment row.

As-built

  • Endpoint POST /api/setup/test-relay (routes/setup.ts) — validates, signs, then registry.create(...) → pulseOpen(relay). Feature-detects pulseOpen on the built device.
  • UI: RelayTester in SetupWizard.tsx (access category only). Reason code setup.relayTest in @parking/shared + both web catalogs (i18n).
  • Tests: setup-relay-test.test.ts — RBAC 403, CSRF 403, signed command on success, 400/404 refusals sign nothing, bad relay value.