feat(server): playback_errors table + admin inbox endpoints
test-go / test (push) Successful in 29s
test-go / integration (push) Successful in 11m25s

New client-reported playback-error log. Surfaces zero-duration
tracks (and future load_failed / stalled kinds) into an admin
inbox so the operator can hide / delete / re-request the
offending track.

Schema (migration 0032):
- playback_errors table with CHECK constraints on the kind +
  resolution enums (per the standing rule that new enum values
  need a migration to add)
- Partial index on unresolved rows for fast inbox lookup
- ON DELETE CASCADE from tracks + users so cleanup is automatic

Endpoints:
- POST /api/playback-errors: any signed-in user reports. Body
  validates track existence + kind whitelist; client_id required
  so support can correlate reports from the same device.
- GET /api/admin/playback-errors?resolved=false&offset=&limit=:
  admin list with join to track/album/artist for table render
  without per-row round-trips. Pagination capped at 200/page.
- POST /api/admin/playback-errors/{id}/resolve: admin marks
  resolved with a resolution enum string.

Auto-resolve on Hide/Delete/Re-request from the inbox row is
driven from the web client (two sequential calls) — keeps the
existing track-action endpoints unchanged.
This commit is contained in:
2026-06-02 11:25:50 -04:00
parent 6a54d074fd
commit 15b59a214d
7 changed files with 577 additions and 0 deletions
+13
View File
@@ -383,6 +383,19 @@ type PlaySession struct {
ClientID *string
}
type PlaybackError struct {
ID pgtype.UUID
TrackID pgtype.UUID
UserID pgtype.UUID
ClientID string
Kind string
Detail *string
OccurredAt pgtype.Timestamptz
ResolvedAt pgtype.Timestamptz
ResolvedBy pgtype.UUID
Resolution *string
}
type Playlist struct {
ID pgtype.UUID
UserID pgtype.UUID