The auditors-audit patch: a fresh-eyes review of the 0.10.16/0.10.17 changes closed the gaps in yesterday's fixes (r442–r446), and install.sh — the one large artifact never deeply audited — got its first full pass (r447–r452), headlined by docker-mode upgrades finally getting the r087 treatment.
Fixed
- A failed docker-mode upgrade left the panel down with no recovery (r447). Bare metal has the full stop→rollback→restart machinery; docker mode had two bare
composecalls.docker compose up -drecreating a changed container stops and renames the old one before creating the new — a failed recreate (port collision, mount error, bad env) left the old container stopped and the panel dark, and a SIGTERM mid-up did the same. The previous container is captured before the recreate and started again when the new one does not land. - A docker-mode re-run silently reset an operator-chosen port (r448).
NINEDEPLOY_PORTwas force-upserted from the ambient environment on every run — an operator who installed on 8080 (the documented escape from an occupied 3000) got the mapping flipped to 3000 on the next upgrade, external access broken behind a green "Installation Complete", and a recreate failure into the r447 window when 3000 was busy. The port is read back from.envfirst now, the same pattern the JWT secret always used. - Operator-supplied
.envvalues rode through a sed replacement (r449). The docker-modeupsert_envinterpolated values intos|…|…|— a JWT secret or DNS token containing&(valid chars) silently corrupted the file,|aborted the run after the rewrite. Values are written with grep+printf append semantics; the bare-metal seds stay (their inputs are literals, generated hex, or email-regex-validated). - The installer could re-point a live install at a random clone (r452). INSTALL_DIR prefers a checkout in the cwd, so running the script from any clone on a host with a systemd install took the "upgrade" branch against the CLONE: production stopped, a fresh
.envminted over an empty.data, the unit re-rendered at the clone, and the panel came up empty with every deployment orphaned on disk. When the live unit'sWorkingDirectorydiffers from the resolved install dir, the installer now refuses loudly. (The panel's own self-update was immune — it pinsNINEDEPLOY_INSTALL_DIR.) .datawas world-readable (r451). The installer is meticulous about.envand backups; the data directory — home ofninedeploy.db(credential hashes, sessions),repos/checkouts (committed secrets included) and PM2's dump — was created with the ambient umask. It is0750on create now.NINEDEPLOY_BINDis also persisted to the docker-mode.envwhen provided, so the advertised manualdocker compose up -dno longer silently rebinds the panel to loopback.- The git upgrade path never warned it has no rollback (r450). Only the release-tarball path prepares a code-rollback point;
--channel main(and the tarball-fetch-failure fallback) swaps the tree with none, and a build failure surfaces as "The panel is DOWN" with no advance notice. The warning now fires BEFORE the swap. - The audit of the auditors — gaps in the 0.10.16/0.10.17 fixes (r442–r446). The SAML consumer read the provider config with a bare
JSON.parse, which the r435 boot normalization breaks for every legacy SAML row it serves — it reads through the envelope helper now (r442). The agent child-process scrub claimed to remove the enrolment token but the list missed the env var that actually carries it —NINEDEPLOY_ENROLMENT_TOKENandNINEDEPLOY_DNS_TOKENare scrubbed too (r443). Admin-forced password resets and SCIM deprovisioning revoke "every credential the account holds" without touching the studio-cookie epoch — a deactivated operator's 8-hour pre-authenticated database-GUI cookie (Redis studios even carry the decrypted password) kept working; both bump the epoch like self-service resets (r444). The kernelbackup.completedtype matches what the bridge emits (r445), and a key rotation skips a pre-r435 SSO row that escaped the boot normalization instead of aborting the sweep (r446).