26.09.0
LatestThings that had never worked
66 fixes, and the theme is not regressions — it is features that had never worked at all. Every MFA recovery code the system had ever issued was rejected before verification. Restoring a config-only backup NULLed every credential secret in the organization and reported success. Plugin install was impossible on any production deployment. The HA overlay could not start, and streaming replication had never once worked. Nearly all of it was found by RUNNING the product on a clean Linux box, from a fresh clone, rather than by reading it.
Upgrading: Pull, rebuild, restart. The migration chain runs itself and was verified in place from 26.08.4 on existing volumes. Two things do not apply themselves: docker/postgres/init-replication.sh only runs on a FRESH Postgres volume, so enabling --ha over an existing single-node install needs the manual command in that script's header; and .env.max.example no longer enables the dr profile, which started an rclone container that cannot work without operator credentials.
- FixedMFA recovery codes are minted at 10 characters and the login schema capped the field at 8, so every recovery code the system had ever issued was rejected before verification.
- SecurityA camera stream token, designed to be safe in a URL query string, authenticated the entire REST API with its owner's full role. The scope check existed on the WebSocket and on no other route.
- FixedRestoring a config-only backup with “Overwrite existing” NULLed every credential secret in the organization and reported success.
- FixedPlugin install was impossible on any production deployment: the volume mounted over a path the image never creates, so it was root-owned while the container runs as uid 1001. Firmware upload, evidence export and the backup destination had the same fault.
- Fixed./install.sh was not executable. Fifteen of nineteen tracked shell scripts were committed non-executable, so the documented first command failed with Permission denied on every fresh clone.
- FixedEvery event a Celery task published was silently discarded: the bus only fanned out to Redis when a client was set, and nothing in the Celery bootstrap ever set one.
- FixedThe HA overlay could not start. pgbouncer's tmpfs was owned by uid 999 while its image runs as uid 70, and the streaming-replication role had never been created by anything. --tier max --ha now brings up 19/19 healthy and passes a Sentinel failover drill with the replica promoted in about eight seconds.
- FixedChanging your own password and enrolling MFA were unreachable from the shipped UI.
- FixedThree API endpoints were unreachable because a catch-all route was registered ahead of them, including a certificate delete that dispatched to the VM-delete handler.
- SecurityThe edge CSP no longer permits arbitrary WebSocket hosts; the hardening had been applied to API responses and not to the page. A factory reset could be confirmed with the string “false”.