fix(booth): backfill the live-feed plate + make plate search work

Two booth feed fixes:

- Plate not showing until refresh. Plate recognition is async/advisory
  (snapshot.ts recognizePlate → a kind:"read" device_event keyed by the session
  identity), so it lands AFTER the entry/exit event already shipped over the WS
  without a plate; a refresh re-fetched via the bulk enrich path and showed it.
  Added a `plate-recognized` bus event (device-events.ts) emitted when the read
  is written; ws.ts forwards it; the client patchPlate(identity, plate)
  (live-store) backfills the already-rendered feed row in place and invalidates
  the Query-owned active-sessions list. No refresh.

- Plate search didn't filter. Both the live-feed (BoothScreen) and active-sessions
  (ActiveSessions) search haystacks matched the wrong field — the displayed plate
  is the ENRICHED top-level e.plate/s.plate (set by enrichEvent), not payload.plate
  (the plate is unsigned, never in the signed payload). Switched the haystacks to
  the displayed field.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
2026-06-28 12:24:46 +02:00
parent 38481f105f
commit 6734e9815e
7 changed files with 61 additions and 7 deletions
+3 -2
View File
@@ -207,7 +207,8 @@ export function BoothScreen() {
// Apply the live-feed filters. Source maps to booth (operator-initiated `manual`)
// vs reader (device-initiated: wiegand/lpr/qr/ticket). Search spans identity,
// subscriber label, and any advisory plate on the payload.
// subscriber label, and the enriched advisory plate (`e.plate` — the displayed field;
// the plate is NOT in the signed payload, so `payload.plate` would never match).
const fq = feedSearch.trim().toLowerCase();
const events = scoped.filter((e) => {
if (feedType && feedCat(e.type) !== feedType) return false;
@@ -217,7 +218,7 @@ export function BoothScreen() {
if (feedSrc === "booth" ? !isBooth : isBooth) return false;
}
if (fq) {
const hay = `${e.identity ?? ""} ${e.subscriberLabel ?? ""} ${e.payload?.plate ?? ""}`.toLowerCase();
const hay = `${e.identity ?? ""} ${e.subscriberLabel ?? ""} ${e.plate ?? ""}`.toLowerCase();
if (!hay.includes(fq)) return false;
}
return true;