From 6a0efba47764c31f517c6053724380141687e3a2 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sat, 5 Sep 2026 04:54:15 +0200 Subject: [PATCH] =?UTF-8?q?chore(release):=200.81.0=20=E2=80=94=20E12=20Se?= =?UTF-8?q?curity=20&=20Ops=20Hardening?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ VERSION | 2 +- frontend/src/lib/releaseNotes.ts | 26 ++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c9fb8ee..3387919f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,33 @@ edit the release notes and re-run the generator. Upgrading, pinning a version and rolling back: [docs/self-hosting.md](docs/self-hosting.md#upgrading). +## 0.81.0 — 2026-09-05 + +If you run your own Siftlode, this one is mostly for you: there is now a way back from a bad upgrade, backup scripts that actually restore, and a way to let someone in on an instance that cannot send mail. If you just use Siftlode, the visible part is that a download can no longer quietly blow past your storage limit, and that the box refuses addresses on the server's own network. + +### Features + +- Admins get an account panel: click anyone in Users and it says, in one place, why that person can or cannot get in — whether their address is confirmed, whether an admin has approved them, whether they have a password, which Google account is attached, and whether their address is on the allow-list. Every recovery action for that account sits under the readout, so you pick one having read what is actually wrong instead of guessing. +- Someone locked out of an instance with no email setup can now be let back in. "Create a set-password link" gives you a one-time link to hand them however you like — chat, in person, on paper. It lasts 24 hours, works once, and signs out anyone already using that account. Issuing it changes nothing by itself: a misclick cannot lock anyone out. +- Self-hosters can pin a version. Put `IMAGE_TAG=0.81.0` in your `.env` and Siftlode stays there until you change the line, so an upgrade happens when you decide it does. The docs now also carry a rollback recipe — and say plainly that restoring the dump you took first is the way back that does not lose data. +- The backup and restore scripts work. On Windows they no longer corrupt the dump on the way out of the container, and on the documented self-host layout — the one where you download a single compose file — they now find it. The docs spell out that a backup is three things, not one: the database dump, your `.env` (without `TOKEN_ENCRYPTION_KEY` the restored secrets are unreadable), and your downloaded media. +- Plex works on the public compose files. The read-only media mount and its empty-volume fallback are in both of them, with a short setup section — before, the feature existed but the file you were told to run could not satisfy it. +- Siftlode is licensed, under AGPL-3.0. + +### Fixes + +- A download can no longer exceed your storage quota. The limit was only checked when you queued a job, so a single large download could pass that check and then fill the disk — and once you were at your cap, the download running at that moment was the one with no ceiling at all. Downloads are now bounded by what you have left, and a job that finds nothing left says so instead of running anyway. +- The download box refuses an address on the server's own network, and tells you why in your own language. Pasting an internal address used to make the server fetch it and hand the result back, which turned the box into a way to probe the machine Siftlode runs on. A malformed link is now refused as one rather than failing with a server error. +- One person holding down the sync button no longer spends the shared YouTube budget for everyone on the instance. Sync and playlist pull now say, in plain words, that you have synced a few times just now and that background syncing keeps running either way — a pace limit rather than a failure. +- A password-reset link opened in a tab you are already signed in to now says what to do with it. It used to do nothing at all: the page loaded, and the link appeared broken. The link itself stays in the address bar, so signing out from that same tab picks it up. +- Admin actions that fail now say so. Sending a confirmation link on an instance whose mail is misconfigured used to produce nothing on screen at all, which reads exactly like it worked. +- The row you click to open a user's account panel now looks clickable. + +### Internal + +- E12, five sprints. S1: the backup/restore scripts honour COMPOSE_FILE and the PowerShell pair moves the dump with `docker compose cp` rather than through the pipeline (binary does not survive it on 5.1, and `-Encoding Byte` does not exist on 7); docs gained an Upgrading section, and `siftlode release` now tags `v$VERSION` and refuses on a stale CHANGELOG.md. S2: AGPL-3.0, the Plex mount and `init: true` on the worker in both public compose files. S3 (SEC-12/13/14): a URL guard that resolves the host and refuses loopback/private/link-local at enqueue AND again in the worker, a generalised network-class error so it stops working as a port oracle, playlist_items/max_downloads/max_filesize derived from the caller's remaining quota, and a per-user cooldown on the manual sync triggers. S4: the three E9.5 deferrals (DX-16, DX-17, canonical resolution in the setup wizard). S5 (SEC-15/16): the account panel and the admin-issued set-password link, after a mockup round. +- The closing review ran six rounds across eight dimensions and converged 47 → 34 → 15 → 7 → 6 → 0. Round one's 47 deduplicated to 20 and 18 survived 60 adversarial verifier runs. Rounds two, four and five each found that a previous round's own fix had broken something — the ops half every time, because no gate can run shell scripts or a documented command. The three worth recording: the per-user quota refusal was writing onto a MediaAsset shared between users, so one person hitting their cap failed a second person's queued job for the same video with the first one's reason; the restore scripts' automatic restart re-ran `alembic upgrade head`, undoing the restore on the very rollback path the docs recommend; and the command printed in its place resolved to the other compose file, whose volumes differ, recreating the database empty. Two fixes were reverted rather than patched a third time. Round five also caught that the loop had been running seven of the gate's eight lanes. Residuals documented rather than closed: SEC-17 (redirects walk past the URL guard — the same socket-level fix as DNS rebinding), SEC-18 (the playlist push routes), SEC-19 (the edit path does not consult the byte cap). + ## 0.80.0 — 2026-09-05 Getting into Siftlode used to take nine steps, three of which could quietly end in nothing — and one of which deleted the password you had just chosen. It is now one mail and one click in the usual case, every screen says which of the two gates you are actually waiting on, and the messages arrive in your own language. diff --git a/VERSION b/VERSION index e0d6b5ea..c85a67dc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.80.0 \ No newline at end of file +0.81.0 \ No newline at end of file diff --git a/frontend/src/lib/releaseNotes.ts b/frontend/src/lib/releaseNotes.ts index 4be9bf6f..0b42ad58 100644 --- a/frontend/src/lib/releaseNotes.ts +++ b/frontend/src/lib/releaseNotes.ts @@ -14,6 +14,32 @@ export interface ReleaseEntry { } export const RELEASE_NOTES: ReleaseEntry[] = [ + { + version: "0.81.0", + date: "2026-09-05", + summary: + "If you run your own Siftlode, this one is mostly for you: there is now a way back from a bad upgrade, backup scripts that actually restore, and a way to let someone in on an instance that cannot send mail. If you just use Siftlode, the visible part is that a download can no longer quietly blow past your storage limit, and that the box refuses addresses on the server's own network.", + features: [ + "Admins get an account panel: click anyone in Users and it says, in one place, why that person can or cannot get in — whether their address is confirmed, whether an admin has approved them, whether they have a password, which Google account is attached, and whether their address is on the allow-list. Every recovery action for that account sits under the readout, so you pick one having read what is actually wrong instead of guessing.", + 'Someone locked out of an instance with no email setup can now be let back in. "Create a set-password link" gives you a one-time link to hand them however you like — chat, in person, on paper. It lasts 24 hours, works once, and signs out anyone already using that account. Issuing it changes nothing by itself: a misclick cannot lock anyone out.', + "Self-hosters can pin a version. Put `IMAGE_TAG=0.81.0` in your `.env` and Siftlode stays there until you change the line, so an upgrade happens when you decide it does. The docs now also carry a rollback recipe — and say plainly that restoring the dump you took first is the way back that does not lose data.", + "The backup and restore scripts work. On Windows they no longer corrupt the dump on the way out of the container, and on the documented self-host layout — the one where you download a single compose file — they now find it. The docs spell out that a backup is three things, not one: the database dump, your `.env` (without `TOKEN_ENCRYPTION_KEY` the restored secrets are unreadable), and your downloaded media.", + "Plex works on the public compose files. The read-only media mount and its empty-volume fallback are in both of them, with a short setup section — before, the feature existed but the file you were told to run could not satisfy it.", + "Siftlode is licensed, under AGPL-3.0.", + ], + fixes: [ + "A download can no longer exceed your storage quota. The limit was only checked when you queued a job, so a single large download could pass that check and then fill the disk — and once you were at your cap, the download running at that moment was the one with no ceiling at all. Downloads are now bounded by what you have left, and a job that finds nothing left says so instead of running anyway.", + "The download box refuses an address on the server's own network, and tells you why in your own language. Pasting an internal address used to make the server fetch it and hand the result back, which turned the box into a way to probe the machine Siftlode runs on. A malformed link is now refused as one rather than failing with a server error.", + "One person holding down the sync button no longer spends the shared YouTube budget for everyone on the instance. Sync and playlist pull now say, in plain words, that you have synced a few times just now and that background syncing keeps running either way — a pace limit rather than a failure.", + "A password-reset link opened in a tab you are already signed in to now says what to do with it. It used to do nothing at all: the page loaded, and the link appeared broken. The link itself stays in the address bar, so signing out from that same tab picks it up.", + "Admin actions that fail now say so. Sending a confirmation link on an instance whose mail is misconfigured used to produce nothing on screen at all, which reads exactly like it worked.", + "The row you click to open a user's account panel now looks clickable.", + ], + chores: [ + "E12, five sprints. S1: the backup/restore scripts honour COMPOSE_FILE and the PowerShell pair moves the dump with `docker compose cp` rather than through the pipeline (binary does not survive it on 5.1, and `-Encoding Byte` does not exist on 7); docs gained an Upgrading section, and `siftlode release` now tags `v$VERSION` and refuses on a stale CHANGELOG.md. S2: AGPL-3.0, the Plex mount and `init: true` on the worker in both public compose files. S3 (SEC-12/13/14): a URL guard that resolves the host and refuses loopback/private/link-local at enqueue AND again in the worker, a generalised network-class error so it stops working as a port oracle, playlist_items/max_downloads/max_filesize derived from the caller's remaining quota, and a per-user cooldown on the manual sync triggers. S4: the three E9.5 deferrals (DX-16, DX-17, canonical resolution in the setup wizard). S5 (SEC-15/16): the account panel and the admin-issued set-password link, after a mockup round.", + "The closing review ran six rounds across eight dimensions and converged 47 → 34 → 15 → 7 → 6 → 0. Round one's 47 deduplicated to 20 and 18 survived 60 adversarial verifier runs. Rounds two, four and five each found that a previous round's own fix had broken something — the ops half every time, because no gate can run shell scripts or a documented command. The three worth recording: the per-user quota refusal was writing onto a MediaAsset shared between users, so one person hitting their cap failed a second person's queued job for the same video with the first one's reason; the restore scripts' automatic restart re-ran `alembic upgrade head`, undoing the restore on the very rollback path the docs recommend; and the command printed in its place resolved to the other compose file, whose volumes differ, recreating the database empty. Two fixes were reverted rather than patched a third time. Round five also caught that the loop had been running seven of the gate's eight lanes. Residuals documented rather than closed: SEC-17 (redirects walk past the URL guard — the same socket-level fix as DNS rebinding), SEC-18 (the playlist push routes), SEC-19 (the edit path does not consult the byte cap).", + ], + }, { version: "0.80.0", date: "2026-09-05",