--- type: entity tags: [parking, stack, auth, offline-first] sources: [parking-system-architecture] updated: 2026-06-15 --- # Local JWT Auth Authentication and authorization, kept **fully local** — a direct consequence of [[offline-first]] (an air-gapped park cannot reach an external identity provider; see [[logto-zitadel-oidc]] for the rejected alternative). (See [[parking-system-architecture]] §2.) - `@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). - A `users` table in [[sqlite]] holds **bcrypt** password hashes plus a **role** column. - Authorization = a simple `preHandler` role guard per route: **admin / operator / cashier / readonly**. No Casbin or full RBAC engine needed at this scale. > **Open decision:** moving from the symmetric secret to an **asymmetric key (RS256/EdDSA)** so > verifying hosts hold only a public key — [[open-questions]] #7. Relevant before any > multi-host/multi-lane deployment. Part of the [[technology-stack]]. License: MIT.