Implement Phase 3A playlist management

This commit is contained in:
Media
2026-08-16 20:34:36 -05:00
parent 722c6cf77d
commit e2ecdc97e2
15 changed files with 2955 additions and 7 deletions
+42
View File
@@ -79,6 +79,48 @@ display and thumbnail routes stream private S3 objects through the API with a
one-year immutable cache policy. Original downloads use private, no-store
caching.
## Playlists
Playlist and entry metadata is authoritative in SQLite. The API surface is:
- `GET /api/playlists`
- `POST /api/playlists`
- `GET /api/playlists/:playlistId`
- `PATCH /api/playlists/:playlistId`
- `DELETE /api/playlists/:playlistId`
- `POST /api/playlists/:playlistId/entries`
- `PATCH /api/playlists/:playlistId/entries/:entryId`
- `DELETE /api/playlists/:playlistId/entries/:entryId`
- `PUT /api/playlists/:playlistId/entries/order`
- `POST /api/playlists/:playlistId/activate`
Entry positions are zero-based and contiguous. Reordering requires the complete
ordered list as `{ "entryIds": [...] }`. An asset can occur only once in a
playlist, but the same asset can be used independently by any number of other
playlists. Only ready, unexpired assets can be newly added.
Entry duration overrides may be null (inherit the global setting) or 1,000 to
3,600,000 milliseconds. Presentation overrides are nullable; darkening is an
inherit/off/on boolean and blur always comes from the global setting. Schedule
instants use epoch milliseconds or ISO strings with an explicit `Z` or numeric
UTC offset, and intervals are evaluated as `[start, end)`.
Playlist detail responses include effective duration and presentation,
server-evaluated eligibility, immutable display/thumbnail URLs, and the
settings revision and evaluation time used. Playlist revisions increment once
per semantic content change. Exact no-ops and reads do not increment them.
Activation is explicit. A request is held in the existing pending-activation
state while a playable normal slide is mid-duration; otherwise the target
playlist is prepared immediately at its first currently playable entry. The
output-off flag remains only a visual gate, and static hold is preserved while
the hidden normal playlist changes. Phase 3A does not include the advancing
playback timer that will consume pending activation at a slide boundary.
Socket.IO publishes `playlists:changed` as a refetch invalidation after
committed playlist changes and after settings or referenced-asset edits that
affect resolved playlist data. Socket.IO is not a mutation API.
## Storage and health
The API uses a small path-style S3 adapter configured by `S3_ENDPOINT`,