docs(wiki): activity-log explainability, dates/i18n, KP-300H barcode fix
Record this session's work across the affected pages + three log entries. - ticket-encoding: id 13→11 digits (guess-resistance rationale, legacy-safe validation) + a barcode-geometry rule (symbol dots must fit the narrowest deployed printer's line — the KP-300H 72mm overflow). - rongta-printer: KP-300H raster-garbage root cause (line overflow, not corruption), sendRaw graceful-close fix, Albanian human dates (formatStampSq). - i18n: localized ledger reason codes, relative/human dates + the "browser ICU lacks Albanian" gotcha, toggle stale-router-context fix. - shift: Albanian Z-report, shift-history UI + permission scoping. - booth-console: explainable activity log (inline reasons/badges, event-detail modal with snapshots + audit disclosure, subscriber names, failed-snapshot tiles). - index/log updated; all added wikilinks resolve. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
type: concept
|
||||
tags: [parking, frontend, booth, realtime, ui]
|
||||
sources: []
|
||||
updated: 2026-06-18
|
||||
updated: 2026-06-19
|
||||
status: open
|
||||
---
|
||||
|
||||
@@ -68,6 +68,29 @@ a right column with the **live event ticker**. Submitting/clicking a ticket open
|
||||
modal** (entry/duration/total, tender, voucher checkbox, entry/exit snapshots). All live-refreshed via
|
||||
the WS.
|
||||
|
||||
### Explainable activity log (2026-06-19)
|
||||
The ticker used to flag an **anomaly** with no explanation — a red row with just an id, "nobody knows
|
||||
what happened." Now every event is **self-describing and clickable**:
|
||||
- **Inline reason + badges.** Each row surfaces the localized reason (from the signed `reasonCode` —
|
||||
see [[i18n]]) and computed classification badges (entry/exit-refused, lot-full, barrier-failed,
|
||||
manual-open…). Anomalies always show a reason line (or "no reason recorded") so a red flag is never
|
||||
silent.
|
||||
- **Clickable → event-detail modal.** A read-only modal with humanized labelled fields (not raw JSON),
|
||||
the session's **entry/exit snapshots**, and the **signed-chain provenance** (signature / keyId /
|
||||
prevHash) collapsed behind an "audit data" disclosure — operator sees the story, an auditor expands
|
||||
for the crypto. *Why show signatures at all:* makes the [[append-only-event-chain|tamper-evidence]]
|
||||
visible against the [[threat-model|booth-operator]] threat, and survives a signer swap (`keyId`).
|
||||
- **Subscriber names, not opaque keys.** A [[subscription]] occurrence's `SUBSESS-…` id now renders as
|
||||
the holder's name ("Aqif Kopertoni", fallback "Abonent"/"Subscriber"). Resolved **read-time
|
||||
server-side** (events API + WS push attach a non-signed `subscriberLabel` from `permitId →
|
||||
holder_name`; cached, invalidated on subscription edit/delete) so it needs no extra client
|
||||
permission and the signed event stays minimal.
|
||||
- **Failed-snapshot visibility.** A camera that was *attempted but unreachable* now shows a "⚠ camera
|
||||
unreachable" tile (from snapshot [[device-events|telemetry]]) instead of a silent gap — so the
|
||||
operator can tell "no camera" from "camera failed". (Surfaced a real incident: a subscriber's entry
|
||||
snapshot failed `EHOSTUNREACH` while the exit one succeeded — by design a snapshot is *evidence, not
|
||||
a gate*, so the open proceeded and only the image was missing.)
|
||||
|
||||
## The shift control (header) + the booth gate
|
||||
|
||||
The header carries a single **shift button** that expresses the [[shift|site-wide single-open
|
||||
|
||||
Reference in New Issue
Block a user