ecaaefd899
Rework the ANPR trigger to the real design: when a transient presses the button or a
subscriber passes QR/RFID, the entry/exit fires and takes its evidence snapshot — that
is the moment to recognize. snapshotAsync now takes the VisionClient and, after storing
each snapshot from an opt-in (config.anpr) camera, runs ANPR on the SAME image and
records the plate against the SAME session identity (device_events kind:"read" with
plate/confidence/region/snapshotId/source:"entry-exit-snapshot"). One image serves both
evidence and plate extraction; recognition fires only on a real entry/exit — no polling.
The entry/exit/subscription flows take an optional VisionClient and pass it through;
server.ts wires it. Removed the polling VisionReader and VISION_POLL_MS/VISION_DEDUPE_MS.
Advisory + fire-and-forget: a low-confidence/no-plate result records nothing, a vision
failure never delays or changes the open, and the plate does not feed the access
decision. Verified e2e: a simulated entry snapshot on an anpr camera (live fast_alpr)
stored the snapshot for the session and recorded {identity, plate:AA558EE, 0.999,
region:Albania, snapshotId}. Build + lint green.
Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
43 lines
2.2 KiB
Bash
43 lines
2.2 KiB
Bash
# Copy this file to `.env` (same folder: apps/server/.env) and fill it in.
|
|
# The dev/start scripts load it automatically via Node's --env-file-if-exists.
|
|
#
|
|
# cp apps/server/.env.example apps/server/.env
|
|
#
|
|
# Required ----------------------------------------------------------------
|
|
# The server refuses to start without a strong JWT_SECRET (>=32 chars).
|
|
# Generate one with: openssl rand -hex 32
|
|
JWT_SECRET=
|
|
|
|
# Dedicated HMAC key for signing the append-only event ledger (>=16 chars).
|
|
# Generate with: openssl rand -hex 32
|
|
# If unset, the server falls back to JWT_SECRET (logged as a warning) — fine for
|
|
# dev, but set a dedicated key before production. Events store the key that signed
|
|
# them (keyId), so verifyChain still validates a chain that spans a key change.
|
|
EVENT_SIGNING_KEY=
|
|
|
|
# Optional ----------------------------------------------------------------
|
|
# PORT=3000
|
|
# HOST=0.0.0.0 # interface to bind. 127.0.0.1 = loopback only.
|
|
# LOG_LEVEL=info
|
|
# DATABASE_URL=./parking.sqlite
|
|
# NODE_ENV=production # set in prod: makes auth cookies Secure (HTTPS-only)
|
|
|
|
# First admin (seed once): pnpm --filter @parking/server seed-admin
|
|
# ADMIN_USER=admin
|
|
# ADMIN_PASS=
|
|
|
|
# Comma-separated extra origins allowed to open the booth WebSocket (/api/ws).
|
|
# In dev, set the Vite SPA origin. Same-origin is always allowed without this.
|
|
WS_ALLOWED_ORIGINS=http://localhost:5173
|
|
|
|
# Vision / ANPR (optional) -------------------------------------------------
|
|
# OFF by default. The Node SERVER's view of the vision microservice (apps/vision),
|
|
# which runs as a separate process with its OWN apps/vision/.env. Both sides share the
|
|
# VISION_ prefix but are different processes — keep the two .env files separate.
|
|
# See wiki/entities/opencv-anpr-service.md "Configuration".
|
|
# ANPR rides the entry/exit snapshot (button / QR / RFID triggers it) — no polling.
|
|
# VISION_ENABLED=1 # master switch — nothing runs without it
|
|
# VISION_URL=http://127.0.0.1:8089 # must match apps/vision VISION_HOST:VISION_PORT
|
|
# VISION_TIMEOUT_MS=1500 # per-request cap so a slow call can't hang the lane
|
|
# VISION_MIN_CONFIDENCE=0.5 # confidence floor; keep in sync with the service
|