The plies, and how long each one took

FeatureMediaService
Shipped
September 8, 2026 at 6:44 PM UTC
Author
Kamo
Commit
7825d6c

Two things the move panel needs, neither of them on the published frame. `GET /games/{id}/moves` hands over every ply in order. It is a separate read rather than a field on `ChessGameView` on purpose: the move list and the per-ply positions used to ride on every publish, several kilobytes per recipient per move, for a panel nothing rendered. They came off the frame and they stay off it — the window fetches this when it opens and when the game ends, and appends each live move from `lastMoveSan` in between. Authorized by handing the id to the same `require(...)` the board itself uses, because an endpoint that hands over the whole course of a game must refuse exactly the people the board refuses. `THINKING_MS` has existed since the table did and nothing ever wrote it, so every row in the database carries a null and the panel had a time field it could never fill. `applyMove` is the one place the answer is knowable: the position last changed when the previous ply was written, or when the game was created if this is the first move. Not `dateUpdated`, which looks like the same fact and is not — `@PreUpdate` stamps it on every save, so a draw offer or an opponent opening the board would reset it and the next move would report a think time of a few seconds. Recorded, not enforced. There is still deliberately no clock.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing