feat(server): playback_errors table + admin inbox endpoints
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:
@@ -107,6 +107,10 @@ func Mount(r chi.Router, pool *pgxpool.Pool, logger *slog.Logger, events *playev
|
||||
authed.Delete("/quarantine/{track_id}", h.handleUnflag)
|
||||
authed.Get("/quarantine/mine", h.handleListMyQuarantine)
|
||||
|
||||
// Client-reported playback errors (zero-duration tracks,
|
||||
// load failures). Admin-only inbox; any user can report.
|
||||
authed.Post("/playback-errors", h.handleReportPlaybackError)
|
||||
|
||||
// Self-hosted in-app update channel (#397). Auth-gated to
|
||||
// prevent anonymous bandwidth abuse on the APK stream;
|
||||
// /apk additionally per-user rate-limited.
|
||||
@@ -127,6 +131,9 @@ func Mount(r chi.Router, pool *pgxpool.Pool, logger *slog.Logger, events *playev
|
||||
|
||||
admin.Get("/quarantine", h.handleListAdminQuarantine)
|
||||
admin.Post("/quarantine/{track_id}/resolve", h.handleResolveQuarantine)
|
||||
|
||||
admin.Get("/playback-errors", h.handleListAdminPlaybackErrors)
|
||||
admin.Post("/playback-errors/{id}/resolve", h.handleResolvePlaybackError)
|
||||
admin.Post("/quarantine/{track_id}/delete-file", h.handleDeleteQuarantineFile)
|
||||
admin.Post("/quarantine/{track_id}/delete-via-lidarr", h.handleDeleteQuarantineViaLidarr)
|
||||
admin.Get("/quarantine/actions", h.handleListQuarantineActions)
|
||||
|
||||
Reference in New Issue
Block a user