Go server (PR1):internal/apierror package + typed *Error; writeErr(err) rewrite migrating ~342 call sites; resolveByID helper for parseUUID→fetch→404; audit.WriteOrLog wrapper; per-package ErrNotFound consolidated to alias apierror.ErrNotFound.
Cover-art (PR3): Shared httpClient for rate-limit + retry + body read across Last.fm / Deezer / TheAudioDB providers; ~400 LoC removed across the 3 providers.
#85: error-copy.json expanded from 14 → 46 codes (auth/validation/404 flows), mirrored to Flutter.
B4 Drag-reorder convergence — PlaylistTrackRow migrated to @neodrag/svelte.
C1 Cover URL helper migration — 5 sites.
C2.play-overlay CSS hoisted from 3 components to app.css.
A4 / C-base / C3 / D / API-DTO codegen — examined, skipped with rationale (see commit messages / discovery doc).
Test plan
CI Go vet + golangci-lint + short race tests on dev — green
CI vitest + svelte-check on dev — green
Smoke-test :main image in prod after merge: log in, browse library, play a track, queue management, search, /admin/integrations renders, cover art loads
If smoke clean, tag v2026.05.08.1 for the pinned release image
## Summary
Two-round DRY pass across Go server + web SPA, plus PR3's cover-art provider HTTP plumbing extraction. ~50 commits on dev since the last release.
## Round 1 (PR1+PR2+PR3 + #85 error-copy)
- **Go server (PR1):** `internal/apierror` package + typed `*Error`; `writeErr(err)` rewrite migrating ~342 call sites; `resolveByID` helper for `parseUUID→fetch→404`; `audit.WriteOrLog` wrapper; per-package `ErrNotFound` consolidated to alias `apierror.ErrNotFound`.
- **Web SPA (PR2):** `errCode` / `errMessage` helpers (38 sites); `<Modal>` component (8 admin modals); `pushToast` store + `<ToastHost />` (8 sites); `offsetGetNextPageParam`/`pageGetNextPageParam` (8 sites).
- **Cover-art (PR3):** Shared `httpClient` for rate-limit + retry + body read across Last.fm / Deezer / TheAudioDB providers; ~400 LoC removed across the 3 providers.
- **#85:** error-copy.json expanded from 14 → 46 codes (auth/validation/404 flows), mirrored to Flutter.
## Round 2 (Groups A/B/C/D)
- **A1** sqlc `*ForUser` dedup — 3 query pairs unified via nullable user_id.
- **A2** Handler-prelude helpers — `requireUser` / `requireURLUUID` / `decodeBody`, ~25 handler files migrated.
- **A3** `withUser` test helper — 11 test files migrated.
- **B1** Theme hex DRY — meta-theme reads from tokens.json.
- **B2** Auth↔player cycle break — `auth/user.svelte.ts` extracted, defensive patches removed.
- **B3** svelte-query mock factoring — vitest setup default + 34 files cleaned (-180 LoC).
- **B4** Drag-reorder convergence — `PlaylistTrackRow` migrated to `@neodrag/svelte`.
- **C1** Cover URL helper migration — 5 sites.
- **C2** `.play-overlay` CSS hoisted from 3 components to `app.css`.
- **A4 / C-base / C3 / D / API-DTO codegen** — examined, skipped with rationale (see commit messages / discovery doc).
## Test plan
- [x] CI Go vet + golangci-lint + short race tests on dev — green
- [x] CI vitest + svelte-check on dev — green
- [ ] Smoke-test `:main` image in prod after merge: log in, browse library, play a track, queue management, search, /admin/integrations renders, cover art loads
- [ ] If smoke clean, tag `v2026.05.08.1` for the pinned release image
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Two-round DRY pass across Go server + web SPA, plus PR3's cover-art provider HTTP plumbing extraction. ~50 commits on dev since the last release.
Round 1 (PR1+PR2+PR3 + #85 error-copy)
internal/apierrorpackage + typed*Error;writeErr(err)rewrite migrating ~342 call sites;resolveByIDhelper forparseUUID→fetch→404;audit.WriteOrLogwrapper; per-packageErrNotFoundconsolidated to aliasapierror.ErrNotFound.errCode/errMessagehelpers (38 sites);<Modal>component (8 admin modals);pushToaststore +<ToastHost />(8 sites);offsetGetNextPageParam/pageGetNextPageParam(8 sites).httpClientfor rate-limit + retry + body read across Last.fm / Deezer / TheAudioDB providers; ~400 LoC removed across the 3 providers.Round 2 (Groups A/B/C/D)
*ForUserdedup — 3 query pairs unified via nullable user_id.requireUser/requireURLUUID/decodeBody, ~25 handler files migrated.withUsertest helper — 11 test files migrated.auth/user.svelte.tsextracted, defensive patches removed.PlaylistTrackRowmigrated to@neodrag/svelte..play-overlayCSS hoisted from 3 components toapp.css.Test plan
:mainimage in prod after merge: log in, browse library, play a track, queue management, search, /admin/integrations renders, cover art loadsv2026.05.08.1for the pinned release image