Improvements and Fixes
- Clone major upgrade no longer fails at the check stage on instances that mount TLS certificates or other files into clones: the upgrade container now gets the volumes from
databaseContainer.containerConfig(!1206, #792) - The "Upgrade clone" button stays visible when clone upgrade is unavailable (for example,
provision.pgUpgradeImageis not set); it is disabled and shows the engine's reason in a tooltip (!1205) - Creating a clone for a restricted user no longer fails with
cannot alter partition ... with an incomplete detachwhen the snapshot holds a partition with a pendingDETACH PARTITION ... CONCURRENTLY; the detach is finalized in the clone (!1208, #795) - Clone state (
sessions.json) is written atomically, and the engine refuses to start on an unreadable state file; a crash in the middle of a write could previously lead to every clone being destroyed on the next start (!1198, #783) - A panic in a background job or an HTTP handler no longer terminates the engine, and data races in WebSocket token cleanup and webhook reload are fixed (!1198, !1199, #783, #784)
- Config reload is synchronized across engine services, fixing data races between a reload and in-flight requests; two concurrent full refreshes can no longer both start, and a clone being provisioned keeps its database config across a reload (!1202, #788)
- A rotated
verificationTokentakes effect on config reload instead of requiring a restart (!1199, #29) - A Postgres start timeout is reported as an error instead of success, and
POST /observation/stopno longer hangs when the observation session ended with an error (!1199, #784) - The pool is activated and branching is initialized when there are no retrieval jobs or the snapshot already exists (!1199, #784)
--extra-configand--tagsvalues without=makedblabreturn an error instead of panicking (!1199, #784)- Not-found and bad-request API errors return 404/400 instead of 500; percent-encoded snapshot IDs are accepted;
POST /snapshotreturns the snapshot model with correct sizes; an emptydeleteAtis rejected with 400; the log of a branch namedsnapshotis reachable (!1197, #782) - The OpenAPI spec matches the engine's routes and models, including 7 previously undocumented operations (!1196)
- The Logs tab no longer leaks WebSocket connections and auto-scrolls again, and a render error shows a message instead of a blank page (!1203, #787)
Security
- An empty
provision.upgradeImageAllowListnow allows clone upgrades only to images from the repository of the clone image instead of any repository; set["*"]to restore the previous behavior (breaking change of the default) (!1200, #786) - Host, user, database and table names are shell-quoted in logical dump and restore commands (!1200, #786)
- Physical-mode
envsvalues (WAL-G and pgBackRest credentials) are masked in the config view and inGET /admin/config; the configuration editor keeps the stored values on save (!1200, #786) - The HTTP server has read and idle timeouts and a 1 MiB request body limit (413
PAYLOAD_TOO_LARGE), and the API client applies a request timeout (!1200, #786) - Binaries are built with Go 1.26.8 (up from 1.26.7), and
golang.org/x/cryptois bumped to v0.57.0 (!1201) momentis bumped to 2.31.0 (CVE-2026-17495) anddompurifyto 3.4.16, with raised floors forfast-uri,brace-expansion,browserslist,js-yamland other transitive UI dependencies (!1210)
Internal
- Release tags are gated on the e2e matrix (PG 10-18) and the integration suite; publish jobs run only after the tests pass (!1201)
- ESLint and unit tests run for every UI package, including
@postgres.ai/shared(!1203, #787)