diff --git a/CHANGELOG.md b/CHANGELOG.md index b438aac29..8880f82fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,96 @@ generated trace matrix lives in [docs/traceability.md](docs/traceability.md). For how long each fixed defect had been shipping before it was found, see [docs/defect-windows.md](docs/defect-windows.md). +## v0.12.0 + +JellyTau works against Jellyfin 12. Jellyfin 12.0 shipped on 2026-09-08 and +turns off, by default, the two ways every earlier JellyTau build identified +itself to a server — including on servers that were upgraded rather than freshly +installed. An app that was not changed for it stops signing in the day the server +updates. This release is changed for it, and still works against 10.11, so the +app can be updated first and the server whenever it suits. + +There is no Jellyfin 11. The project dropped the leading `10` from its version +scheme: what would have been 10.12.0 shipped as 12.0. Anything that compares +Jellyfin version numbers needed to learn that, and this app now has. + +### ✨ Changes + +- **Signing in survives a server upgrade to Jellyfin 12.** The server used to be + told who was asking through a header and a URL parameter that 12.0 disables by + default — a migration disables them on upgraded servers too, so nothing in an + admin's hands changes the outcome. The replacement spellings are accepted by + 10.11 and 12 alike, so this is one way of identifying the app that works + everywhere, not a switch between two. The URL half matters more than it + sounds: video and audio are streamed by the device's media player, which cannot + send headers at all, so the URL parameter is the only way playback can + authenticate. A test now refuses any request built with the old spellings, + because the failure is silent right up until a server upgrades. + (UR-085 → DR-287) + +- **Browsing a library returns the same things on both server versions.** 12.0 + changed what a filtered library listing means — asked for the films in a + library, 10.11 returned the folder's immediate contents and 12.0 returns + everything beneath it, and nothing in the reply says which rule applied. The + app now says which it wants, so both servers answer the same way, and the + answer is the one it always had. (UR-085 → DR-288) + +- **The app knows what server it is talking to, once, and adapts.** The server + version was already fetched at sign-in and then thrown away. It is now + resolved into a small set of named capabilities that every version-dependent + decision reads from, rather than the version number being compared wherever + somebody needed it — which is unreadable by the second occurrence and cannot + express a backport. A server newer than this build is treated as the newest + one it knows and keeps working; refusing it would make every release expire + the moment the server updated. Only a server older than 10.10 is refused, and + the sign-in screen says so and names the minimum. (UR-085 → IR-035, DR-280, + DR-286) + +- **The cached library re-fetches itself after a server upgrade.** Nothing had + recorded which server version wrote the cached catalog, so a server upgraded + underneath the app kept serving rows read under the old rules. The generation + is now recorded, and a change clears the cache so it fills back under the new + one. The first launch of this version records and clears nothing — an + existing install is not charged a full re-download to defend against an + upgrade that has not happened. (UR-085 → DR-284) + +### 🛠 Development + +- **Every route the app speaks lives in one place.** Fifty-seven inline URL + strings across the server adapter became one module of route functions, each + taking the resolved capabilities. Both shapes of the item routes Jellyfin has + deprecated are built and tested, though nothing selects the second yet — the + family still works on 12.0, and 12.0's written policy that unlisted endpoints + may go in any major release is why having the alternative ready costs less + than needing it. (UR-085 → DR-279, DR-282) + +- **The server adapter is tested against a server.** There was no HTTP mocking + in the Rust tree at all: every test of the adapter asserted on a URL string it + had built, and none exercised a reply. A fake Jellyfin now answers over real + HTTP and reports whichever version a test asks for, so the same assertions run + against both generations through the production resolution path. The one + file that had tried this before reimplemented the URL builders inside its own + mock and asserted against itself — and had never compiled, and had once + stayed green while the real code shipped a download endpoint that 404s. It is + deleted, and the rule it teaches is written at the top of its replacement. + (UR-085 → DR-281) + +- **A Jellyfin URL was being built in the interface layer** — the last one, + and, it turned out, unused. Deleted rather than moved. (UR-085 → DR-285) + +### ⚠️ Known limits + +Every cross-version assertion runs against a fake server built from a +source-level diff of the two Jellyfin releases, not against a running 12.0. Two +things that diff could not settle: whether remote control and casting behave +identically, and whether the audio-codec check that forces a transcode on 10.11 +is still needed on 12 — it is left on, which errs toward an unnecessary +transcode rather than silent playback. Both resolve with a real 12.0 server; +reports welcome. + +**Upgrading:** install this version *before* upgrading the server, not after. +It works against both; an older JellyTau does not work against 12. + ## v0.11.6 Found by an audit of the stack's most fragile seams rather than by hitting them, diff --git a/package.json b/package.json index d6fdaec3d..c4c6c5e8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jellytau", - "version": "0.11.6", + "version": "0.12.0", "description": "A cross-platform Jellyfin client built with Tauri, SvelteKit and Rust.", "author": "Duncan Tourolle ", "license": "MIT", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 125d198db..b9d238854 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2275,7 +2275,7 @@ dependencies = [ [[package]] name = "jellytau" -version = "0.11.6" +version = "0.12.0" dependencies = [ "aes-gcm", "argon2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index bb1e33f6a..9a8d14bce 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -4,7 +4,7 @@ name = "jellytau" # `player-conformance`, and a second binary makes a bare `cargo run` — # which `tauri dev` issues — ambiguous. default-run = "jellytau" -version = "0.11.6" +version = "0.12.0" description = "A cross-platform Jellyfin client" authors = ["Duncan Tourolle "] license = "MIT" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 822f2a616..c38d29e50 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "JellyTau", - "version": "0.11.6", + "version": "0.12.0", "identifier": "com.dtourolle.jellytau", "build": { "beforeDevCommand": "bun run dev",