> ## 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 log

> Append-only finishes, edits, and status changes.

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.

## 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` |

Each event has a `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 `delete` event 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-participant `timingResult` 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 `elapsedMs` once the matching start lands. The row shows "awaiting start".
* **Duplicate finish from two devices**: keep both events; flag the result with both `clientEventId`s as candidates. A human resolves it in the review UI.
* **Self-clear in dual slalom**: a `lane_clear` event supersedes its referenced `lane_finish`; the lane goes back to "live".
* **Storage precision**: always 3 decimal places (ms); display rounds.
