changelog and spec: dry run complete, restore 0.0.1, record deviations 25 and 26
Gates / test (push) Successful in 1m18s
Gates / test-aarch64 (push) Successful in 5m4s
Gates / frontend (push) Successful in 49s
Gates / package (push) Successful in 5m24s
Gates / container (push) Successful in 2m18s
CI / gates (push) Successful in 14m54s

This commit is contained in:
2026-08-08 21:43:36 +02:00
parent 51d8281abb
commit 31a6f0c5e5
3 changed files with 43 additions and 15 deletions
+41 -7
View File
@@ -620,19 +620,47 @@ was reproduced before it was fixed.
which moved to `web/scripts/bundledPackages.mjs` with its own vitest
coverage and an `npm run assert-bundled` entry point.
**Secret contract change:** `RELEASE_GPG_SUBKEY` becomes
`RELEASE_GPG_SUBKEY` and holds `base64 -w0` of the armored
**Secret contract change:** `RELEASE_GPG_SUBKEY` keeps its name but now
holds `base64 -w0` of the armored
`--export-secret-subkeys` output rather than the armored text. Manual
prerequisite 1 and 3 change accordingly. The tool decodes it in memory and
writes it to a mode-600 file inside the temporary `GNUPGHOME`. A single-line
secret is one the masker can actually mask.
25. **The first signing subkey was leaked into a job log and rotated.** Dry-run
attempt 3 failed inside the credential-less refetch, and the runner printed
the failing step's env block; the multiline armored `RELEASE_GPG_SUBKEY`
escaped the per-line masker while the single-line passphrase was masked.
Exposure: the passphrase-protected secret subkey only — the passphrase and
the primary key were never on the runner. Response: both runs that ever saw
the secret were deleted (verified 404 via the API and absent from
`actions_log` on disk), subkey `B281CECC…` was revoked with the primary,
and its replacement `019D00DF…` is the pinned `RELEASE_SIGNING_FPR`. The
base64 contract in deviation 24 is the preventive half of this record.
26. **The image is named by the public registry host, never the server URL.**
Attempt 4 reached the registry and failed at `docker login gitea:3000`:
inside the cluster `GITHUB_SERVER_URL` is `http://gitea:3000`, docker
refuses plain-http registries, and an image named `gitea:3000/…` would be
unpullable from anywhere that matters — a wrong name that would have been
written into the released `IMAGE-DIGEST.txt`. `release.yml` now pins
`REGISTRY_HOST: git.mial.net`; the tool uses it for docker and image
naming, and keeps the internal URL for the manifest probe (same registry,
no TLS dependency in the tool). The old shell had the identical latent bug;
no run ever reached it.
### Not verified, and why
- **No workflow has ever executed.** `release.yml` and `gates.yml` were validated
by YAML parse and `bash -n`, plus two steps lifted out and run directly: the
registry probe against a fake registry (five response shapes) and the whole
bundled-package check against the real `web/` build, proven able to fail.
- **The workflows' validation history.** Before any live run, `release.yml` and
`gates.yml` were validated by YAML parse and `bash -n`, plus two steps lifted
out and run directly: the registry probe against a fake registry (five
response shapes) and the bundled-package check against the real `web/` build,
proven able to fail. The live dry run then superseded this: attempt 5
published `v0.0.0` end to end — guard, gates, image push to both platforms,
binary-identity assertion, signing, draft, `:latest`, publication — and the
assets verified from a clean directory (checksums OK, signature good under
the rotated subkey). The throwaway release, tag and registry versions were
deleted afterwards.
Everything else that talks to the registry or the Gitea API — `buildx build
--push`, `imagetools`, draft creation, asset upload, publication, the
adopt-an-existing-tag path — is unexercised.
@@ -680,7 +708,13 @@ was reproduced before it was fixed.
removing an inventory entry, staling a dependency version, staling the Zig
version, changing the base image digest, editing a pinned licence text and
dropping a package from the recorded bundle each produce a named failure.
- [ ] A dry run of `release.yml` completes with publication disabled.
- [x] A dry run of `release.yml` completes with publication disabled. Done with
a disposable published tag instead: publication cannot be disabled without
forking the flow it is supposed to prove, so `v0.0.0` ran the real path
end to end — five assets, verifying checksums and signature, a
multi-architecture image — and was then deleted (release, git tag, both
registry versions). Five attempts; the failures and their fixes are
deviations 23-26.
- [ ] `v0.0.1` is published: five assets, a verifying signature, and an image at
`git.mial.net/mokhtar/nxdns:0.0.1` and `:latest`.
- [ ] `docs/how-to/verify-a-release.md` was followed end to end against the