Skip to content

Post-v1: full-audit data model — detections, pass provenance, actor/when, config changes, commit grouping #353

Description

@ryan-johnson2

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_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

Gaps to close for FULL audit

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.

Related: #352 (Audit page), #44 (auth), D16 (plugin).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions