183 lines
3.6 KiB
Markdown
183 lines
3.6 KiB
Markdown
# API Changes (Not Yet Reflected in `backend/openapi/openapi.json`)
|
|
|
|
This document lists additive API changes currently implemented in the Go backend.
|
|
|
|
## Summary
|
|
|
|
Existing endpoints remain compatible.
|
|
|
|
Added capabilities:
|
|
|
|
1. Position board persistence for live/admin ordering.
|
|
2. Stage session control (`start`/`end`) for event flow.
|
|
3. Stage history retrieval.
|
|
4. New state fields (`positionBoards`, `current_stage`, `last_stage`).
|
|
|
|
## 1) Position Board Endpoint
|
|
|
|
- Method: `PUT`
|
|
- Path: `/api/admin/positions/:board`
|
|
- Auth: admin bearer token (`Authorization: Bearer <token>`)
|
|
|
|
### Supported `:board` values
|
|
|
|
- `preliminary`
|
|
- `final`
|
|
- `prelim_tiebreak`
|
|
- `final_tiebreak`
|
|
|
|
### Request body
|
|
|
|
```json
|
|
{
|
|
"slots": [
|
|
{ "playerId": 12, "groupKey": "A", "position": 1 },
|
|
{ "playerId": 15, "groupKey": "A", "position": 2 },
|
|
{ "playerId": 20, "groupKey": "B", "position": 1 }
|
|
]
|
|
}
|
|
```
|
|
|
|
Fields:
|
|
|
|
- `playerId` (integer, required)
|
|
- `groupKey` (string, required)
|
|
- `position` (integer > 0, required)
|
|
|
|
Notes:
|
|
|
|
- The request replaces all saved slots for the target board.
|
|
- For `preliminary`, `players.group_code` is synchronized from `groupKey`.
|
|
- Special value `UNASSIGNED` maps to empty player group.
|
|
|
|
### Response
|
|
|
|
- `200 OK` with full updated admin state payload.
|
|
|
|
## 2) Stage Session Control Endpoints
|
|
|
|
### Start stage
|
|
|
|
- Method: `POST`
|
|
- Path: `/api/admin/stage/start`
|
|
- Auth: admin bearer token
|
|
|
|
Request body:
|
|
|
|
```json
|
|
{
|
|
"phase": "preliminary",
|
|
"group": "A",
|
|
"round": 2
|
|
}
|
|
```
|
|
|
|
Rules:
|
|
|
|
- `phase` must be one of:
|
|
- `preliminary`
|
|
- `prelim_tiebreak`
|
|
- `final`
|
|
- `final_tiebreak`
|
|
- `group` validation depends on phase:
|
|
- `preliminary`: group code string (or `UNASSIGNED`)
|
|
- `final`: `"1"` or `"2"`
|
|
- tie-break phases: positive numeric string
|
|
- `round` normalization:
|
|
- `preliminary`: `1..3`
|
|
- `final`: `1..2`
|
|
- tie-break phases: always `1`
|
|
- If another stage is active (started, not ended), API returns `409`.
|
|
|
|
Response:
|
|
|
|
- `200 OK` with full updated admin state payload.
|
|
|
|
### End stage
|
|
|
|
- Method: `POST`
|
|
- Path: `/api/admin/stage/end`
|
|
- Auth: admin bearer token
|
|
|
|
Rules:
|
|
|
|
- Ends the currently active stage by setting `ended_at`.
|
|
- If no active stage exists, API returns `400`.
|
|
|
|
Response:
|
|
|
|
- `200 OK` with full updated admin state payload.
|
|
|
|
## 3) Stage History Endpoint
|
|
|
|
- Method: `GET`
|
|
- Path: `/api/admin/stage/history`
|
|
- Auth: admin bearer token
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"items": [
|
|
{
|
|
"id": 1,
|
|
"phase": "preliminary",
|
|
"group": "A",
|
|
"round": 2,
|
|
"startedAt": "2026-04-30T08:27:13Z",
|
|
"endedAt": "2026-04-30T08:28:01Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## 4) New State Fields
|
|
|
|
Both endpoints now include these fields:
|
|
|
|
- `GET /api/state`
|
|
- `GET /api/admin/state`
|
|
|
|
```json
|
|
{
|
|
"positionBoards": {
|
|
"preliminary": {
|
|
"12": { "groupKey": "A", "position": 1 }
|
|
},
|
|
"final": {
|
|
"12": { "groupKey": "1", "position": 3 }
|
|
},
|
|
"prelim_tiebreak": {},
|
|
"final_tiebreak": {}
|
|
},
|
|
"current_stage": {
|
|
"id": 7,
|
|
"phase": "preliminary",
|
|
"group": "A",
|
|
"round": 2,
|
|
"startedAt": "2026-04-30T09:00:00Z"
|
|
},
|
|
"last_stage": {
|
|
"id": 6,
|
|
"phase": "final",
|
|
"group": "1",
|
|
"round": 1,
|
|
"startedAt": "2026-04-30T08:45:00Z",
|
|
"endedAt": "2026-04-30T08:55:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
Notes:
|
|
|
|
- `positionBoards` keys are player IDs as strings.
|
|
- `current_stage` is `null` when no stage is active.
|
|
- `last_stage` is `null` when no stage session has ever started.
|
|
- `last_stage` is the most recently started session (ended or still active).
|
|
|
|
## Compatibility Impact
|
|
|
|
- Additive only; existing consumers remain functional.
|
|
- Consumers can ignore unknown fields safely.
|
|
- Consumers needing control/monitoring can use new stage endpoints and fields.
|