feat(library): let auditors correct game data
Build, Test & Push Core Service / quality-check (push) Successful in 1m0s
Build, Test & Push Core Service / docker (push) Successful in 1m25s

An AUDITOR corrects name, header image, speedrun link, moods, endless and genres of a game for every user (V20 game_correction, PUT/DELETE /api/library/games/{appid}/corrections/{field}). The value is also written into the cached row, so reads stay unchanged; the Steam sync, the image repair, the IGDB add and the mood and speedrun upserts skip corrected fields. SteamGame gets @DynamicUpdate so a sync no longer writes back columns it did not change.
This commit is contained in:
lobo committed 2026-09-28 09:31:39 +02:00
1 parent 2596df609e
commit 3c2f40036d
30 files changed
+1066 -20

No files matched your search

+12
View File
@@ -95,6 +95,7 @@ method calling another service's method that needs more.
|---|---|---|
| `GET` | `/api/library/games`, `/api/library/games/{appid}` | JWT |
| `PUT` | `/api/library/games/{appid}/backlog` | JWT |
| `PUT`, `DELETE` | `/api/library/games/{appid}/corrections/{field}` (`{value}`; `name`, `image`, `speedrun`, `moods`, `endless`, `genres`; `204`, `400 INVALID_CORRECTION`) | JWT, AUDITOR |
| `PUT` | `/api/library/games/{appid}/status` (status only, keeps rating, notes, priority) | JWT |
| `PUT` | `/api/library/games/{appid}/finished-hint` (`{dismissed: ENDING\|PLAYTIME}`, "Not yet"; `204`) | JWT |
| `PUT` | `/api/library/games/{appid}/hidden` (`{hidden}`; `409 MANUAL_GAME` for a game added by hand) | JWT |
@@ -206,6 +207,17 @@ The frontend polls `GET /api/library/sync-status` until the run ends.
At 01:30 `ImageRepairService` repairs the pictures reported through `POST /api/library/broken-images` (table
`broken_image`, one row per game and kind). Reports only count for Steam games the user owns.
### Corrections by an auditor
An AUDITOR (active role) corrects a game's name, header image, speedrun link, moods, endless flag and genres for
every user (`game_correction`, V20). The value is also written into the cached row (`steam_game`, `game_speedrun`,
`game_mood`), so no read joins the corrections. The refresh writers skip a corrected field: the Steam sync (name),
the image repair (image), the IGDB add (name, image), the mood and speedrun upserts (SQL). **A new writer of these
fields must do the same.** "Back to source" (`DELETE`) writes back the source value from the first correction and
lets the next refresh ask IGDB or speedrun.com again. An image must be on a host of the frontend's CSP.
Known limit: a mood or speedrun refresh that waits on the row lock while an auditor saves can still write the
source value once (its guard sees the state from before the save); the auditor saves again.
### Deleted accounts
Auth drives it (see Auth's readme). `POST /internal/accounts/deleted` adds a tombstone in `deleted_user`: the user