wiki: design the business layer (session, tariff, permit, vision, shift, ops)
Pivot from the hardware/integrity layer to the parking operation. All wiki-only; no code yet. Core principle throughout: business entities are projections over the signed append-only event log, never mutable tables. New concepts: parking-session, tariff (composable/versioned, FX-ready), shift (manned-only Z-report), capacity-occupancy, validation-discounts, reporting-analytics, clock-integrity, ticket-encoding, anti-passback. New entities: permit, opencv-anpr-service, blocklist. Decisions: session-model, vision-service (host-side ANPR + vehicle verification; scoped AGPL exception for the isolated service). Updates: append-only-event-chain (new event types + vision witness), local-jwt-auth (drop 8h expiry -> until logout; code change pending), lpr-camera (host-side recognition supersedes edge-AI), standing-decisions (AGPL exception), open-questions (+FX, +pay-station money corners, backup). Deferred + flagged: intercom/help-call, receipts/refunds/change, FX engine, lane topology (#1).
This commit is contained in:
@@ -13,7 +13,14 @@ Authentication and authorization, kept **fully local** — a direct consequence
|
||||
|
||||
- `@fastify/jwt` signs tokens with a **local secret** (symmetric HMAC). The server **refuses to
|
||||
start** without a strong `JWT_SECRET` (≥32 chars, no placeholder) — there is deliberately no
|
||||
insecure default — and mints tokens with an **8h expiry** (bound to a shift).
|
||||
insecure default.
|
||||
- **Session lifetime: valid until explicit logout — no time expiry** (decision 2026-06-15).
|
||||
Booth reality breaks any fixed clock: relief arrives late, fails to show, or one operator is
|
||||
forced to work two shifts in a row — a token that expired mid-duty would strand an active
|
||||
operator. So the login persists until logout; a **[[shift]] is a separate, explicit boundary**,
|
||||
not tied to token lifetime. (Superseded the earlier "8h expiry, bound to a shift" assumption.)
|
||||
> ⚠️ Code still mints an 8h-expiry token — this page records the decided design; the server
|
||||
> change (drop `expiresIn`, persist until logout) is pending.
|
||||
- A `users` table in [[sqlite]] holds **bcrypt** password hashes plus a **role** column. The
|
||||
first admin is seeded via `pnpm --filter @parking/server seed-admin` (no bootstrap endpoint).
|
||||
- Authorization = a simple `preHandler` role guard per route: **admin / operator / cashier /
|
||||
|
||||
Reference in New Issue
Block a user