release: the Linux / Windows updater signatures are made on the VDS (desktop-release add-remote, vds-key; tools/vds-sign.ts); the Mac no longer downloads those installers, verifies each returned .sig over its BLAKE2b-512 digest before publishing; release.ts --sign-local keeps the old path

This commit is contained in:
CRTkafa 2026-10-21 03:14:53 +07:00
parent d94bf67340
commit ef3c66e8f0
6 changed files with 444 additions and 51 deletions

View file

@ -95,10 +95,10 @@ Run it by hand from Actions > release with a `tag` (dry by default: only the pla
3. **Fast gate, commit, push:** `bun run ci:quick`, the commit as CRT, push to main, push the tag.
4. **In parallel:** `desktop-release.ts mac` (universal build, sign; Tauri notarizes the app while the boot check runs;
the DMG is notarized while the app and the updater bundle are checked, scanned and signed), Forgejo's ci run of the
bump commit (installers only) and release.yml's promotion. Meanwhile the candidate's Linux / Windows installers
and acceptance runs are downloaded.
5. **add, matrix, verify:** updater signatures of the Linux / Windows files, the 9-run acceptance matrix (strict) to
the release, `verify`.
bump commit (installers only) and release.yml's promotion. The Linux / Windows installers are not downloaded to
the Mac (only with `--sign-local`).
5. **add-remote, verify:** the VDS signs the Linux / Windows files (see "Updater signatures on the VDS" below); the
acceptance matrix only when the release's `TESTS` is on; `verify`.
6. **publish** with `--forgejo-tag`: the VDS fetches the Linux / Windows files from the Forgejo release over its own
network, rsync sends only the Mac's DMG and updater bundle, the VDS attaches those to the Forgejo release from its
copy, then the publish script swaps latest.json. The owner's uplink (about 0.5 to 1 MB/s) carries each Mac file
@ -129,8 +129,10 @@ the local folders, and prints the times.
- `bun tools/desktop-version.ts --set 0.8.5` and the CHANGELOG section, `bun run ci:quick`, commit, push, tag, push
the tag (release.yml promotes the candidate).
- `bun tools/desktop-release.ts mac --out ~/.storebound-releases/desktop/0.8.5`.
- `bun tools/release-candidate.ts fetch --sha <sha> --dir <dir>`, then `bun tools/desktop-release.ts add --out ...
--commit <sha> --run <run> <AppImage> <deb> <setup.exe>`.
- `bun tools/desktop-release.ts add-remote --out ... --host root@<vds> --assets <json> --commit <sha> --run <run>`
(the json: `[{name, url, sha256, size}]` of the release's installers, the SHA-256 from the candidate's
green.json). Fallback: `bun tools/release-candidate.ts fetch --sha <sha> --dir <dir>`, then
`bun tools/desktop-release.ts add --out ... --commit <sha> --run <run> <AppImage> <deb> <setup.exe>`.
- `bun tools/desktop-release.ts publish --out ... --forgejo-tag v0.8.5 --yes` (or `upload-forgejo`, then `publish`).
- `npm publish` of the same version: the owner's step (CONTRIBUTING.md).
@ -155,7 +157,30 @@ a new one under CRT's Settings > Applications with that scope, put it into the s
**Back up `updater.key`** (password manager or an offline copy). If it is lost, installed apps can never update
again: they only accept bundles signed with this key, so everyone would have to reinstall by hand. Never commit
it, never copy it to a runner. The Forgejo workflow builds unsigned installers, and the Mac signs them.
it, never copy it to a runner. The Forgejo workflow builds unsigned installers; the VDS signs the Linux / Windows
ones and the Mac its own.
### Updater signatures on the VDS (since 21 Oct 2026)
The Mac's line is too slow to download the ~120 MB AppImage, the deb and the exe just to sign them, so the
updater key has a second home on the VDS: `/root/.storebound-keys/updater.key` (dir 0700, file 0600, root; an
optional `updater.key.password` next to it, 0600, when the key has a password; today it has none).
- **Install or rotate:** `bun tools/desktop-release.ts vds-key` (host from `~/.storebound-keys/publish-host`, one ssh
connection). It sends the Mac's `updater.key` (and `updater.key.password`, if present) over ssh stdin, never
printed or on a command line, sets the modes, signs a test string on the VDS with the tauri signer and verifies it
here against tauri.conf.json's public key. Rotation: make the new key on the Mac (as in the table), update the
public key in tauri.conf.json and cli/lib/desktop-dist.ts, run `vds-key`.
- **In a release** (`tools/release.ts` step 5, `desktop-release.ts add-remote`, code in `tools/vds-sign.ts`): one ssh
script fetches the promoted release's installers into `/var/lib/storebound-desktop/incoming/<version>/`, checks
each SHA-256 against the candidate's green.json, signs with `bunx @tauri-apps/cli@<pinned> signer sign` (bun is on
the VDS; no minisign needed) and prints only `SIG <file> <blake2b-512> <size> <.sig>` lines. The Mac verifies every
signature over that digest with the public key (and that its trusted comment names the file) before it writes
anything, then writes the .sig files, latest.json, SHA256SUMS and `.remote.json` (the files that live only on the
VDS). `verify` and `publish` use `.remote.json`; publish re-checks those files' SHA-256 on the VDS and never
rsyncs them. The installers' privacy scan is the one of their build jobs.
- **Fallback:** `bun tools/release.ts <version> --resume --sign-local --yes` (or without `--resume`): the old path,
the installers downloaded to the Mac and signed there with `~/.storebound-keys/updater.key`.
## Privacy gate