docs(wiki): record session findings — snapshot fix, booth rework, db reset
- entry-exit-points.md: the snapshot content-type bug + serve-side cleanType fix (Hikvision image/jpeg; charset="UTF-8" broke every legacy render). - booth-exit-flow.md: the Active-Sessions/modal rework — inline barrier button removed -> modal; closed-within-grace view; live grace countdown; actual paid amount; read-only snapshot review in the closed-session view. - local-dev-workflow.md: the gated `pnpm db:reset` training tool + flag table + the booth (docker exec, no pnpm) note. - appliance-provisioning.md: new §7d — reset on the booth via docker exec into the server container (script ships in the deploy bundle; DATABASE_URL= /data/parking.sqlite), ledger-truncation warning + the two safety gates. - index.md catalog line; log.md entries. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
type: concept
|
||||
tags: [parking, architecture, devices, setup]
|
||||
sources: []
|
||||
updated: 2026-06-16
|
||||
updated: 2026-06-30
|
||||
---
|
||||
|
||||
# Entry / Exit Points (pool-of-spaces model)
|
||||
@@ -114,6 +114,21 @@ re-encode is **storage-only** — ANPR recognition runs on the **original full-r
|
||||
(downscaling hurts OCR). Fail-soft: a re-encode error stores the original, never drops the snapshot
|
||||
(`snapshot.ts` `encodeForStorage`).
|
||||
|
||||
> **Content-type bug — every legacy snapshot rendered blank (fixed 2026-06-30).** Symptom: *no*
|
||||
> snapshot showed in the booth modal. Root cause: some cameras (Hikvision) return
|
||||
> `Content-Type: image/jpeg; charset="UTF-8"` — a charset param on a binary body is **malformed**, and
|
||||
> browsers refuse to decode an `<img>` declared that way. Old capture code persisted that raw header
|
||||
> into `snapshots.content_type` (100 of 101 rows in the dev DB), and the serve route
|
||||
> (`GET /api/snapshots/:id`) re-emitted it **verbatim** → broken render for every legacy row. The
|
||||
> capture path was *already* hardened (`encodeForStorage` re-encodes to a clean `image/jpeg`; its
|
||||
> fail-soft branch calls `cleanType` to strip `; charset=…`), so NEW rows were fine — but the serve
|
||||
> route trusted the stored value. Fix: the route now also runs `cleanType(row.contentType)` on the way
|
||||
> out (a bare `image/jpeg`), which un-breaks all legacy rows with **no data migration**. Verified: a
|
||||
> previously-unrenderable 2560×1440 row now decodes in-browser. Lesson: **normalize a camera-supplied
|
||||
> content-type both on capture AND on serve** — a stored value from an untrusted device is itself input.
|
||||
> The stored `content_type` column could be backfilled to `image/jpeg` for cleanliness, but serving
|
||||
> normalizes so it isn't required.
|
||||
|
||||
**Retention (2026-06-28, resolves the old open question) — DISK-PRESSURE safety valve.** Snapshots
|
||||
are unsigned/advisory, so they prune freely. The day-to-day shrink is the re-encode above; pruning is
|
||||
a backstop that only fires under real disk pressure. A **daily** check (`snapshot-retention.ts`
|
||||
|
||||
Reference in New Issue
Block a user