From 8027fd5facac0f621bfdfe8864a1c69c8bffaa2e Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Tue, 8 Sep 2026 20:09:34 +0200 Subject: [PATCH] feat(repository): a route table and resolved server capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Endpoints were 57 inline format! literals with their query strings baked in at the point of use. That is workable against exactly one server and hostile to anything else: a second route shape would mean a conditional at every one of them. They now live in repository/endpoints.rs, one function each, taking &ServerCapabilities. Two things fall out of the move: - A small Endpoint builder replaces the manual ?/& juggling, so a double or trailing separator is structurally impossible rather than something four assertions in a deleted test file used to watch for. - Both user-scoped route shapes (/Users/{uid}/Items and /Items?userId=) are built and tested, though nothing selects the second yet. The family still works on 12.0, so migrating is optional; having both means it is a one-line change if 13.0 removes them, as the newly written removal policy allows. ServerCapabilities is resolved once per connection from the version the server already reported at connect. The version-to-flags mapping lives in exactly one function and nothing else in the crate compares a version number: a `version < N` at the point of use re-derives a domain fact where it is consumed, is unreadable by its second occurrence, and cannot express a backport. An unrecognised version resolves forward to the newest known generation rather than being refused, because refusing would make every release expire the moment the server upgrades. Only a version below the floor is refused. This commit also carries the two fixes that are NOT capability branches, because they live in the same files: - Authorization replaces X-Emby-Authorization, and ApiKey replaces the api_key query parameter. Jellyfin 12.0 disables both legacy spellings by default and a migration flips them on upgraded servers too, so this is what actually breaks against 12.0. The header value this app already built was always the correct MediaBrowser scheme, and both new spellings are ungated on 10.11.x — so it is a rename, not a branch. The query-parameter spelling is load-bearing rather than cosmetic: stream URLs go to mpv, ExoPlayer and the webview's