Commit Graph

19 Commits

Author SHA1 Message Date
bvandeusen 3d0e213081 feat(server/m7-381): admin scan-status + manual trigger endpoints
Adds GET /api/admin/scan/status and POST /api/admin/scan/run under the
existing RequireAdmin middleware block; plumbs *library.Scanner and
library.RunScanConfig through api.Mount, server.New, and main.go so the
manual trigger reuses the same RunScan orchestrator as startup scans.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 20:13:31 -04:00
bvandeusen 65a3c4892c feat(server/m7-381): RunScan orchestrator chains library+backfill+enrich
Adds internal/library/scanrun.go with RunScan, which creates a scan_runs
row and sequences file-walk → MBID backfill → cover enrich, persisting
per-stage tallies as jsonb. Extends coverart.EnrichBatch to return
(processed, succeeded, failed, err) so the orchestrator can classify
outcomes. Replaces main.go's two separate boot goroutines with a single
RunScan call; passes nil scanner in the no-startup-scan branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 20:08:48 -04:00
bvandeusen 34615fffbd feat(server/m7-380): one-shot MBID backfill worker for existing libraries
Adds a boot-time goroutine that walks albums with NULL mbid, re-reads
tags from one track per album via dhowden/tag, and persists album + artist
MBIDs. Healed albums also get their cover_art_source='none' cleared so the
enricher's next batch retries the MBCAA fetch. Caps at 5000 albums per
boot to avoid stalling startup on huge libraries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 19:40:27 -04:00
bvandeusen d4a837b904 feat(server/m7-353): admin endpoints for cover refetch (per-album + bulk)
Adds POST /api/admin/albums/{id}/cover/refetch (synchronous single-album
retry) and POST /api/admin/covers/refetch-missing (async bulk drain).
Wires coverart.Enricher through server.New → api.Mount → handlers struct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:11:53 -04:00
bvandeusen 6c33acf062 feat(server/m7-353): config + main.go wiring for coverart enricher 2026-05-04 15:06:28 -04:00
bvandeusen 391f5f16a1 feat(server/m7-352): cron loop + main.go wiring for system playlist build 2026-05-04 09:16:07 -04:00
bvandeusen ca82862346 chore(config): rename SMARTMUSIC_ env prefix to MINSTREL_; default admin user
The legacy SMARTMUSIC_ prefix dates from when the project was specced
as "smart-music" before being renamed to Minstrel. Hard cutover to
MINSTREL_* across config.go, tests, config.example.yaml, README, and
docker-compose. Also renames SMARTMUSIC_CONFIG in cmd/minstrel/main.go
which was missed in the original audit.

Also seeds Auth.AdminBootstrap.Username = "admin" in Default() so
MINSTREL_DATABASE_URL is the only env var required for a fresh prod
deployment — the bootstrap auto-generates a password and prints it
to stderr. Drops the now-redundant MINSTREL_AUTH_ADMIN_USERNAME=admin
line from the README quickstart and docker-compose.

M1 follow-up from the #363 final review: guards
MINSTREL_BRANDING_APP_NAME and _DESCRIPTION against empty-string
overrides — empty would have shipped <title></title> to share-preview
crawlers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 18:40:59 -04:00
bvandeusen 46ea9a761a feat(server/m7-363): thread BrandingConfig through server.New 2026-05-03 17:17:52 -04:00
bvandeusen 6d1709caff fix(config): wire DataDir from yaml/env through to playlists service
Slice 1 of M7 #352 added Server.DataDir but left it un-populated —
the playlist cover-collage writer would have used "" as the relative
path root in production, writing to the current working directory.

- Add Storage.DataDir to Config (yaml: storage.data_dir, env:
  SMARTMUSIC_STORAGE_DATA_DIR), defaulting to "./data".
- server.New takes the data dir as a parameter; main.go threads it.
- main.go MkdirAll's the directory at startup so the playlist cover
  writer doesn't fail on first use with a missing parent.
- config.example.yaml documents the new section.

Existing internal/server/server_test.go constructs Server directly
without server.New, so no test fixture changes needed for that file.
2026-05-03 11:37:41 -04:00
bvandeusen 1bde1787b9 feat(cmd): start Lidarr reconciler worker alongside HTTP server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 17:57:42 -04:00
bvandeusen 358bfd9453 feat(cmd): start similarity worker alongside HTTP server 2026-04-28 20:25:11 -04:00
bvandeusen 46b23424c2 feat(cmd): start scrobble worker alongside HTTP server 2026-04-28 09:28:13 -04:00
bvandeusen 08591debee feat(api): rewrite /api/radio with weighted shuffle v1
Validates seed_track + optional limit (default cfg.Recommendation.RadioSize,
clamped to RadioSizeMax). Calls recommendation.LoadCandidates +
recommendation.Shuffle. Prepends seed to result. Server seeds a
math/rand source at startup; handlers package threads that as a
func() float64 so tests inject deterministic RNGs.

Mount + server.New gain a RecommendationConfig parameter.
2026-04-27 08:08:10 -04:00
bvandeusen f4e73b81b4 feat(api): add POST /api/events handler
Discriminated-union JSON over three event types: play_started,
play_ended, play_skipped. Auth via existing RequireUser. play_started
returns play_event_id + session_id; the other two return { ok: true }.
Validates ownership: play_ended/play_skipped on another user's row
returns 403. Mount signature now takes EventsConfig and constructs
the playevents.Writer; server.New propagates it through.
2026-04-26 00:12:06 -04:00
bvandeusen 9f325cf309 feat(cmd): plumb SubsonicConfig into server.New 2026-04-19 17:40:24 +00:00
bvandeusen bea0604846 M1/#293: wire scanner into startup + server 2026-04-19 15:16:03 +00:00
bvandeusen d358d7e1a0 M1/#292: wire auth.Bootstrap into startup 2026-04-19 02:31:05 +00:00
bvandeusen e54482409a M1/#291: run migrations + open pool on startup 2026-04-19 01:12:23 +00:00
bvandeusen be181f8245 feat(skel): add cmd/minstrel entrypoint
Parses --config / SMARTMUSIC_CONFIG, loads YAML config with env overlay,
initializes slog, starts the chi HTTP server, and shuts down cleanly on
SIGINT/SIGTERM.
2026-04-18 21:19:39 +00:00