Skip to content

feat(playlists): permalink-only access to private playlists#843

Open
dylanjeffers wants to merge 1 commit into
mainfrom
claude/sad-swirles-f24794
Open

feat(playlists): permalink-only access to private playlists#843
dylanjeffers wants to merge 1 commit into
mainfrom
claude/sad-swirles-f24794

Conversation

@dylanjeffers
Copy link
Copy Markdown
Contributor

Summary

  • Allow unauthenticated callers to view a private playlist when they have the permalink, while keeping it hidden from search/browse and bare-ID lookups. This mirrors the existing is_unlisted model for tracks.
  • A new is_private filter is added to get_playlists.sql with an @include_private bypass flag. Permalink-driven entry points (the by_permalink route, the bulk /v1/full/playlists?permalink=… endpoint, and the /v1/resolve redirect target) set IncludePrivate: true; bare ID lookups do not.
  • The bulk endpoint keeps caller-supplied IDs and permalink-derived IDs in separate Playlists() calls so a request mixing ?id=PRIVATE_ID&permalink=any_public cannot leak a private playlist by piggy-backing on the permalink trust.
  • v1_playlist_by_permalink now accepts both /playlist/ and /album/ URL variants, so /v1/resolve can redirect album URLs there.
  • Tracks already allow anonymous permalink access (every direct-fetch handler sets IncludeUnlisted: true); no code change there, just a regression test.

Behavior change

Anonymous (and non-owner) requests to /v1/full/playlists/:id or /v1/full/playlists?id=… for a private playlist will now return 404 / empty. Owners (myID == owner_id) and any callers using the permalink continue to see the playlist.

Test plan

  • TestV1PlaylistByPermalink and TestV1AlbumByPermalink still pass
  • TestV1PrivatePlaylistByPermalinkAnonymous — anon caller gets private playlist via permalink
  • TestV1PrivateAlbumByPermalinkAnonymous — anon caller gets private album via permalink
  • TestPlaylistsEndpointPrivatePermalinkAnonymous — same via bulk endpoint
  • TestPlaylistsEndpointPrivateByIdHiddenFromAnonymous?id= does not leak private
  • TestGetPlaylistPrivateAnonymous404/playlists/:id returns 404 for anon on private
  • TestGetPlaylistPrivateOwnerAllowed — owner can still fetch their private playlist by ID
  • TestGetUnlistedTrackByPermalinkAnonymous — regression lock-in for track permalink behavior
  • Resolve tests (TestResolvePlaylistURL) still 302 (redirect target changed to by_permalink, still ok)

🤖 Generated with Claude Code

Add an `is_private` filter to `get_playlists.sql` with an
`@include_private` bypass, mirroring the existing `is_unlisted`
pattern for tracks. The flag is set to true on permalink-driven
entry points (by_permalink route, bulk endpoint when ?permalink= is
used, and the /resolve redirect target), so possessing a valid
permalink is treated as proof of access for unauthenticated callers.

Caller-supplied IDs in the bulk endpoint are kept in a separate
query from permalink-derived IDs to avoid leaking a private playlist
when both are mixed in one request.

Also: extend the by_permalink route to accept both /playlist/ and
/album/ URL variants so /v1/resolve can redirect there for albums.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dylanjeffers dylanjeffers force-pushed the claude/sad-swirles-f24794 branch from ec22c3c to 95e844a Compare May 21, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant