rotation phase 2, executed: old folder stripped to the 0.3.5 manifest, local files renamed, relay on the new key, DL_TOKEN rotated; 7 October swap and the owner's rewrite checklist
logs.mjs --rotation reads the old fingerprints from the dated .old-* files once the .next files are gone; fresh-repo.sh scrubs the dated secret files too; ship-app.mjs mirrors payload-inputs.json.sig. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
442a1ccd0f
commit
2fa4cbccb1
4 changed files with 308 additions and 6 deletions
|
|
@ -7,6 +7,8 @@ installers of the day. Phase 2 is this file: the 0.3.6 build carries the new val
|
|||
across while the old folder still serves, then the old folder and the old key die, and only then the history is
|
||||
rewritten into a fresh repository (owner's decision, 5 October 2026; `docs/plans/history-rewrite.md`, option B).
|
||||
|
||||
REMINDER, 7 October 2026: once `node tools/logs.mjs --rotation` shows Sam's Mac 3a9bf309 on 0.3.8 (moved), run section 8f: the old intake key off the site, the relay and GitHub, the old folder off the downloads host; the old files wait in `~/igneum-dl-old-20261005` until 12 October.
|
||||
|
||||
No value is written here. Each is named by its fingerprint, the first 8 hex of sha256 over the trimmed value
|
||||
(`tr -d '[:space:]' < ~/.config/igneum/<file> | shasum -a 256 | cut -c1-8`; the app logs the same 8 characters):
|
||||
|
||||
|
|
@ -271,3 +273,294 @@ removed after the run; nothing left the Mac.
|
|||
two for a synced fleet; a machine that is off waits for its owner).
|
||||
5. Section 5: the deletion, in order.
|
||||
6. The owner's two GitHub settings (login rename, one owner); then section 6, the fresh repository, from a frozen tree.
|
||||
|
||||
## 8. Execution, 5 October 2026 (owner: "3 execute"; from 15:25 UTC, branch `rotation-3`)
|
||||
|
||||
The order the owner set differs from section 5 in one place: the old intake key stays until Sam's Mac is on 0.3.8,
|
||||
because that machine uploads with the old key until it updates. So steps 1, 2, 4 and 5 of section 5 ran today in the
|
||||
owner's order (folder, local files, relay, GitHub), and the intake swap (section 5 step 3, plus the same swap on the
|
||||
relay) is written out in 8f for 7 October.
|
||||
|
||||
### 8a. State at the start (`node tools/logs.mjs --rotation`, 15:25 UTC)
|
||||
|
||||
| Machine | Version | Key | Folder | Last upload (UTC) | State |
|
||||
|---|---|---|---|---|---|
|
||||
| mac-d937c69d (this Mac) | 0.3.8 | 477bb0ef | ed9c4d2e | 15:24:45 | moved |
|
||||
| win-1ccfe586 (PC 2) | 0.3.8 | 477bb0ef | ed9c4d2e | 15:24:29 | moved |
|
||||
| win-ae432dc7 (PC 1) | 0.3.8 | 477bb0ef | ed9c4d2e | 15:25:10 | moved |
|
||||
| win-37ba0461 | 0.3.7 | 477bb0ef | ed9c4d2e | 13:52:20 | moved |
|
||||
| mac-3a9bf309 (Sam's Mac, asleep) | 0.3.5 | - | - | 09:43:45 | unknown: reads the OLD folder and uploads with the OLD key |
|
||||
| mac-MacBook-Pro | ? | - | - | 4 Oct 01:46:13 | unknown: a pre-header upload, stopped for good; accounted for |
|
||||
|
||||
Only Sam's Mac is behind. Its 0.3.5 checks the OLD manifest once an hour when its node is synced, downloads the file
|
||||
named inside that manifest, and the new bundle carries the NEW manifest URL and the NEW key (section 2). Its job
|
||||
runner polls `dl/<old>/igneum-jobs.json` every 10 minutes; a missing file is a quiet error in 0.3.5
|
||||
(`jobrun.rs:338`, "no jobs file"), so the strip below costs it nothing.
|
||||
|
||||
### 8b. The OLD folder, stripped to what 0.3.5 needs (section 5 step 1, narrowed)
|
||||
|
||||
Kept, 4 files: `igneum-app-latest.json` (861 bytes, version 0.3.8, published 13:33:20Z, both platform URLs inside it
|
||||
name the OLD folder), `igneum-app-latest.json.sig`, `Igneum-Miner-0.3.8.dmg` (41,247,419) and
|
||||
`Igneum-Miner-Setup-0.3.8.exe` (19,794,320).
|
||||
|
||||
Before the strip, one copy into the NEW folder: `payload-inputs.json.sig` (129 bytes, byte-identical). The NEW folder
|
||||
had never received it: `tools/ship-app.mjs` FOLDER_FILES carried the zip, the json and the sha256 but not the
|
||||
signature, and `.github/workflows/windows.yml` fetches all four from the `DL_TOKEN` folder, which is the NEW folder
|
||||
from 8e on. Without the copy the next Windows build would have failed at the inputs step. The list is fixed on this
|
||||
branch (8h).
|
||||
|
||||
Removed: 56 files, 947,635,881 bytes, moved (not deleted) to `~/igneum-dl-old-20261005` (mode 0700), to be removed
|
||||
on 12 October (8f step 6):
|
||||
|
||||
| File | Bytes | Modified (BST) | sha256 (first 12) |
|
||||
|---|---|---|---|
|
||||
| `Igneum-Miner-0.1.0.dmg` | 16994336 | 2026-10-03T23:28 | 69904f6191e0 |
|
||||
| `Igneum-Miner-0.2.0.dmg` | 19924804 | 2026-10-04T08:57 | 2cb1c1d657bc |
|
||||
| `Igneum-Miner-0.3.0.dmg` | 20320453 | 2026-10-04T12:46 | 670d26b49904 |
|
||||
| `Igneum-Miner-0.3.1.dmg` | 20320855 | 2026-10-04T14:27 | 4b29d91cdd05 |
|
||||
| `Igneum-Miner-0.3.2.dmg` | 20519491 | 2026-10-04T15:17 | 26fdc1e854ea |
|
||||
| `Igneum-Miner-0.3.3.dmg` | 39775332 | 2026-10-04T17:56 | 3177bced3698 |
|
||||
| `Igneum-Miner-0.3.4.dmg` | 39798913 | 2026-10-04T21:20 | 1b346811b807 |
|
||||
| `Igneum-Miner-0.3.5.dmg` | 40027384 | 2026-10-05T07:39 | 2dad2b2615a6 |
|
||||
| `Igneum-Miner-0.3.6.dmg` | 40156607 | 2026-10-05T10:34 | fddf3580353d |
|
||||
| `Igneum-Miner-0.3.7.dmg` | 40156739 | 2026-10-05T11:16 | 8ee96b3b054f |
|
||||
| `Igneum-Miner-Setup-0.3.0.exe` | 44005195 | 2026-10-04T12:46 | 42b3f167ba25 |
|
||||
| `Igneum-Miner-Setup-0.3.1.exe` | 44013598 | 2026-10-04T14:32 | abc5b6226582 |
|
||||
| `Igneum-Miner-Setup-0.3.2.exe` | 44138229 | 2026-10-04T15:17 | f5e0763ff126 |
|
||||
| `Igneum-Miner-Setup-0.3.3.exe` | 44275245 | 2026-10-04T16:10 | 739f7e8af968 |
|
||||
| `Igneum-Miner-Setup-0.3.4.exe` | 44304304 | 2026-10-04T21:14 | 756ee2c0af7f |
|
||||
| `Igneum-Miner-Setup-0.3.5.exe` | 44447899 | 2026-10-05T07:38 | 0184abecaf99 |
|
||||
| `Igneum-Miner-Setup-0.3.6.exe` | 19536899 | 2026-10-05T10:34 | ca0fb9197bee |
|
||||
| `Igneum-Miner-Setup-0.3.7.exe` | 19784297 | 2026-10-05T11:16 | 2bacba64628b |
|
||||
| `Igneum-Wallet-0.1.1.dmg` | 19565360 | 2026-10-05T09:24 | 02446a480dae |
|
||||
| `Igneum-Wallet-0.1.2.dmg` | 19582462 | 2026-10-05T10:13 | 4ddfd7a07ac1 |
|
||||
| `Igneum-Wallet-0.1.3.dmg` | 19598469 | 2026-10-05T14:21 | d5b7945e4fe8 |
|
||||
| `build-inputs-t035.json` | 705 | 2026-10-05T10:17 | da48d4fbb7c4 |
|
||||
| `build-inputs-t035.sha256` | 65 | 2026-10-05T10:17 | caa267821f17 |
|
||||
| `build-inputs-t035.zip` | 7223133 | 2026-10-05T10:17 | d1dd841d9872 |
|
||||
| `build-inputs-t036.json` | 701 | 2026-10-05T10:17 | a0cdfe1a83c8 |
|
||||
| `build-inputs-t036.sha256` | 65 | 2026-10-05T10:17 | 37794f58f636 |
|
||||
| `build-inputs-t036.zip` | 7244256 | 2026-10-05T10:17 | c01a7525a903 |
|
||||
| `build-inputs-tests.json` | 1149 | 2026-10-05T10:04 | 0aa92c6a10f8 |
|
||||
| `build-inputs-tests.sha256` | 65 | 2026-10-05T10:04 | 216760a99a61 |
|
||||
| `build-inputs-tests.zip` | 8206608 | 2026-10-05T10:04 | f60713b133ec |
|
||||
| `build-inputs.json` | 1046 | 2026-10-05T10:12 | ed3e06ef5fdf |
|
||||
| `build-inputs.sha256` | 65 | 2026-10-05T10:12 | 0c0c2a0c186c |
|
||||
| `build-inputs.zip` | 8206958 | 2026-10-05T10:12 | 7c63df808331 |
|
||||
| `igneum-devnet-mac.dmg` | 17750579 | 2026-10-03T22:55 | c5b49d3c0097 |
|
||||
| `igneum-jobs.json` | 64416 | 2026-10-05T15:04 | 6812e147601f |
|
||||
| `igneum-jobs.json.sig` | 129 | 2026-10-05T15:04 | 3c3fbbeb258b |
|
||||
| `igneum-mine-test-v2.zip` | 4442068 | 2026-10-03T22:52 | 16abd0ff2a42 |
|
||||
| `igneum-mine-test-v3.zip` | 4442367 | 2026-10-03T22:52 | 646d6d4b659c |
|
||||
| `igneum-mine-test.zip` | 4431923 | 2026-10-03T22:52 | ab1951f1450d |
|
||||
| `igneum-node-windows-v4.zip` | 32973919 | 2026-10-04T08:57 | 8fbdc646596e |
|
||||
| `igneum-node-windows.zip` | 29454819 | 2026-10-03T22:52 | beadad43d1f0 |
|
||||
| `igneum-prove-wsl2-038.zip` | 1425452 | 2026-10-05T14:28 | 98c246146e89 |
|
||||
| `igneum-prove-wsl2.zip` | 295176 | 2026-10-05T11:48 | 75e3a96fed84 |
|
||||
| `igneum-wallet-latest.json` | 473 | 2026-10-05T14:21 | dc9bf8ac2bf5 |
|
||||
| `igneum-wallet-latest.json.sig` | 129 | 2026-10-05T14:21 | 1568dbdc33d0 |
|
||||
| `igneum-windows-app.zip` | 27591281 | 2026-10-05T14:33 | 8f08a3040ac7 |
|
||||
| `igneum-windows-ci.json` | 199 | 2026-10-05T14:33 | f8e099c8c2c3 |
|
||||
| `igneum-windows-v4.zip` | 64286803 | 2026-10-04T12:05 | a936c0f80715 |
|
||||
| `igneum-windows.zip` | 22885438 | 2026-10-03T22:52 | 862d61098c4b |
|
||||
| `igneum-worker-cuda.exe` | 1121792 | 2026-10-04T11:12 | 3f3f8337d53b |
|
||||
| `mingw-runtime-gcc13.zip` | 8338215 | 2026-10-05T10:52 | 7f030f253571 |
|
||||
| `mingw-runtime-x64.zip` | 9327832 | 2026-10-05T10:45 | b6671e811559 |
|
||||
| `payload-inputs.json` | 995 | 2026-10-05T14:25 | 403d0108b1b8 |
|
||||
| `payload-inputs.json.sig` | 129 | 2026-10-05T14:25 | a667d898e29e |
|
||||
| `payload-inputs.sha256` | 65 | 2026-10-05T14:25 | e627981e8b09 |
|
||||
| `payload-inputs.zip` | 26669995 | 2026-10-05T14:25 | b587ed19fac4 |
|
||||
|
||||
The deploy: one `vercel deploy --prod` of the downloads folder (`igneum-dl`), 15:29 UTC. Verified straight after:
|
||||
|
||||
| Check | Result |
|
||||
|---|---|
|
||||
| `packaging/ota/publish-manifest.sh --verify-only` (OLD folder, the default token at that moment) | version 0.3.8, byte-identical, signature OK, try 1 of 12 |
|
||||
| the same with `--dest "$DLSITE/dl/$NEW" --base-url https://dl.igneum.network/dl/$NEW` | version 0.3.8, byte-identical, signature OK, try 1 of 12 |
|
||||
| OLD folder, removed: `igneum-jobs.json`, `Igneum-Miner-0.3.7.dmg`, `build-inputs.zip`, `igneum-wallet-latest.json`, `payload-inputs.zip` | 404, 404, 404, 404, 404 |
|
||||
| OLD folder, kept: the manifest, its signature, the 0.3.8 DMG, the 0.3.8 installer | 200, 200, 200, 200 |
|
||||
| NEW folder: `payload-inputs.json.sig`, `igneum-jobs.json`, `igneum-jobs.json.sig`, `payload-inputs.zip` | 200, 200, 200, 200 |
|
||||
|
||||
Jobs whose `zip_url` names the OLD folder (the build jobs of the morning, `fetch-prove-038`, `rollback-035-pcs`) have
|
||||
all run on their machines; a machine never re-runs a job it has finished, so nothing waits on those URLs. The wallet
|
||||
manifest and DMGs left the OLD folder with everything else; the NEW folder carries `igneum-wallet-latest.json` and
|
||||
`Igneum-Wallet-0.1.3.dmg` (mirrored 14:22 UTC). The wallet publisher is not on master (the wallet branch): if it reads
|
||||
`dl-token` as every other publisher does, it writes the NEW folder from now on; confirm at the next wallet publish.
|
||||
|
||||
### 8c. The local files (section 5 step 2, as written)
|
||||
|
||||
```
|
||||
mv ~/.config/igneum/log-intake-key ~/.config/igneum/log-intake-key.old-2026-10-05
|
||||
mv ~/.config/igneum/log-intake-key.next ~/.config/igneum/log-intake-key
|
||||
mv ~/.config/igneum/dl-token ~/.config/igneum/dl-token.old-2026-10-05
|
||||
mv ~/.config/igneum/dl-token.next ~/.config/igneum/dl-token
|
||||
```
|
||||
|
||||
| File | Mode | Fingerprint |
|
||||
|---|---|---|
|
||||
| `log-intake-key` | 0600 | 477bb0ef |
|
||||
| `log-intake-key.old-2026-10-05` | 0600 | e2005de8 |
|
||||
| `dl-token` | 0600 | ed9c4d2e |
|
||||
| `dl-token.old-2026-10-05` | 0600 | df66a82c |
|
||||
|
||||
No `.next` file is left. Every script reads the NEW folder and the NEW key by default from here: `packaging/mac/packaged-config.sh --test`
|
||||
all checks passed; `packaging/ota/publish-manifest.sh --verify-only` (now the NEW folder) 0.3.8, byte-identical,
|
||||
signature OK; `publish-jobs.sh` has no next folder to mirror to, and the job another agent published at 15:32 UTC
|
||||
landed in the NEW folder only, as intended. Two tools read the renamed files wrongly and are fixed on this branch (8h):
|
||||
`tools/logs.mjs --rotation` printed the old fingerprints as 477bb0ef/ed9c4d2e (it took "old" from the plain files),
|
||||
and `tools/repo/fresh-repo.sh` built its secret rules from the four plain names only, so the rewrite would have left
|
||||
the OLD key and the OLD token in the history. The dated files stay until the fresh repository is pushed (8g step 10).
|
||||
|
||||
### 8d. The intake and the relay (section 5 step 3, split)
|
||||
|
||||
The site project `igneum` is untouched today: `LOG_INTAKE_KEY` (old) and `LOG_INTAKE_KEY_NEXT` (new) both stay, and
|
||||
a POST to `/api/log` answered 200 with the new key and 200 with the old key (baseline for 8f; label
|
||||
`rotation-check`). Sam's Mac keeps uploading with the old key until it has applied 0.3.8.
|
||||
|
||||
The relay project `igneum-relay` (`relay/lib/relay.mjs` `authed()` accepts `LOG_INTAKE_KEY` and `LOG_INTAKE_KEY_NEXT`
|
||||
since this morning): `LOG_INTAKE_KEY_NEXT` added (production, piped from `~/.config/igneum/log-intake-key`), and
|
||||
`DL_TOKEN` moved to the NEW token (`relay/api/console.mjs` reads the jobs file, the manifest and the CI record from
|
||||
that folder, and the OLD folder no longer carries them). Deployed from the main checkout's `relay/` on master 23d11d5
|
||||
with the command of `relay/README.md` (`vercel deploy --prod --yes --scope igneum`), 15:31 UTC.
|
||||
|
||||
| `POST https://relay.igneum.network/api/relay?fn=upload` with header `x-igneum-key` | Answer |
|
||||
|---|---|
|
||||
| the NEW key | `ok: true`, `api_version: 11`, 200 |
|
||||
| the OLD key | `ok: true`, `api_version: 11`, 200 |
|
||||
| a wrong key | 401 |
|
||||
|
||||
Relay env after: DL_TOKEN, LOG_INTAKE_KEY, LOG_INTAKE_KEY_NEXT, RELAY_KEY, RELAY_TOKEN, DATABASE_URL,
|
||||
BLOB_READ_WRITE_TOKEN. `node tools/console.mjs jobs` lists the jobs through the NEW folder.
|
||||
|
||||
### 8e. The GitHub secrets (section 5 step 4, the token half)
|
||||
|
||||
`gh auth status`: igneum-labs active. `DL_TOKEN` set 15:32:05Z from `~/.config/igneum/dl-token` (the NEW token);
|
||||
`DL_TOKEN_NEXT` deleted. `gh secret list`: DL_TOKEN (15:32:05Z), LOG_INTAKE_KEY (08:36:35Z, old), LOG_INTAKE_KEY_NEXT
|
||||
(08:36:36Z, new). On the runner (`windows.yml`): the payload inputs and the manifest folder come from `DL_TOKEN`, the
|
||||
NEW folder (which now carries `payload-inputs.json.sig`, 8b); `packaged-config.sh` packages the `.next` key, the new
|
||||
one, while `LOG_INTAKE_KEY_NEXT` exists, and the plain `LOG_INTAKE_KEY` once 8f has run.
|
||||
|
||||
### 8f. Deferred to 7 October: the old key and the old folder, exact commands
|
||||
|
||||
Condition, checked first and never skipped: Sam's Mac reports 0.3.8 with the new fingerprints. If it is still asleep
|
||||
on 7 October, wait; nothing below runs on a schedule.
|
||||
|
||||
```
|
||||
cd /Users/joshm/Projects/igneum && git checkout master && git pull
|
||||
node tools/logs.mjs --rotation | grep 3a9bf309 # must read: 0.3.8 477bb0ef ed9c4d2e ... moved
|
||||
gh auth status # igneum-labs active
|
||||
|
||||
# 1. the site: LOG_INTAKE_KEY becomes the new value, LOG_INTAKE_KEY_NEXT goes, then a production deploy
|
||||
cd site
|
||||
npx --yes vercel@latest --global-config ~/.config/igneum/vercel env rm LOG_INTAKE_KEY production --scope igneum --yes
|
||||
tr -d '[:space:]' < ~/.config/igneum/log-intake-key | npx --yes vercel@latest --global-config ~/.config/igneum/vercel env add LOG_INTAKE_KEY production --scope igneum
|
||||
npx --yes vercel@latest --global-config ~/.config/igneum/vercel env rm LOG_INTAKE_KEY_NEXT production --scope igneum --yes
|
||||
cd ..
|
||||
git push origin master # the GitHub integration deploys; if master has nothing new: the hand deploy of packaging/README-ship.md
|
||||
# the old key is dead (401), the new one lives (200)
|
||||
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H "x-igneum-key: $(tr -d '[:space:]' < ~/.config/igneum/log-intake-key.old-2026-10-05)" -H 'Content-Type: application/json' -d '{"label":"rotation-check","machine":"mac","run_id":"rotation-check","lines":"old key must be refused"}' https://igneum-six.vercel.app/api/log
|
||||
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H "x-igneum-key: $(tr -d '[:space:]' < ~/.config/igneum/log-intake-key)" -H 'Content-Type: application/json' -d '{"label":"rotation-check","machine":"mac","run_id":"rotation-check","lines":"new key accepted"}' https://igneum-six.vercel.app/api/log
|
||||
|
||||
# 2. the relay: the same swap, then its own deploy (relay/README.md)
|
||||
cd relay
|
||||
npx --yes vercel@latest --global-config ~/.config/igneum/vercel env rm LOG_INTAKE_KEY production --scope igneum --yes
|
||||
tr -d '[:space:]' < ~/.config/igneum/log-intake-key | npx --yes vercel@latest --global-config ~/.config/igneum/vercel env add LOG_INTAKE_KEY production --scope igneum
|
||||
npx --yes vercel@latest --global-config ~/.config/igneum/vercel env rm LOG_INTAKE_KEY_NEXT production --scope igneum --yes
|
||||
npx --yes vercel@latest --global-config ~/.config/igneum/vercel deploy --prod --yes --scope igneum
|
||||
cd ..
|
||||
# old key 401, new key 200 (the answer carries a Blob client token: print the status only)
|
||||
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H "x-igneum-key: $(tr -d '[:space:]' < ~/.config/igneum/log-intake-key.old-2026-10-05)" -H 'Content-Type: application/json' -d '{"name":"rotation-check.txt","size":10}' 'https://relay.igneum.network/api/relay?fn=upload'
|
||||
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H "x-igneum-key: $(tr -d '[:space:]' < ~/.config/igneum/log-intake-key)" -H 'Content-Type: application/json' -d '{"name":"rotation-check.txt","size":10}' 'https://relay.igneum.network/api/relay?fn=upload'
|
||||
|
||||
# 3. GitHub: LOG_INTAKE_KEY carries the new value, LOG_INTAKE_KEY_NEXT goes
|
||||
tr -d '[:space:]' < ~/.config/igneum/log-intake-key | gh secret set LOG_INTAKE_KEY --repo igneum-network/igneum
|
||||
gh secret delete LOG_INTAKE_KEY_NEXT --repo igneum-network/igneum
|
||||
gh secret list --repo igneum-network/igneum # DL_TOKEN, LOG_INTAKE_KEY
|
||||
|
||||
# 4. the OLD folder: its last 4 files join the holding folder, one deploy, 404
|
||||
DLSITE="$(tr -d '[:space:]' < ~/.config/igneum/dlsite-dir)"; OLD="$(tr -d '[:space:]' < ~/.config/igneum/dl-token.old-2026-10-05)"
|
||||
mkdir -p ~/igneum-dl-old-20261005/last-manifest && mv "$DLSITE/dl/$OLD"/* ~/igneum-dl-old-20261005/last-manifest/ && rmdir "$DLSITE/dl/$OLD"
|
||||
ls "$DLSITE/dl" | wc -l # 1
|
||||
(cd "$DLSITE" && npx --yes vercel@latest --global-config ~/.config/igneum/vercel deploy --prod --yes)
|
||||
curl -s -o /dev/null -w '%{http_code}\n' "https://dl.igneum.network/dl/$OLD/igneum-app-latest.json" # 404
|
||||
packaging/ota/publish-manifest.sh --verify-only # the NEW folder: live, byte-identical, signature OK
|
||||
|
||||
# 5. an hour later: every row moved (mac-MacBook-Pro stays unknown: stopped 4 October)
|
||||
node tools/logs.mjs --rotation
|
||||
|
||||
# 6. on 12 October, and only after 8g step 10 has pushed the fresh repository (the rewrite reads the dated files)
|
||||
rm -rf ~/igneum-dl-old-20261005
|
||||
rm -P ~/.config/igneum/log-intake-key.old-2026-10-05 ~/.config/igneum/dl-token.old-2026-10-05
|
||||
```
|
||||
|
||||
After step 3 the 0.2.0 launcher machines (`proto-cuda/windows-app`, `windows-miner`, the old key in `upload-log.bat`)
|
||||
upload nothing, which is the intent of section 5.
|
||||
|
||||
### 8g. The owner's checklist: the login rename and the fresh repository (about twenty minutes)
|
||||
|
||||
Before: 8f done (the old values are dead values), `gh auth status` igneum-labs active, and
|
||||
`~/.config/igneum/pytools/git_filter_repo.py` present (copied today from the dry run's download, version a40bce5;
|
||||
if missing: `python3 -m pip install --target ~/.config/igneum/pytools git-filter-repo`). Browser work in the
|
||||
"[user] (igneum.network)" Chrome profile. `<new>` is the handle: letters, digits, hyphens, no name.
|
||||
|
||||
1. (1 min) Pick `<new>` and the repository name. `igneum-core` is the script's default; the commands below use it.
|
||||
2. (3 min) GitHub, signed in as igneum-labs: Settings > Account > Change username: `igneum-labs` to `<new>`. The
|
||||
noreply id 337424239 stays, so the commit address becomes `337424239+<new>@users.noreply.github.com`. Then the
|
||||
organisation igneum-network > People: [second-owner-login] leaves the owners (remove from the organisation). Check
|
||||
the profile and the organisation: no name, no location, no personal avatar, 2FA on, the public members list empty.
|
||||
Nothing on this Mac breaks: the token survives a rename and `gh auth token --user igneum-labs` reads it by the
|
||||
stored name; the tidy-up is step 10.
|
||||
3. (2 min) Freeze: every agent commits and pushes its branch and stops; no ship, no merge, no job publish that
|
||||
commits. Then, from the main checkout:
|
||||
`gh pr list --repo igneum-network/igneum` (must be empty) and
|
||||
`git -C ~/Projects/igneum worktree list > ~/igneum-worktrees-$(date -u +%Y%m%d).txt` (42 worktrees today).
|
||||
The freeze holds until step 10 is done.
|
||||
4. (4 min) The pass, from the main checkout on master, nothing pushed by the script:
|
||||
```
|
||||
cd ~/Projects/igneum && git checkout master && git pull
|
||||
IGNEUM_FILTER_REPO=~/.config/igneum/pytools/git_filter_repo.py tools/repo/fresh-repo.sh --new-login <new> --new-repo igneum-network/igneum-core --work ~/igneum-rewrite
|
||||
```
|
||||
Add `--public-claude-md <file>` when the scrubbed `CLAUDE.md` of `docs/fud-fixes.md` section 5 step 2 exists;
|
||||
without it the private `CLAUDE.md` stays in every commit and the repository must stay private. Expected, against
|
||||
the dry run of section 6: about 353 commits, 1 identity (`<new>`), 0 stamps off `+0000`, 0 commits touching the
|
||||
four dropped files, 0 secret lines (the rules now carry 4 values: 2 current, 2 dated), 0 identity lines,
|
||||
0 lines of the old login, then `clean.` and the printed push commands. On `NOT CLEAN`: stop, keep
|
||||
`~/igneum-rewrite/report.txt`, ask.
|
||||
5. (2 min) The push, the script's printed lines:
|
||||
```
|
||||
gh repo create igneum-network/igneum-core --private --description 'Igneum: the GPU-mined zkEVM L1' --disable-wiki
|
||||
cd ~/igneum-rewrite/clone && git remote add origin https://github.com/igneum-network/igneum-core.git && git push --mirror origin
|
||||
```
|
||||
On GitHub: default branch master, the commit count of step 4, author `<new>` on the newest and the oldest commit.
|
||||
6. (1 min) The two secrets on the new repository (two after 8f):
|
||||
`tr -d '[:space:]' < ~/.config/igneum/dl-token | gh secret set DL_TOKEN --repo igneum-network/igneum-core`,
|
||||
the same for `log-intake-key` into `LOG_INTAKE_KEY`, then `gh secret list --repo igneum-network/igneum-core`.
|
||||
7. (3 min) Vercel, team igneum, project igneum > Settings > Git: disconnect `igneum-network/igneum`, connect
|
||||
`igneum-network/igneum-core`, production branch master. Then one push to master from the new checkout (step 10)
|
||||
triggers the first deploy; `curl -sI https://igneum.network | head -1` reads 200. The relay and the downloads
|
||||
folder deploy by CLI and have no Git link: nothing to re-link.
|
||||
8. (1 min) Archive `igneum-network/igneum` (Settings > Archive this repository). Private, never deleted the same day.
|
||||
9. (3 min) Re-clone and re-identify:
|
||||
```
|
||||
cd ~/Projects && mv igneum igneum-old-history && git clone https://github.com/igneum-network/igneum-core.git igneum
|
||||
cd igneum && git config user.name <new> && git config user.email 337424239+<new>@users.noreply.github.com
|
||||
gh auth logout --user igneum-labs && gh auth login --web --hostname github.com # as <new>
|
||||
git config credential.https://github.com.helper '' && git config --add credential.https://github.com.helper '!f() { echo username=<new>; echo "password=$(gh auth token --user <new> 2>/dev/null)"; }; f'
|
||||
mv ../igneum-old-history/vendor ./vendor # gitignored: the fork worktrees and their targets
|
||||
git commit --allow-empty -m "fresh repository: first push" && git push origin master # the deploy of step 7
|
||||
```
|
||||
The private `CLAUDE.md` names the login and the repository: update both lines in the same commit (or the scrubbed
|
||||
file of step 4).
|
||||
10. (0 min, each agent) Unfreeze: every agent removes its old worktree directory and re-creates it from the new
|
||||
checkout, `git -C ~/Projects/igneum worktree add ../igneum-wt-<name> <branch>`; never a merge of an old-id branch
|
||||
into a new one. `TZ=UTC` in every shell that commits. `~/igneum-old-history` and the dated secret files go on
|
||||
12 October (8f step 6).
|
||||
|
||||
### 8h. What this branch changes (`rotation-3`)
|
||||
|
||||
| File | Change |
|
||||
|---|---|
|
||||
| `tools/logs.mjs` | `--rotation`: once no `.next` file exists, the "old" fingerprints come from the newest `log-intake-key.old-<date>` and `dl-token.old-<date>` instead of the plain files (which are the new values after the rename); the summary line says which. `--self-test` passes |
|
||||
| `tools/repo/fresh-repo.sh` | the secret rules take every `log-intake-key.old-*` and `dl-token.old-*` file next to the four names, so the rewrite scrubs the old values after the rename; the count line no longer says "of 4" |
|
||||
| `tools/ship-app.mjs` | `FOLDER_FILES` carries `payload-inputs.json.sig` (the mirror step had left the signature behind; `windows.yml` fetches it). `--self-test` passes |
|
||||
| this file | section 8 |
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
// while any machine still reports with the old values
|
||||
// node tools/logs.mjs --self-test the header parser on sample lines
|
||||
// Reads DATABASE_URL from ~/.config/igneum/env. No dependencies: Neon HTTP SQL over fetch.
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import { createHash } from 'node:crypto';
|
||||
|
||||
|
|
@ -80,7 +80,13 @@ const [runId, flag] = process.argv.slice(2);
|
|||
if (runId === '--rotation') {
|
||||
const cfg = `${homedir()}/.config/igneum`;
|
||||
const want = { key: fingerprintFile(`${cfg}/log-intake-key.next`) || fingerprintFile(`${cfg}/log-intake-key`), folder: fingerprintFile(`${cfg}/dl-token.next`) || fingerprintFile(`${cfg}/dl-token`) };
|
||||
const old = { key: fingerprintFile(`${cfg}/log-intake-key`), folder: fingerprintFile(`${cfg}/dl-token`) };
|
||||
// the old values: the plain files while the .next files exist (phase 2 before the rename); after the rename
|
||||
// (plan section 5 step 2) the newest dated copy, log-intake-key.old-<date> and dl-token.old-<date>
|
||||
const dated = name => { try { return readdirSync(cfg).filter(f => f.startsWith(`${name}.old-`)).sort().reverse().map(f => `${cfg}/${f}`)[0] || ''; } catch { return ''; } };
|
||||
const renamed = !existsSync(`${cfg}/log-intake-key.next`) && !existsSync(`${cfg}/dl-token.next`);
|
||||
const old = renamed
|
||||
? { key: fingerprintFile(dated('log-intake-key')), folder: fingerprintFile(dated('dl-token')) }
|
||||
: { key: fingerprintFile(`${cfg}/log-intake-key`), folder: fingerprintFile(`${cfg}/dl-token`) };
|
||||
// the latest upload per app label (mac-<id8>, win-<id8>); the header lines sit in the first bytes, the config line
|
||||
// may repeat after an OTA restart, so the whole upload is parsed
|
||||
const rows = await sql(`
|
||||
|
|
@ -96,7 +102,7 @@ if (runId === '--rotation') {
|
|||
return { label: r.label, machine: r.machine, version: p.version || '?', key: p.keyFp || '-', folder: p.folderFp || '-', sources: [p.keySource, p.manifestSource].filter(Boolean).join(' / ') || '-', last_received: new Date(r.received_at).toISOString().replace('T', ' ').slice(0, 19) + ' UTC', state: ok ? 'moved' : p.keyFp === old.key || p.folderFp === old.folder ? 'OLD' : 'unknown' };
|
||||
}).sort((a, b) => a.state.localeCompare(b.state) || a.label.localeCompare(b.label));
|
||||
console.table(table);
|
||||
console.log(`expected: key ${want.key || '?'} folder ${want.folder || '?'} (from the .next files when they exist); old: key ${old.key || '?'} folder ${old.folder || '?'}`);
|
||||
console.log(`expected: key ${want.key || '?'} folder ${want.folder || '?'} (from the .next files when they exist, else the plain files); old: key ${old.key || '?'} folder ${old.folder || '?'} (${renamed ? 'from the dated .old-* files' : 'from the plain files'})`);
|
||||
console.log(`${moved} machine(s) on the new key and folder, ${stale} not yet; a machine silent for over a day is listed by its last upload`);
|
||||
process.exit(stale ? 1 : 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,12 +93,15 @@ LAST_NAMES="$(printf '%s\n' "$PERSONAL_NAMES" | awk 'NF>=2{print $NF}' | sort -u
|
|||
SECOND_LOGINS="$(printf '%s\n' "$PERSONAL_EMAILS" | sed -nE 's/^[0-9]+\+([A-Za-z0-9-]+)@users\.noreply\.github\.com$/\1/p' | grep -v "^$STANDING_LOGIN$" | sort -u || true)"
|
||||
# the other businesses named in the plan (brand names, not people)
|
||||
OTHER_BUSINESSES='[other-business]|[other-business]|[other-business]|[other-business]|[other-business]'
|
||||
# the secrets: whichever of the four files exist
|
||||
# the secrets: whichever of the four files exist, plus every dated copy the rotation left behind
|
||||
# (log-intake-key.old-<date>, dl-token.old-<date>: rotation phase 2 section 5 step 2 renames the .next files to the
|
||||
# plain ones and keeps the old values dated, and those old values are the ones the history carries)
|
||||
SECRET_FILES=(); for n in log-intake-key log-intake-key.next dl-token dl-token.next; do [ -f "$HOME/.config/igneum/$n" ] && SECRET_FILES+=("$HOME/.config/igneum/$n"); done
|
||||
for f in "$HOME/.config/igneum"/log-intake-key.old-* "$HOME/.config/igneum"/dl-token.old-*; do [ -f "$f" ] && SECRET_FILES+=("$f"); done
|
||||
|
||||
say "standing login: $STANDING_LOGIN (noreply id $STANDING_ID)${NEW_LOGIN:+ -> $NEW_LOGIN}"
|
||||
say "personal identities in the history: $(printf '%s\n' "$PERSONAL_PAIRS" | grep -c . || true) (names $(printf '%s\n' "$PERSONAL_NAMES" | grep -c . || true), addresses $(printf '%s\n' "$PERSONAL_EMAILS" | grep -c . || true), second owner logins $(printf '%s\n' "$SECOND_LOGINS" | grep -c . || true))"
|
||||
say "secret files for the rules: ${#SECRET_FILES[@]} of 4"
|
||||
say "secret files for the rules: ${#SECRET_FILES[@]} (the four names plus dated .old-* copies; 4 are needed once the rotation has renamed: 2 current, 2 old)"
|
||||
|
||||
# the rule files
|
||||
REPLACE="$RULES/replace.txt"; MAILMAP="$RULES/mailmap"; IDENT="$RULES/identity.pl"; SECRETS="$RULES/secrets.pl"
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ const DEST_NEXT = BOTH && DLSITE && TOKEN_NEXT ? join(DLSITE, 'dl', TOKEN_NEXT)
|
|||
const BASE_NEXT = `https://dl.igneum.network/dl/${TOKEN_NEXT}`;
|
||||
// the folder-level files the apps and the CI read next to the manifest (jobs, the CI's inputs, the CI record, the
|
||||
// WSL2 prover zip): mirrored into the NEXT folder when present in the current one
|
||||
const FOLDER_FILES = ['igneum-jobs.json', 'igneum-jobs.json.sig', 'payload-inputs.zip', 'payload-inputs.json', 'payload-inputs.sha256', 'igneum-windows-ci.json', 'igneum-prove-wsl2.zip'];
|
||||
const FOLDER_FILES = ['igneum-jobs.json', 'igneum-jobs.json.sig', 'payload-inputs.zip', 'payload-inputs.json', 'payload-inputs.json.sig', 'payload-inputs.sha256', 'igneum-windows-ci.json', 'igneum-prove-wsl2.zip'];
|
||||
const DMG_NAME = `Igneum-Miner-${VERSION}.dmg`;
|
||||
const SETUP_NAME = `Igneum-Miner-Setup-${VERSION}.exe`;
|
||||
const ZIP_NAME = 'igneum-windows-app.zip';
|
||||
|
|
|
|||
Loading…
Reference in a new issue