From 6da194045b02eb045e88d0f57311ac91d32062e4 Mon Sep 17 00:00:00 2001 From: mithral Date: Sun, 11 Oct 2026 15:05:43 -0400 Subject: [PATCH] Waves 9-10: Jellyfin and Subsonic clients can browse and play MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vellum now speaks two foreign protocols, so the clients people already own can use it. Both are translation layers over queries that already exist, and both go through the same grant chokepoint as the web app — a token is a second way to be a user, never a second set of permissions. Shared foundation (coordinator, written before dispatch) - migrations/0012_api_tokens.sql + internal/apitoken. Both protocols need a credential that is not the session cookie, and letting two agents each invent a token table would have produced two incompatible ones. - The table stores two shapes for a real reason: a Jellyfin token is a bearer value so only its hash is kept, while a Subsonic key must be recoverable because verifying `t` means computing md5(key + salt) server-side. token_plain is therefore the one column in the schema holding a usable credential. It is a generated random secret, never a user password, and it is revocable. Wave 9 - Jellyfin - /System/Info/Public, /Users/AuthenticateByName, /Users/Me, /Users/{id}, /Items, /Users/{id}/Items, /Items/{id}, /Items/{id}/Images/Primary, /Items/{id}/PlaybackInfo, /Videos/{id}/stream, /Audio/{id}/stream, /Sessions/Playing{,/Progress,/Stopped}. - Auth accepts X-Emby-Token, X-MediaBrowser-Token, ?api_key=, and Authorization: MediaBrowser Token="...". The ?api_key= form is the one that matters: