Every action on a timing session — start, finish, edit, status change, finalize — is an entry in an append-only event log. Materialized results are derived from the log by a reducer that runs identically on client and server.Documentation Index
Fetch the complete documentation index at: https://docs.time2.bike/llms.txt
Use this file to discover all available pages before exploring further.
Event kinds
| Group | Kinds |
|---|---|
| Session lifecycle | session_open, finalize, publish |
| Race clock | race_start, race_pause, race_resume, race_stop |
| Standard finishes | finish, manual_time, note, status_change, delete |
| Splits & laps | lap, split, prime |
| Dual slalom lanes | lane_start, lane_finish, lane_clear, lane_assign, lane_unassign |
| External hardware | external_rfid |
| Brackets | bracket_init, bracket_rebuild, bracket_set_match_winner, bracket_reset_match, bracket_resolve, bracket_match_forfeit, bracket_swap_match_sides, bracket_set_match_participant, bracket_reseed, bracket_set_leg_time |
clientEventId (UUID), payload, localTimestamp, clockOffset, deviceId, userId, roleAtRecord, and a server-assigned seq.
Why append-only
- Audit: nothing is silently lost. Deleting a finish writes a
deleteevent referencing the original; the original stays. - Offline merge: two devices recording in parallel can post their events independently and the server can re-project the truth deterministically.
- Time travel: you can “replay to time T” for debugging without rolling back any data.
Materialized state
The reducer computes per-participanttimingResult rows: status, startAt, finishAt, elapsedMs, lane, run, and any flagged reasons (duplicate_finish, orphan_finish). The client computes its own projection from local + server events so the UI is correct even offline.
Conflict policy
- Finish before start arrives: accept the finish; reducer computes
elapsedMsonce the matching start lands. The row shows “awaiting start”. - Duplicate finish from two devices: keep both events; flag the result with both
clientEventIds as candidates. A human resolves it in the review UI. - Self-clear in dual slalom: a
lane_clearevent supersedes its referencedlane_finish; the lane goes back to “live”. - Storage precision: always 3 decimal places (ms); display rounds.