| … | … | @@ -40,29 +40,55 @@ At prep time this was **124 commits**. Open a PR from `feat/service-http-wiring` |
| 40 | 40 | rather than fast-forwarding — `rc.3` was previously cut from `main` by mistake |
| 41 | 41 | without the feature tree, and that is exactly the failure this gap invites. |
| 42 | 42 | |
| 43 | | ### 1b. The release signing key is not on this machine |
| 43 | ### 1b. Do NOT sign by hand — use `scripts/release.sh` |
| 44 | 44 | |
| 45 | | The fleet trusts exactly one signer, in both `fleet/allowed-signers` and the copy |
| 46 | | installed on the provisioned boxes (verified identical on miami): |
| 45 | `git tag -s` defaults to **GPG**, but the fleet verifies **SSH** signatures |
| 46 | (`ssh-ed25519` in `allowed-signers`). A hand-cut GPG tag produces a signature |
| 47 | every enforcing box rejects, and `gpg` will simply fail with "No secret key" |
| 48 | because no GPG key exists here. |
| 47 | 49 | |
| 50 | The repo ships a keyvault-integrated cutter that does the right thing: sign with |
| 51 | SSH from the vault, **self-verify against `fleet/allowed-signers` before pushing**, |
| 52 | push, and create the GitHub prerelease. |
| 53 | |
| 54 | ```bash |
| 55 | scripts/release.sh status # what is configured |
| 56 | scripts/release.sh cut v0.25.0-rc.5 # sign + verify + push + prerelease |
| 57 | ``` |
| 58 | |
| 59 | Two prerequisites, both currently unmet: |
| 60 | |
| 61 | **The vault is locked.** `status` reports |
| 62 | `locked: no agent running for ~/.keyvault/secrets.vault`, and consequently cannot |
| 63 | see the key (`signing key: NOT in vault` is what a locked vault looks like — it is |
| 64 | not proof the key is absent). Unlock first: |
| 65 | |
| 66 | ```bash |
| 67 | keyvault agent --daemonize |
| 68 | # or run the cut under: keyvault exec --scope hiverelay-release -- scripts/release.sh cut v0.25.0-rc.5 |
| 48 | 69 | ``` |
| 49 | | bigdestiny2@users.noreply.github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGxvfmV3/yKO0C5HMCGRiOMiqfEwkzr6/aMlz4TUfojO hiverelay-release |
| 70 | |
| 71 | **The signer principal does not match `allowed-signers`.** `release.sh` derives |
| 72 | `SIGNER_EMAIL` from `git config user.email`, which is |
| 73 | `33146784+bigdestiny2@users.noreply.github.com`, but the principal in |
| 74 | `fleet/allowed-signers` — and in the copy installed on every enforcing box — is |
| 75 | `bigdestiny2@users.noreply.github.com`, with no numeric prefix. Signing with the |
| 76 | default tags under a principal that is not in the file, so `verify_tag` on miami, |
| 77 | sydney, and amsterdam would refuse the checkout. Override it: |
| 78 | |
| 79 | ```bash |
| 80 | HIVERELAY_RELEASE_SIGNER_EMAIL=bigdestiny2@users.noreply.github.com \ |
| 81 | scripts/release.sh cut v0.25.0-rc.5 |
| 50 | 82 | ``` |
| 51 | 83 | |
| 52 | | None of the local keys match it (`cloudzy_hiverelay`, `id_ed25519`, |
| 53 | | `peerit_vps_deploy`), the ssh-agent is empty, and git has no signing config |
| 54 | | (`user.signingkey`, `gpg.format`, `tag.gpgsign` all unset). **Sign on whichever |
| 55 | | machine or token holds `hiverelay-release`**, or rotate the release key and |
| 56 | | redistribute `/etc/hiverelay/allowed-signers` fleet-wide. |
| 84 | `release.sh` self-verifies against `fleet/allowed-signers` before it pushes, so a |
| 85 | principal mismatch fails locally rather than shipping a tag the fleet rejects. |
| 57 | 86 | |
| 58 | 87 | Prior tags *are* signed — `git tag -v v0.24.3` errors only because local |
| 59 | | verification is unconfigured, not because the signature is missing. To verify |
| 60 | | locally: |
| 88 | verification is unconfigured, not because a signature is missing: |
| 61 | 89 | |
| 62 | 90 | ```bash |
| 63 | | git config gpg.ssh.allowedSignersFile "$PWD/fleet/allowed-signers" |
| 64 | | git config gpg.format ssh |
| 65 | | git tag -v v0.24.3 |
| 91 | git -c gpg.format=ssh -c gpg.ssh.allowedSignersFile="$PWD/fleet/allowed-signers" tag -v v0.24.3 |
| 66 | 92 | ``` |
| 67 | 93 | |
| 68 | 94 | ### 1c. `main`'s canary channel is parked at v0.24.3 |
| … | … | @@ -113,23 +139,20 @@ scp fleet/allowed-signers root@<box>:/etc/hiverelay/allowed-signers |
| 113 | 139 | |
| 114 | 140 | ## 2. Cut the release |
| 115 | 141 | |
| 116 | | Run from the repo, not `~`: |
| 117 | | |
| 118 | | ```bash |
| 119 | | cd /Users/localllm/Projects/pear-ecosystem/00-core/hiverelay && git tag -s v0.25.0-rc.5 -m "v0.25.0-rc.5 — restore orphaned lifecycle/gateway features" |
| 120 | | ``` |
| 121 | | |
| 122 | | Verify before pushing — this is the exact check each box performs: |
| 142 | From the repo root, with the vault unlocked (§1b). `release.sh` signs, self-verifies |
| 143 | against `fleet/allowed-signers`, pushes the tag, and creates the GitHub prerelease: |
| 123 | 144 | |
| 124 | 145 | ```bash |
| 125 | | git tag -v v0.25.0-rc.5 |
| 146 | cd /Users/localllm/Projects/pear-ecosystem/00-core/hiverelay && HIVERELAY_RELEASE_SIGNER_EMAIL=bigdestiny2@users.noreply.github.com scripts/release.sh cut v0.25.0-rc.5 |
| 126 | 147 | ``` |
| 127 | 148 | |
| 128 | | Then: |
| 149 | The tag must be **exactly** `v0.25.0-rc.5` — `release.sh status` cross-checks it |
| 150 | against `package.json`, and the updater's health gate compares the running |
| 151 | version against the tag. |
| 129 | 152 | |
| 130 | | ```bash |
| 131 | | git push origin v0.25.0-rc.5 |
| 132 | | ``` |
| 153 | `--promote-canary` also bumps `channels.json`. Do **not** use it here: §1d shows |
| 154 | the canary box is not actually self-updating, so promote deliberately (§4) after |
| 155 | provisioning. |
| 133 | 156 | |
| 134 | 157 | --- |
| 135 | 158 | |