You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A truly complete audit should contain: enter detections from the timer, exit detections from the timer, laps from the timer, laps from timer catch-up (RH current_laps reconciliation at minimum), and every RD modification to any of the above. This issue is the research + gap inventory; deliberately out of scope for the v1 release.
What the event log (our audit substrate) has TODAY
Raw Pass events — lap-gate detections (optional SignalContext.rssi_peak).
Signal evidence — SignalThresholds (the enter/exit levels the timer detected against, per node) + SignalChunk/SignalHistory (the RSSI traces the marshaling graph and re-detection run over).
Enter/exit detections from the timer are not captured. We record the levels and the trace, but not the timer's actual crossing-enter / crossing-exit trigger instants. Needs a plugin emit (RH crossing callbacks) → a new canonical fact (e.g. GateCrossing { phase: Enter|Exit, at, node }). Approximate reconstruction from trace+thresholds exists (redetect.ts) but is not the timer's own record.
Pass provenance is invisible. A live-streamed pass and a catch-up pass (recovered from RH's authoritative current_laps at race end) fold to identical Pass events. Additive origin on Pass (live | snapshot-reconciliation | sim) — confirmed 2026-07-03 that NO adapter emits LapInserted; all insertions are RD actions, so provenance is purely a Pass-level concern.
Rulings carry no WHO and no WHEN. Actor identity needs the auth work (Protocol: auth & authorization [BE] #44) — single-RD today, but multi-console/read-only tiers make this real. And recorded_at is not stamped on control-path appends (only heat transitions get it — found while building Event-wide searchable Audit page; Marshaling keeps a compact strip #352's contract test), so a ruling's wall-clock time is unrecoverable. The WHEN fix is small and could even precede the rest.
Re-detection commits are unbundled. One commit lands as N independent rulings; the audit can't show 'one re-detection at enter=X/exit=Y produced these +A/−R'. A grouping fact (e.g. RedetectionCommitted { enter, exit, refs }) or a shared batch id would let the Audit page render commits as one entry with children.
Config/meta changes never reach the log. Round create/edit/delete (win condition changes rescore!), roster/membership/class/timer changes all live in EventMeta persistence — invisible to audit. Defensible results arguably requires 'the round's win condition was edited at T' in the trail.
Transition cause is ambiguous. Auto (runtime clock), manual override (SkipCountdown/ForceEnd), and auto-official finalize all log the same HeatStateChanged shapes.
Suggested sequencing (post-v1)
(3-when) recorded_at on control appends → (2) Pass origin → (4) commit grouping → (5) meta-change events → (1) GateCrossing via plugin → (3-who) actor identity after #44. Each additive/back-compat.
Vision (user, 2026-07-03)
A truly complete audit should contain: enter detections from the timer, exit detections from the timer, laps from the timer, laps from timer catch-up (RH
current_lapsreconciliation at minimum), and every RD modification to any of the above. This issue is the research + gap inventory; deliberately out of scope for the v1 release.What the event log (our audit substrate) has TODAY
Passevents — lap-gate detections (optionalSignalContext.rssi_peak).SignalThresholds(the enter/exit levels the timer detected against, per node) +SignalChunk/SignalHistory(the RSSI traces the marshaling graph and re-detection run over).HeatScheduled(lineup/class/round/frequencies), everyHeatStateChangedtransition,HeatStarting,CurrentHeatSelected,RoundFieldDrawn(frozen seeding draws, Seeding re-resolves live: adjudicating a source round after a dependent round ran silently rewrites the dependent field #334).Gaps to close for FULL audit
GateCrossing { phase: Enter|Exit, at, node }). Approximate reconstruction from trace+thresholds exists (redetect.ts) but is not the timer's own record.current_lapsat race end) fold to identicalPassevents. AdditiveoriginonPass(live | snapshot-reconciliation | sim) — confirmed 2026-07-03 that NO adapter emitsLapInserted; all insertions are RD actions, so provenance is purely aPass-level concern.recorded_atis not stamped on control-path appends (only heat transitions get it — found while building Event-wide searchable Audit page; Marshaling keeps a compact strip #352's contract test), so a ruling's wall-clock time is unrecoverable. The WHEN fix is small and could even precede the rest.RedetectionCommitted { enter, exit, refs }) or a shared batch id would let the Audit page render commits as one entry with children.HeatStateChangedshapes.Suggested sequencing (post-v1)
(3-when) recorded_at on control appends → (2) Pass origin → (4) commit grouping → (5) meta-change events → (1) GateCrossing via plugin → (3-who) actor identity after #44. Each additive/back-compat.
Related: #352 (Audit page), #44 (auth), D16 (plugin).