34 lines
2.1 KiB
Markdown
34 lines
2.1 KiB
Markdown
# Issue #310 — Host transition idempotency and error catalog
|
|
|
|
## Scope
|
|
|
|
This artifact hardens the two host-owned scoreboard exits in the canonical gameplay flow:
|
|
|
|
- `POST /lobby/sessions/{code}/rounds/next`
|
|
- `POST /lobby/sessions/{code}/finish`
|
|
|
|
The goal is retry-safe host behavior when the scoreboard transition already succeeded server-side but the client retries because of a duplicate click, timeout, or lost response.
|
|
|
|
## Transition contract
|
|
|
|
| Endpoint | First valid transition | Idempotent replay state | Replay result | Broadcast behavior | Still-invalid states |
|
|
|---|---|---|---|---|---|
|
|
| `POST /lobby/sessions/{code}/rounds/next` | `scoreboard -> lie` | `lie` with persisted current-round bootstrap (`RoundConfig` + `RoundQuestion`) | `200 OK` with the same canonical next-round payload shape | `phase.lie_started` fires only on the first transition | `lobby`, `guess`, `reveal`, `finished` → `next_round_invalid_phase` |
|
|
| `POST /lobby/sessions/{code}/finish` | `scoreboard -> finished` | `finished` | `200 OK` with the same final leaderboard payload shape | `phase.game_over` fires only on the first transition | `lobby`, `lie`, `guess`, `reveal` → `finish_game_invalid_phase` |
|
|
|
|
## Error catalog notes
|
|
|
|
No new backend error codes were introduced for this slice.
|
|
|
|
The contract change is behavioral:
|
|
|
|
- `next_round_invalid_phase` now means the session is in a phase where the scoreboard → next-round transition has **not** already been completed, or the expected bootstrap artifact for the already-started round is missing.
|
|
- `finish_game_invalid_phase` now means the session is in a phase where the scoreboard → finish transition has **not** already been completed.
|
|
- Successful replays are returned as normal `200 OK` canonical responses instead of phase errors.
|
|
|
|
## Acceptance evidence
|
|
|
|
- Repeated `rounds/next` calls after a successful scoreboard exit return the same canonical lie/bootstrap payload without incrementing the round twice.
|
|
- Repeated `finish` calls after a successful scoreboard exit return the same finished leaderboard payload without rebroadcasting game-over.
|
|
- Wrong-phase calls outside those replay states still return the existing shared error codes.
|