wiki: record JWT key open question; defer ESP32 controller

- open-questions #7: symmetric vs. asymmetric JWT signing key (from the
  commit security review). Prefer RS256/EdDSA so verifying hosts hold only a
  public key — mirrors the ATECC608 / challenge-response "public key only"
  property. Decide before multi-host/multi-lane deployment.
- Mark esp32-custom-controller status: deferred per decision not to build
  device-level auth now; access control stays on UHPPOTE + network isolation
  (noted in open-questions #6).
- local-jwt-auth: document hardened secret handling + 8h expiry and the
  asymmetric-key pointer.
- Update index.md and append a log.md entry.
This commit is contained in:
2026-06-14 07:45:14 +02:00
parent 94dd3fcff4
commit 7de5c74500
5 changed files with 40 additions and 8 deletions
+15 -4
View File
@@ -2,7 +2,7 @@
type: decision
tags: [parking, decisions, open]
sources: [parking-system-architecture]
updated: 2026-06-14
updated: 2026-06-15
status: open
---
@@ -25,6 +25,17 @@ status: open
control. See [[reconciliation]].
5. **Durability / backup.** Backup strategy for the [[sqlite]] database + recovery plan; "sync
later" currently leaves a disk failure as **total revenue-history loss**.
6. **Secure-element integration.** Confirm [[atecc608]] wiring/usage on both the host (event
signing) and, if pursued, the custom controller (command authentication — see
[[esp32-custom-controller]]).
6. **Secure-element integration.** Confirm [[atecc608]] wiring/usage on the host (event
signing). The [[esp32-custom-controller]] command-authentication use is **deferred — not
being implemented for now** (access control stays on the [[uhppote-controller]] behind
[[network-isolation]]); revisit only if prevention-grade device auth becomes a requirement.
7. **JWT signing: symmetric vs. asymmetric key.** _(Raised by the commit security review, not the
source doc.)_ Auth currently uses a symmetric HMAC secret (`@fastify/jwt`, see
[[local-jwt-auth]]) — the same secret signs *and* verifies, so it must live on every host that
validates tokens. Consider rotating to an **asymmetric key (RS256 / EdDSA)** so the server
holds only the **public key** to verify; the private signing key can then live in the
[[atecc608]] or a key-management step. This mirrors the "store only the public key" property
already used for [[atecc608]] event signing and the [[challenge-response-auth]] scheme —
compromising a verifying host yields nothing that can forge a token. Decide before
multi-host / multi-lane deployment (see #1 lane topology), since that's when shared-secret
distribution becomes the liability.
+7 -1
View File
@@ -2,11 +2,17 @@
type: entity
tags: [parking, hardware, access-control, upgrade-path]
sources: [parking-system-architecture]
updated: 2026-06-14
updated: 2026-06-15
status: deferred
---
# Custom ESP32 Controller (prevention alternative)
> **Status: deferred — not being implemented for now.** Access control stays on the
> [[uhppote-controller]] behind [[network-isolation]] (tamper-*evident*). This page is kept as
> the documented upgrade path; revisit only if prevention-grade device authentication becomes a
> requirement. See [[open-questions]] #6.
A small custom controller for **device-level authentication** — a control path that holds even
against an attacker on the wire. The prevention-grade upgrade from the [[uhppote-controller]]
(which is only tamper-*evident*). It moves the [[trust-boundary]] to the device. (See
+8 -2
View File
@@ -2,7 +2,7 @@
type: entity
tags: [parking, stack, auth, offline-first]
sources: [parking-system-architecture]
updated: 2026-06-14
updated: 2026-06-15
---
# Local JWT Auth
@@ -11,9 +11,15 @@ Authentication and authorization, kept **fully local** — a direct consequence
[[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**.
- `@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.
+1 -1
View File
@@ -64,4 +64,4 @@ Counts: 1 source · 14 entities · 10 concepts · 2 decision records.
## Decisions
- [[standing-decisions]] — settled decisions (stack, platform, integrity, access control, readers).
- [[open-questions]] — 6 unsettled items that drive procurement.
- [[open-questions]] — 7 open items (6 procurement + JWT key choice); ESP32 device auth deferred.
+9
View File
@@ -9,3 +9,12 @@ overview.md, log.md). Created source summary, 14 entity pages, 9 concept pages,
decision records (settled decisions + 6 open questions). Source is a dense design
doc covering stack, threat model, device architecture, UHPPOTE access control, the
custom ESP32 controller alternative, readers, and a reference BOM.
## [2026-06-15] decision | JWT key choice + ESP32 deferred
From app work, not a new source. Added [[open-questions]] #7 (symmetric vs.
asymmetric JWT signing key — raised by the commit security review; prefer RS256/EdDSA
so verifying hosts hold only a public key, mirroring the ATECC608 / challenge-response
property). Marked [[esp32-custom-controller]] `status: deferred` per decision not to
implement device-level auth for now (access control stays on UHPPOTE + network
isolation); noted in [[open-questions]] #6. Updated [[local-jwt-auth]] (hardened secret
handling + 8h expiry, asymmetric-key pointer) and the index.