Skip to content

Event log

The Event Log is a running history of operations on a rotation — who did what, and when. It's useful for answering "who added that override?" or "when was this rotation created?" without digging through Slack.

In the UI: open a rotation (/rotations/[id]) and click Event log. It links to /events?rotationId=<id> — a table, newest first, scoped to that rotation, showing the timestamp, the acting user's email, the action, and a one-line summary. There's no global, unfiltered view in the nav — events not tied to any rotation (engineer.created/updated/deleted, and all of the team.*/team-membership.updated actions, since a Team has no relation to any Rotation) aren't reachable from the UI, only via the API below.

What gets recorded

Every write action across the app records one entry:

ActionRecorded on
rotation.createdCreating a rotation
rotation.updatedEditing a rotation's name, cadence, anchor, timezone, or description
rotation.deletedDeleting a rotation
membership.updatedChanging a rotation's ordered on-call membership
engineer.createdAdding an engineer
engineer.updatedEditing an engineer
engineer.deletedDeleting an engineer
override.createdAdding an override
override.updatedEditing an override
override.deletedDeleting an override
swap.createdSwapping two engineers' shifts (one entry for the pair, not two)
team.createdCreating a team
team.updatedRenaming a team
team.deletedDeleting a team
team-membership.updatedChanging a team's roster

The acting user's email is always the identity recorded — the same user.email that authenticates the request, matching the convention already used for Override.createdByEmail.

Design note: it survives deletion

The Event model has no foreign key to Rotation/Engineer/Override — those all cascade-delete (deleting a rotation removes its overrides and memberships; deleting an engineer removes their memberships and the overrides they covered). If the event log had a real relation to them, deleting a rotation would silently erase its own history right when it matters most.

Instead, rotationId/rotationName on an Event are a denormalized snapshot taken at the time the event was recorded — they keep working as a label and a link even after the rotation is gone (rotationId is null for a rotation.deleted event itself, so there's nothing to link to).

Via the API

sh
curl http://localhost:3000/api/events \
  -H "Cookie: <your-session-cookie>"

Filter to one rotation's history:

sh
curl "http://localhost:3000/api/events?rotationId=<rotationId>" \
  -H "Cookie: <your-session-cookie>"

Read-only — see the API contract for the full shape. It's also readable by a service token, like the other read endpoints.