- Start Web UI before the blocking initial sync so the dashboard is
reachable during the (rate-limited, potentially multi-minute) first
sync; fold the immediate sync into startPeriodicSync's overlap guard
so it can never race a concurrent tick over the shared DB / MB client.
- Make MarkNotificationSent idempotent: INSERT OR IGNORE for same-second
PK collisions, and explicitly swallow FK violations when a release was
pruned by a concurrent re-sync. Prevents a single vanished/duplicate
release from aborting the digest mark-sent loop and re-sending.
- Do not abort NotifyOnce's mark-sent loop on a single failure; log and
continue so every release in the batch is marked.
- NULL-safe reads: COALESCE(type,''), COALESCE(release_date,'') in the
external_releases and unnotified readers to match the cache reader.
- Update/extend tests for the new idempotency and startup contracts.
- 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.
- notifier: show artist display names (not internal IDs) in digest; resolve
names from artist_settings and fall back to ID when unavailable
- notifier: skip sending an empty digest to avoid daily spam
- config: require telegram token/chat_id when enabled
- web: warn loudly when auth is disabled on a non-loopback bind; add HTTP
server timeouts
- web: treat SetReleaseIgnored "release not found" as benign redirect (0 rows)
- musicbrainz: reject low-score/name-mismatched MBID resolutions instead of
silently caching the wrong artist
- database: remove dead duplicate err check; harden DSN param appending
- musicbrainz: check rows.Err() after iterating existing releases