POST /api/admin/cover-sources/research bumps cover_art_sources_meta.
current_version unconditionally; the next enrichment pass re-eligibles
every 'none' row. Existing positively-sourced rows are not affected —
the version-mismatch eligibility rule only kicks in for 'none'.
Admin Cover Art panel gains a "Re-search missing art" button that
calls the endpoint and shows a confirmation toast. Operator's escape
hatch when:
- They've added a Last.fm key and want to retry failed rows
immediately rather than waiting for the next scheduled scan.
- An upstream provider's catalog has updated (e.g. Deezer added a
back-catalog import).
- They want to verify a fix end-to-end before the next scheduled
scan fires.
SettingsService.BumpVersion (the unconditional version of T5's
BumpVersionIfProvidersChanged) is the single-call DB writer; both
endpoints route through it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On boot, the SettingsService computes a SHA-256 hash of the sorted
registered-provider IDs and compares to the hash stored on
cover_art_sources_meta. Mismatch → atomic bump of current_version +
update of stored hash. The next enrichment pass picks up the new
version, all 'none' rows become eligible, and they get retried
against the new chain (now including Deezer / Last.fm).
One-shot: subsequent boots without a provider-set change don't bump
again. The check is best-effort — failures are logged at Warn but
don't refuse startup; a temporarily unreachable DB at boot just
means 'none' rows stay parked until a manual re-search (next task).
Tests cover first-boot (empty stored hash → bump), repeat-boot
(no change → no bump), and the registered-providers-hash
determinism.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Changes the AlbumCoverProvider and ArtistArtProvider interfaces from
MBID-only string parameters to ref-struct signatures so name-based
providers (Deezer, Last.fm in upcoming tasks) can act on rows
without MBIDs.
Today, 53 of 213 artists in the dev DB have NULL MBIDs — featured
artists, remixers, and compilation contributors created from
track-tag splits where the primary-artist MBID is in the file but
collaborator IDs aren't. These rows are unreachable by the current
MBID-only chain. Refactoring the interface unblocks future
name-based providers from acting on them.
TheAudioDB and MBCAA keep MBID-only behavior internally: they return
ErrNotFound when ref.MBID is empty rather than attempting a
name-based fallback. The MBID guard inside EnrichAlbum/EnrichArtist
is removed; providers receive the ref unconditionally and decide
whether they can act on it.
GetAlbumWithFirstTrackPath now JOINs artists to return artist_name
alongside the existing fields, supporting AlbumRef construction.
No behavioral change today (only TheAudioDB + MBCAA registered, both
keep MBID-only behavior). The change unblocks T3 (Deezer) and T4
(Last.fm) which can now register and act on every artist/album
regardless of MBID presence.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reconciles the compile-time provider registry with the
cover_art_provider_settings table at boot, and on every admin
update. Calls Configure() on each provider with the row data so
runtime config (enabled, api_key) propagates immediately.
Owns the cover_art_sources_meta.current_version stamp.
UpdateProvider returns versionBumped=true only when the change
altered the *enabled set* of providers — key rotations don't bump
version (the recheck trigger is for "we have a new source to ask,"
not config rotations).
Capability filtering: EnabledAlbumProviders / EnabledArtistProviders
return only registered providers that (a) are enabled per DB and
(b) implement the requested capability interface. Snapshots —
callers don't mutate.
ListProviderInfo builds the wire-shaped slice the admin GET handler
returns. APIKeySet bool replaces echoing the key (credential never
leaves the server).
TestProvider dispatches to TestableProvider.TestConnection on the
named provider, ErrNotTestable if the provider doesn't implement
the capability, ErrProviderNotFound if not registered.
UpdateProviderSettingsParams uses the sqlc-generated field names:
Enabled bool (not *bool — the COALESCE is handled by passing the
cached current value when patch.Enabled is nil), Column3 bool
(apiKeyChanged flag), ApiKey *string (the api_key value — sqlc
named this from the column, not Column4 as the task spec assumed).
Tests gated on MINSTREL_TEST_DATABASE_URL: boot-inserts-defaults,
flip-enabled-bumps-version, key-only-doesn't-bump, clear-key,
TestProvider routing for testable / non-testable / missing,
ListProviderInfo capability badges. Reuses newPool / discardLogger
and fakeProvider / fakeAlbumProvider from enricher_test.go and
provider_test.go (same package).