v0.44.0
UX release. Rejecting a recommendation now opens a structured picker with six fixed reasons plus a "Don't show again" checkbox that promotes the rejection to a permanent per-user blacklist. Settings gets a new Blocked tab to view, search, and unblock entries. The blocklist filters the pipeline, subscriptions, and quick-discover independent of the existing rejection cooldown, so unblocking does not bypass the cooldown.
Added
- Permanent per-user artist blacklist (
artist_blockstable) with(user_id, artist_id)unique upsert - Structured rejection reasons (6 fixed + freeform "Other") via a bottom-sheet/modal picker
Settings > Blockedtab with debounced search, cursor pagination, and unblock-with-undo toast- New REST routes:
POST/GET /api/v1/artist-blocks,DELETE /api/v1/artist-blocks/:artistId rejection_reasonandrejection_reason_textcolumns onrecommendations- Pipeline filter, subscription runner, and quick-discover all honour the blocklist as an independent layer
- 28 new i18n keys translated across all 15 shipped locales
- Backup/restore round-trips include
artist_blocks - Server-side Zod validation enforces the UI invariants (
not_right_now⊥permanent;reasonTextonly valid whenreason='other')
Changed
PATCH /api/v1/recommendations/:idwithstatus: 'rejected'accepts optionalreason,reasonText, andpermanentfields; legacy callers continue to work unchangedStoreDbinterface gainsgetBlockedMbids(userId)- New
Digarrsignature theme added to the theme picker