feat(server/m7-352): kind filter on GET /api/playlists + lazy fallback

Adds ?kind= filter (user|system|all, default user) to GET /api/playlists
so system mixes don't leak into slice-1 SPA views. Lazy background build
fires when kind=system|all and the caller's run row is stale (>24h).
Propagates Kind/SystemVariant/SeedArtistID through PlaylistRow and
playlistRowView wire types.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-04 09:24:27 -04:00
parent 391f5f16a1
commit a90ff11f0f
3 changed files with 212 additions and 11 deletions
+9
View File
@@ -65,6 +65,9 @@ type PlaylistRow struct {
Name string
Description string
IsPublic bool
Kind string // 'user' | 'system'
SystemVariant *string // 'for_you' | 'songs_like_artist' | nil
SeedArtistID pgtype.UUID // Valid=true only for 'songs_like_artist'
CoverPath *string
TrackCount int32
DurationSec int32
@@ -498,6 +501,9 @@ func playlistFromGetRow(r dbq.GetPlaylistRow) *PlaylistRow {
Name: r.Name,
Description: r.Description,
IsPublic: r.IsPublic,
Kind: r.Kind,
SystemVariant: r.SystemVariant,
SeedArtistID: r.SeedArtistID,
CoverPath: r.CoverPath,
TrackCount: r.TrackCount,
DurationSec: r.DurationSec,
@@ -514,6 +520,9 @@ func playlistFromListRow(r dbq.ListPlaylistsForUserRow) *PlaylistRow {
Name: r.Name,
Description: r.Description,
IsPublic: r.IsPublic,
Kind: r.Kind,
SystemVariant: r.SystemVariant,
SeedArtistID: r.SeedArtistID,
CoverPath: r.CoverPath,
TrackCount: r.TrackCount,
DurationSec: r.DurationSec,