## Summary
- fall back to the existing scoped `RELEASE_MANAGER_GATE_TOKEN` when
`SERVER_UPDATE_TOKEN` is absent
- record the exact frontend SHA through the release-gate endpoint, then
independently read it back
- preserve the legacy dedicated-token path when it is configured
- carry the scoped credential and exact run-attempt build ID through
normal releases, rollback recovery, and restore-on-failure
## Dependency
Depends on backend PR copenhagentruckwash/api#342 being merged and
deployed before this PR is merged.
## Verification
- focused release-gate updater test: 1 passed
- direct exact-SHA update/readback execution passed
- ESLint passed for changed JavaScript/tests
- Prettier passed for both workflows and changed JavaScript/tests
- Node syntax and `git diff --check` passed
The existing broader cPanel release test is also updated; the local
cached dependency set cannot collect that file because `jszip` is
absent, so protected CI remains the full-suite authority.
The production FTPS deploy now authenticates, but lftp exits when cPanel
returns 550 File exists for pre-created deployment directories. Use lftp
mkdir -p -f for the archive and activation directories so retries remain
idempotent while subsequent upload operations still surface real access
failures.\n\nVerification:\n- vitest tests/unit/cpanel-deploy.spec.js
(26 passed)\n- eslint scripts/release/cpanel-deploy-lib.mjs
tests/unit/cpanel-deploy.spec.js\n- git diff --check
Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>
## Summary
- feed the generated lftp command script directly over stdin
- avoid reopening `/dev/stdin`, which fails on the production hosted
runner
- keep FTP credentials out of process arguments
## Verification
- `vitest run tests/unit/cpanel-deploy.spec.js` (26/26)
- ESLint on changed files
- `git diff --check`
Supersedes the failed production release run 29948809036.
## Summary
- Preserve lftp stdout/stderr when the process exits non-zero.
- Surface bounded, whitespace-normalized diagnostics through the deploy
error.
- Redact FTPS host, username, password, path, URL userinfo, and encoded
secret forms.
## Verification
- `vitest run tests/unit/cpanel-deploy.spec.js` (25/25)
- `node --check scripts/release/cpanel-deploy-lib.mjs`
- `git diff --check`
This is the prerequisite diagnostic repair for failed Frontend Release
run 29854900889. Production was not switched during that failure.
## Summary
- remove the release packager's undeclared dependency on host `zip` and
`unzip` executables
- create and round-trip validate ZIP artifacts in Node with explicit
paths, permissions, timestamps, CRC checks, and resource limits
- preserve the existing archive filename, checksum, inventory, and
top-level `dist/` contract
## Root cause
After the prebuilt-dist integrity repair passed on master, Frontend
Release reached packaging and failed with `spawn zip ENOENT` on the
self-hosted runner. The workflow never installed or checked either
archive executable.
## Verification
- focused release/deployment tests: 57/57 passed
- packager tests: 9/9 passed, including empty `PATH`, cross-timezone
determinism, exact archive entries, permissions, and oversized
sparse-file rejection
- real production build: 735 files packaged successfully with an empty
`PATH`
- repeated real packaging produced byte-identical archives
- Info-ZIP test/list/checksum validation passed
- extraction under `umask 077`: every directory is `0755`; all 735 files
extracted
- extracted inventory exactly matches the source inventory
- ESLint and Prettier passed
Co-authored-by: Jeppe Bundgaard <jb@truckwash.dk>