- Honor ignore_singles/ignore_compilations at scanner read time so toggles
take effect immediately on the dashboard, artist page, and digest instead
of waiting for the MusicBrainz cache to expire and prune rows.
- Run notifier notify synchronously in the scheduler loop to avoid overlapping
read-send-mark runs double-sending the digest.
- Show artist name (with ID fallback) on the archive page instead of raw IDs.
- Select last_synced in GetAllArtistSettings for contract consistency.
- Fix stale startPeriodicSync comment and remove redundant error var.
- Remove dead ignored-branch from the artist template (never rendered).
- Add tests: CSRF sameOrigin, ArtistCacheFresh, secondary_types round-trip,
and scanner type-toggle filtering.
- Update Specification.md schema/config to reflect mbid, last_synced,
secondary_types, sync.interval, and server.public_url.
- Store cached_at in canonical UTC layout so the cache TTL cutoff comparison is a valid time ordering (previously go-sqlite3 serialized time.Time as RFC3339, making the space-separated cutoff match only by ASCII accident; same-day expired entries were falsely served as fresh).
- Remove stale no-op scanner config keys (ignore_bootlegs, include_compilations) from config.yaml.example and docs; these fields were removed from ScannerConfig but left in configs, silently doing nothing.
- Fix artist-ID namespace mismatch in MusicBrainz provider: SyncArtistDiscography
now stores the canonical Navidrome artist ID (artist_settings.id) as
external_releases.artist_id instead of the MusicBrainz MBID. Previously the
MBID was stored, which violated the FK to artist_settings and broke the
scanner join (local_albums.artist_id is the Navidrome ID), causing every
external release to be falsely reported as missing and the sync insert to
fail at runtime. getArtistFilterOptions now also resolves by the Navidrome ID.
- Resolve threshold in FindMissingReleases so the exported primitive honors the
same zero-means-default contract as ScanArtist/ScanAll.
- Remove dead maxLen==0 guard in scanner.Similarity.
- Inline trivial buildPath helper; drop unused url import in client.go.
- Replace hand-rolled itoa with strconv.Itoa in tests.
- Rewrite SyncArtistDiscography tests to seed artist_settings with the Navidrome
ID (tests previously seeded the MBID to mask the FK mismatch).
- Fix TestFuzzySmoke to exercise the real dependency (fuzzy.LevenshteinDistance /
scanner.Similarity) instead of an unused API.
- Fix TestAppRun_ScanLogsMissingReleases to run the scan against a live context
and assert the missing release is found.
- Document cached_at column in Specification.md and note startup scan / required
musicbrainz.user_agent in README.
- Stop tracking .serena/ tooling config; add it to .gitignore.
Add the Navidrome client module that connects to a Navidrome server via
the Subsonic API, fetches artist and album data, and syncs it into the
local SQLite database.
- Add go-subsonic dependency for Subsonic API communication
- Create internal/navidrome/client.go with NavidromeClient wrapper
- NewClient constructor with token-based auth
- Ping health check with HTTP status validation
- GetArtists fetches all artists via getArtists endpoint
- GetArtistAlbums fetches albums per artist via getArtist endpoint
- Create internal/navidrome/sync.go with sync orchestration
- SyncArtists upserts artists into artist_settings table
- SyncAlbums fetches and stores albums for monitored artists
- Add local_albums table (migration 003) with FK to artist_settings
- Add LocalAlbum CRUD operations in internal/database/local_albums.go
- Full test coverage: 19 tests across client and sync packages
- All tests pass, go vet and go fmt clean