Capsule: match history
Use when changing match-history schema, persistence, the /api/matches endpoint, the recording
scope, or the lobby front-page table.
Read first
- docs/design/match-history.md — full design source of truth
Code seams
server/src/db.rs— pool, migrations,record_match,recent_matches,replay_artifact_for_match.server/src/main.rs— env loading,/api/matches,POST /api/matches/{id}/replay, replay compatibility checks,RTS_RECORD_MATCHESpublic/local scope.server/src/lobby/mod.rs—Lobby::with_match_history()injects pool/scope into rooms; replay launch creates spectator replay rooms.server/src/lobby/room_task.rs— capture metadata atstart_match, detached write atend_match.server/migrations/*.sql— versioned schema. Never hand-apply DDL.client/src/match_history.js— lobby table renderer and replay launch action.client/src/app.js— mounts/refreshes the table on lobby show / back-to-lobby; auto-joins?replayRoom=...launch pages.
Invariants
- Server is the only writer. Clients never write history.
/api/matchesis read-only. - Detached write at
end_match. A slow Supabase write must never stall the room. Errors log and are dropped. - Recording scope. Beta/mainline writes are enabled only when
RTS_RECORD_MATCHESis truthy. Deployed normal matches, including solo, player-vs-AI, and AI-only matches, get replay-backed rows unless they are dev/scenario/replay rooms or automated test fingerprints. Localcargo runwith the gate off can read history but does not upload rows or replay artifacts. - Recent Matches visibility.
/api/matchesreturns only rows withhuman_count >= 1anddebug_mode = false, so AI-only and lobby Debug/quickstart rows can be stored for replay launch without appearing in the lobby table. - Score-screen schema.
score_screenis JSONB holdingVec<PlayerScore>fromcontract::PlayerScore. Adding fields requires no migration. - Replay storage.
match_replays.artifact_jsonstoresReplayArtifactV1; summaries and launch check artifact schema, build SHA, map schema, and map hash before playback. - TLS to Supabase.
DATABASE_URLmust include?sslmode=require.
Cross-capsule triggers
- Changing
PlayerScore→ also update protocol.md and the score-screen renderer. - New deploy/env var → update deployment.md and
docs/fly.md. - Changing the lobby DOM around the history table → update client-ui.md.