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>
566 lines
44 KiB
Markdown
566 lines
44 KiB
Markdown
# Rotation phase 2: the 0.3.6 handover, the deletion of the old folder and key, the fresh repository (5 October 2026)
|
|
|
|
Internal. Phase 1 (4 October, 19:25 UTC) generated the NEXT intake key and the NEXT downloads token into
|
|
`~/.config/igneum/log-intake-key.next` and `~/.config/igneum/dl-token.next`, taught `site/api/log.mjs` to accept
|
|
`LOG_INTAKE_KEY_NEXT` next to `LOG_INTAKE_KEY`, and staged a second downloads folder `dl/<new token>/` with the
|
|
installers of the day. Phase 2 is this file: the 0.3.6 build carries the new values, every installed 0.3.5 is carried
|
|
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):
|
|
|
|
| Value | File | Fingerprint | Where it lives today |
|
|
|---|---|---|---|
|
|
| old intake key | `~/.config/igneum/log-intake-key` | `e2005de8` | every installed app's `igneum-app.json` (0.3.0 to 0.3.5); the site project's `LOG_INTAKE_KEY`; 6 tracked files until this branch, 8 commits of the history |
|
|
| new intake key | `~/.config/igneum/log-intake-key.next` | `477bb0ef` | nowhere yet (the site accepts it once `LOG_INTAKE_KEY_NEXT` is set) |
|
|
| old downloads token | `~/.config/igneum/dl-token` | `df66a82c` | every installed app's manifest URL; `dl/<old>/` holds every version 0.1.0 to 0.3.5, the jobs file, the CI inputs; the `DL_TOKEN` repository secret; 1 commit of the history (`docs/plans/morning-2026-10-04.md`, masked on this branch) |
|
|
| new downloads token | `~/.config/igneum/dl-token.next` | `ed9c4d2e` | `dl/<new>/` with the 0.3.3 installers and the WSL2 zip only, no manifest, no jobs file, no CI inputs |
|
|
|
|
## 1. What this branch changes (`rotation-2`)
|
|
|
|
| File | Change |
|
|
|---|---|
|
|
| `packaging/mac/packaged-config.sh` | no key literal any more. `IGNEUM_INTAKE_KEY_FILE` and `IGNEUM_DL_TOKEN_FILE` name the files; each defaults to the `.next` file when it exists, else the plain file. Prints file names, lengths and fingerprints, never values. `--test` runs its 23 checks on temporary files |
|
|
| `packaging/windows/make-payload.sh` | sources `packaged-config.sh` and calls `write_packaged_config` (it used to `sed` the key out of that file) |
|
|
| `.github/workflows/windows.yml` | a "packaged configuration" step writes the repository secrets `DL_TOKEN`, `DL_TOKEN_NEXT`, `LOG_INTAKE_KEY`, `LOG_INTAKE_KEY_NEXT` to the same files under `~/.config/igneum` on the runner, so `make-payload.sh` picks them exactly as on the Mac; `LOG_INTAKE_KEY` or `LOG_INTAKE_KEY_NEXT` is now required (the key no longer comes from the tree) |
|
|
| `app/igneum-app/src/config.rs` | `Packaged::with_env_overrides()` honours the same two variables on a running engine (a developer run, or a package built with the old values); `describe()` is the new header line `config: intake <url> key <fp> (<source>); manifest <url with the token masked> folder <fp> (<source>)`; `fingerprint8`, `manifest_url_for_token`, `token_of_manifest_url`, `read_secret_file`; 6 new unit tests |
|
|
| `app/igneum-app/src/main.rs`, `engine.rs` | the overrides applied at load; the `config:` line logged right after the `IGNEUM-APP` header at every engine start (so every upload carries it) |
|
|
| `tools/ship-app.mjs` | `--dl-both`: a `mirror` step copies the version's files and the folder-level files into `dl/<dl-token.next>/`, the `manifest` step publishes a second manifest there (`--dest`, `--base-url`, carrying the first manifest's `override`, `tuning` and `min_supported_version`, compared field by field), one deploy, `verify` checks both folders; self-test covers the three helpers |
|
|
| `tools/logs.mjs` | `--rotation`: every app machine's version and header fingerprints against the `.next` files, exit 1 while any machine is behind; `--self-test` |
|
|
| `infra/gpu-bench/upload.sh`, `proving/windows-wsl2/prove-block.sh`, `prove-shard.sh`, `proto-cuda/windows-app/upload-log.bat`, `proto-cuda/windows-miner/upload-log.bat` | the key literal removed: environment (`IGNEUM_LOG_KEY` or `IGNEUM_INTAKE_KEY`, which the app's job runner already sets), `IGNEUM_INTAKE_KEY_FILE`, or `igneum-log-key.txt` next to the .bat; the tree carries neither value now (`git grep` of both reads 0 files) |
|
|
| `tools/repo/fresh-repo.sh` | the history rewrite of `docs/plans/history-rewrite.md` section 2 as one script with the verification greps and the printed push commands (section 6 below) |
|
|
| `docs/plans/history-rewrite.md` | brought over from `testnet-prep` unchanged, so this branch carries the plan it executes |
|
|
|
|
## 2. The handover, as designed
|
|
|
|
An installed app reads `igneum-app.json` next to its engine (macOS `Contents/Resources`, Windows the install folder):
|
|
the manifest URL and the intake key. The OTA path replaces the whole bundle or runs the whole installer, and both
|
|
carry a new `igneum-app.json`, so the values travel with the version. Nothing is cached in the app data folder.
|
|
|
|
| Step | 0.3.5 on a machine (old folder, old key) | 0.3.6 (new folder, new key) |
|
|
|---|---|---|
|
|
| hourly check | fetches `dl/<old>/igneum-app-latest.json`: 0.3.6 is there (published in BOTH folders), signed by the same key | fetches `dl/<new>/igneum-app-latest.json`: itself |
|
|
| download | the URL inside the old folder's manifest, `dl/<old>/Igneum-Miner-0.3.6.dmg` or `-Setup-0.3.6.exe` (byte-identical to the new folder's copy) | nothing |
|
|
| apply | the new bundle or installer brings `igneum-app.json` with the NEW manifest URL and the NEW key | |
|
|
| after restart | reports to the intake with the new key (`LOG_INTAKE_KEY_NEXT` accepts it); its header reads `key 477bb0ef` and `folder ed9c4d2e`; next check hits the NEW folder | the same |
|
|
| jobs | `igneum-jobs.json` is read next to the manifest, so the mirror step copies the jobs file and its signature into the new folder; any job published while both folders live goes to both (section 3d) | |
|
|
|
|
The window: every 0.3.5 machine must apply 0.3.6 before the old folder goes. Machines apply in their own minute of the
|
|
hour and only when the node is synced, so the window is hours, not minutes. The old folder and the old key stay until
|
|
`node tools/logs.mjs --rotation` reads 0 behind (section 4). Nothing is deleted on a schedule.
|
|
|
|
## 3. The publish, exactly
|
|
|
|
Everything below runs from the main checkout after this branch is merged to master. `DLSITE` is the downloads folder
|
|
(`~/.config/igneum/dlsite-dir`), `OLD` and `NEW` the two tokens read from their files; neither is ever typed.
|
|
|
|
### 3a. Before the cut (by hand, once)
|
|
|
|
```
|
|
# the site must accept both keys (names only are listed; the value is piped from the file)
|
|
cd site && npx --yes vercel@latest --global-config ~/.config/igneum/vercel link --scope igneum --project igneum --yes
|
|
npx --yes vercel@latest --global-config ~/.config/igneum/vercel env ls --scope igneum # LOG_INTAKE_KEY must be there; is LOG_INTAKE_KEY_NEXT?
|
|
tr -d '[:space:]' < ~/.config/igneum/log-intake-key.next | npx --yes vercel@latest --global-config ~/.config/igneum/vercel env add LOG_INTAKE_KEY_NEXT production --scope igneum
|
|
cd .. && git push origin master # or any production deploy: the function reads the variable at the next deploy
|
|
# confirm: a POST with the NEXT key is accepted (200 with an id), the old one still is too
|
|
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H "x-igneum-key: $(tr -d '[:space:]' < ~/.config/igneum/log-intake-key.next)" -H 'Content-Type: application/json' -d '{"label":"rotation-check","machine":"mac","run_id":"rotation-check","lines":"next key accepted"}' https://igneum-six.vercel.app/api/log
|
|
|
|
# the Windows build on GitHub needs the same files (the runner writes the secrets to ~/.config/igneum; windows.yml)
|
|
gh auth switch --user igneum-labs
|
|
tr -d '[:space:]' < ~/.config/igneum/log-intake-key | gh secret set LOG_INTAKE_KEY --repo igneum-network/igneum
|
|
tr -d '[:space:]' < ~/.config/igneum/log-intake-key.next | gh secret set LOG_INTAKE_KEY_NEXT --repo igneum-network/igneum
|
|
tr -d '[:space:]' < ~/.config/igneum/dl-token.next | gh secret set DL_TOKEN_NEXT --repo igneum-network/igneum
|
|
gh secret list --repo igneum-network/igneum # DL_TOKEN, DL_TOKEN_NEXT, LOG_INTAKE_KEY, LOG_INTAKE_KEY_NEXT
|
|
|
|
# the new folder exists and is empty of a manifest (the mirror step fills it)
|
|
DLSITE="$(tr -d '[:space:]' < ~/.config/igneum/dlsite-dir)"; NEW="$(tr -d '[:space:]' < ~/.config/igneum/dl-token.next)"
|
|
ls "$DLSITE/dl/$NEW"
|
|
packaging/mac/packaged-config.sh --test # 23 checks
|
|
```
|
|
|
|
### 3b. The cut: one command, both folders
|
|
|
|
```
|
|
node tools/ship-app.mjs 0.3.6 --node <fork worktree> --notes "<one line>" --dl-both --dry-run # the plan, nothing written
|
|
node tools/ship-app.mjs 0.3.6 --node <fork worktree> --notes "<one line>" --dl-both
|
|
```
|
|
|
|
With `--dl-both` the steps are: preflight (also: `dl-token.next` present and different, the folder exists) > bump >
|
|
inputs > commit and push (the Windows build starts; its payload step runs `packaged-config.sh --test` and packages
|
|
the `.next` values because the `_NEXT` secrets are set) > ci > fetch (installer and zip into the OLD folder) > dmg
|
|
(`build-dmg.sh` packages `igneum-app.json` from the `.next` files by default) > copy (DMG into the OLD folder) >
|
|
mirror (DMG, installer, zip, `igneum-windows-ci.json`, `igneum-jobs.json` and `.sig`, `payload-inputs.{zip,json,sha256}`,
|
|
`igneum-prove-wsl2.zip` into the NEW folder, sha256-checked) > manifest (section 3c, both) > deploy (one) > verify
|
|
(both folders: HEAD and GET of every file, both manifests byte-identical to the local ones and verifying, every
|
|
platform URL inside its own folder) > console.
|
|
|
|
The build itself prints which files it packaged, for example `intake key: ~/.config/igneum/log-intake-key.next (31 chars,
|
|
fingerprint 477bb0ef)` and `manifest: ~/.config/igneum/dl-token.next (10 chars, fingerprint ed9c4d2e) -> https://dl.igneum.network/dl/<token>/igneum-app-latest.json`.
|
|
A build that says `e2005de8` or `df66a82c` packaged the old values: stop, the `.next` files were not found.
|
|
|
|
### 3c. The same by hand with `packaging/ota/publish-manifest.sh` (what the manifest step runs)
|
|
|
|
`publish-manifest.sh` writes the OLD folder by default (it reads `~/.config/igneum/dl-token`); `--dest <folder>` and
|
|
`--base-url <url>` aim it at the NEW folder. With `--dest` it carries `consensus.override`, `tuning` and
|
|
`min_supported_version` over from the manifest already in THAT folder, which is none, so the second call must pass
|
|
what the first manifest carries. `--deploy` is refused with `--dest`; one deploy of the whole folder follows.
|
|
Run by hand, `publish-manifest.sh` prints the manifest it wrote, URLs included, so the terminal shows the token
|
|
path (it always has); `ship-app.mjs` scrubs both tokens from every line, which is the reason to prefer 3b.
|
|
|
|
```
|
|
DLSITE="$(tr -d '[:space:]' < ~/.config/igneum/dlsite-dir)"
|
|
OLD="$(tr -d '[:space:]' < ~/.config/igneum/dl-token)"; NEW="$(tr -d '[:space:]' < ~/.config/igneum/dl-token.next)"
|
|
V=0.3.6; NOTES="<one line>"
|
|
|
|
# 1. the OLD folder (default dest and base): the files are there from fetch and copy
|
|
packaging/ota/publish-manifest.sh --version $V --notes "$NOTES" --no-deploy \
|
|
--mac "$DLSITE/dl/$OLD/Igneum-Miner-$V.dmg" --win "$DLSITE/dl/$OLD/Igneum-Miner-Setup-$V.exe"
|
|
|
|
# 2. the NEW folder: the same bytes copied in, the same override, tuning and min_supported read from the first manifest
|
|
cp "$DLSITE/dl/$OLD/Igneum-Miner-$V.dmg" "$DLSITE/dl/$OLD/Igneum-Miner-Setup-$V.exe" "$DLSITE/dl/$OLD/igneum-windows-app.zip" \
|
|
"$DLSITE/dl/$OLD/igneum-windows-ci.json" "$DLSITE/dl/$OLD/igneum-jobs.json" "$DLSITE/dl/$OLD/igneum-jobs.json.sig" \
|
|
"$DLSITE/dl/$OLD/payload-inputs.zip" "$DLSITE/dl/$OLD/payload-inputs.json" "$DLSITE/dl/$OLD/payload-inputs.sha256" \
|
|
"$DLSITE/dl/$OLD/igneum-prove-wsl2.zip" "$DLSITE/dl/$NEW/"
|
|
M="$DLSITE/dl/$OLD/igneum-app-latest.json"
|
|
OVERRIDE="$(python3 -c 'import json,sys; o=json.load(open(sys.argv[1])).get("consensus",{}).get("override"); print(json.dumps(o,sort_keys=True,separators=(",",":")) if o else "")' "$M")"
|
|
MINSUP="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("min_supported_version",""))' "$M")"
|
|
python3 -c 'import json,sys; t=json.load(open(sys.argv[1])).get("tuning"); open(sys.argv[2],"w").write(json.dumps(t)) if t else None' "$M" /tmp/tuning-$V.json
|
|
packaging/ota/publish-manifest.sh --version $V --notes "$NOTES" --no-deploy \
|
|
--dest "$DLSITE/dl/$NEW" --base-url "https://dl.igneum.network/dl/$NEW" \
|
|
--mac "$DLSITE/dl/$NEW/Igneum-Miner-$V.dmg" --win "$DLSITE/dl/$NEW/Igneum-Miner-Setup-$V.exe" \
|
|
${OVERRIDE:+--override "$OVERRIDE"} ${MINSUP:+--min-supported "$MINSUP"} $([ -s /tmp/tuning-$V.json ] && echo --tuning /tmp/tuning-$V.json || echo --no-tuning)
|
|
rm -f /tmp/tuning-$V.json
|
|
# the two manifests must differ only in published_at and the folder inside the URLs
|
|
diff <(python3 -c 'import json,sys; m=json.load(open(sys.argv[1])); m.pop("published_at"); print(json.dumps(m,sort_keys=True,indent=1).replace(sys.argv[2],"T"))' "$M" "$OLD") \
|
|
<(python3 -c 'import json,sys; m=json.load(open(sys.argv[1])); m.pop("published_at"); print(json.dumps(m,sort_keys=True,indent=1).replace(sys.argv[2],"T"))' "$DLSITE/dl/$NEW/igneum-app-latest.json" "$NEW") && echo "same fields"
|
|
|
|
# 3. one deploy, then both live checks (each: reachable, byte-identical to the local file, signature verifies)
|
|
(cd "$DLSITE" && npx --yes vercel@latest --global-config ~/.config/igneum/vercel deploy --prod --yes)
|
|
packaging/ota/publish-manifest.sh --verify-only
|
|
packaging/ota/publish-manifest.sh --verify-only --dest "$DLSITE/dl/$NEW" --base-url "https://dl.igneum.network/dl/$NEW"
|
|
```
|
|
|
|
### 3d. Jobs while both folders live
|
|
|
|
`packaging/ota/publish-jobs.sh` writes `dl/<old>/igneum-jobs.json` by default and takes the same `--dest` and
|
|
`--base-url`. Until the old folder is deleted, every `add` or `expire` is published twice, the second time with
|
|
`--dest "$DLSITE/dl/$NEW" --base-url "https://dl.igneum.network/dl/$NEW"`, then one deploy. A job whose
|
|
`zip_url` names the old folder keeps working until that folder goes; publish new jobs with URLs in the new folder.
|
|
|
|
## 4. Verification: every machine's header shows the new intake path
|
|
|
|
The engine logs two header lines at every start, and the restart after an OTA apply logs them again, so the latest
|
|
upload of every machine carries them:
|
|
|
|
```
|
|
IGNEUM-APP version=0.3.6 machine=<id8> platform=<os> node=<igneumd version>
|
|
config: intake https://igneum-six.vercel.app/api/log key 477bb0ef (packaged); manifest https://dl.igneum.network/dl/<token>/igneum-app-latest.json folder ed9c4d2e (packaged)
|
|
```
|
|
|
|
```
|
|
node tools/logs.mjs --rotation # one row per app machine: version, key fp, folder fp, sources, state; exit 1 while any is behind
|
|
node tools/logs.mjs <run_id> | grep -E 'IGNEUM-APP|config: intake' # one machine in full
|
|
```
|
|
|
|
Done means: every row `moved` (key `477bb0ef`, folder `ed9c4d2e`, version 0.3.6), none `OLD`, and the `unknown` rows
|
|
(a machine whose last upload predates this header, or a machine that has stopped for good) accounted for by name.
|
|
Today the table shows 6 app machines (three `win-`, three `mac-`), all 0.3.5 or older, all `unknown` because 0.3.5
|
|
has no `config:` line. The console's Machines tab (`relay/`) shows the versions the same way.
|
|
|
|
Also check, once, that the intake stores an upload under the new key from a real machine (the row's `last_received`
|
|
moves after the restart), and that `node tools/logs.mjs` lists no new `rotation-check` rows beyond the one from 3a.
|
|
|
|
## 5. The deletion, after section 4 reads 0 behind
|
|
|
|
In this order, each step checked before the next:
|
|
|
|
```
|
|
DLSITE="$(tr -d '[:space:]' < ~/.config/igneum/dlsite-dir)"
|
|
OLD="$(tr -d '[:space:]' < ~/.config/igneum/dl-token)"; NEW="$(tr -d '[:space:]' < ~/.config/igneum/dl-token.next)"
|
|
node tools/logs.mjs --rotation || { echo "machines still behind"; false; }
|
|
|
|
# 1. the old folder: gone from the downloads host (one deploy); the new one still serves
|
|
mv "$DLSITE/dl/$OLD" "$HOME/igneum-dl-old-$(date -u +%Y%m%d)" # kept outside the site for a week, then rm -rf
|
|
(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 --dest "$DLSITE/dl/$NEW" --base-url "https://dl.igneum.network/dl/$NEW" # still live
|
|
|
|
# 2. the local files: the NEXT values become the plain ones (every script's default), the old ones kept dated
|
|
mv ~/.config/igneum/log-intake-key ~/.config/igneum/log-intake-key.old-$(date -u +%Y%m%d)
|
|
mv ~/.config/igneum/log-intake-key.next ~/.config/igneum/log-intake-key
|
|
mv ~/.config/igneum/dl-token ~/.config/igneum/dl-token.old-$(date -u +%Y%m%d)
|
|
mv ~/.config/igneum/dl-token.next ~/.config/igneum/dl-token
|
|
packaging/ota/publish-manifest.sh --verify-only # now reads the new token by default: live, verified
|
|
|
|
# 3. the intake: the old key dropped (LOG_INTAKE_KEY becomes the new value, LOG_INTAKE_KEY_NEXT removed), redeployed
|
|
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 # or a production deploy
|
|
# 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-$(date -u +%Y%m%d))" -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
|
|
|
|
# 4. the GitHub secrets: the plain names carry the new values, the _NEXT names go
|
|
tr -d '[:space:]' < ~/.config/igneum/dl-token | gh secret set DL_TOKEN --repo igneum-network/igneum
|
|
tr -d '[:space:]' < ~/.config/igneum/log-intake-key | gh secret set LOG_INTAKE_KEY --repo igneum-network/igneum
|
|
gh secret delete DL_TOKEN_NEXT --repo igneum-network/igneum; gh secret delete LOG_INTAKE_KEY_NEXT --repo igneum-network/igneum
|
|
|
|
# 5. the app machines keep reporting (a last look, an hour later)
|
|
node tools/logs.mjs --rotation
|
|
```
|
|
|
|
The relay is not involved: since round 4 (X23) it has its own key (`~/.config/igneum/relay-key`, `RELAY_KEY`), and
|
|
the intake key only reports. The old launcher packages under `proto-cuda/windows-app` and `windows-miner` (0.2.0)
|
|
carried the old key in `upload-log.bat`; those machines are the `unknown` rows of section 4 and upload nothing after
|
|
step 3, which is the intent.
|
|
|
|
## 6. The fresh repository, after section 5
|
|
|
|
The old values are dead values once section 5 is done; only then is the rewrite worth running. The owner's two
|
|
settings come first: rename the GitHub login `igneum-labs` to a neutral handle (the numeric noreply id 337424239
|
|
stays, so the rewritten author line is `<new> <337424239+<new>@users.noreply.github.com>`), and remove the second
|
|
login from the organisation's owners. Then, from the main checkout with every agent frozen:
|
|
|
|
```
|
|
gh pr list --repo igneum-network/igneum # must be empty
|
|
git worktree list > ~/igneum-worktrees-$(date -u +%Y%m%d).txt
|
|
IGNEUM_FILTER_REPO=<dir>/git_filter_repo.py tools/repo/fresh-repo.sh --new-login <new handle> --new-repo igneum-network/<name> \
|
|
[--public-claude-md <scrubbed CLAUDE.md>] --work ~/igneum-rewrite
|
|
```
|
|
|
|
The script clones `origin` afresh (mirror, no hardlinks), reads the personal identities and the second login from
|
|
the history and the four secret values from `~/.config/igneum`, writes the rule files 0600 and removes them after
|
|
the pass, runs the one `git-filter-repo` invocation of `docs/plans/history-rewrite.md` section 2 (drop the four
|
|
internal files, replace the secrets and the names, mailmap both personal identities to the login, every offset to
|
|
`+0000`, optionally the public `CLAUDE.md` in every commit), then demands zero for: secret lines in any blob,
|
|
identity lines in any blob, identity lines in commit metadata, stamps not `+0000`, commits touching the dropped
|
|
files, identities other than the login, the old login in any blob (with `--new-login`). It prints the push commands
|
|
and runs none of them: `gh repo create igneum-network/<name> --private`, `git remote add origin` in the clone,
|
|
`git push --mirror origin`, then the GitHub secrets (section 3a), the Vercel Git connection moved to the new
|
|
repository, the old repository archived, the main checkout re-cloned and every worktree re-created from its
|
|
rewritten branch.
|
|
|
|
### Dry run of 5 October 2026 (throwaway mirror clone of the main checkout under the session scratchpad, nothing pushed)
|
|
|
|
| Count | Before | After |
|
|
|---|---|---|
|
|
| commits (all refs) | 410 | 353 (57 commits that only touched the four dropped files are gone) |
|
|
| refs | 49 | 29 (filter-repo drops the remote-tracking refs of the mirror) |
|
|
| author and committer identities | 3 | 1 (`igneum-labs <337424239+[removed]>`) |
|
|
| stamps not +0000 | 660 of 820 | 0 of 706 |
|
|
| commits touching the four dropped files | 53 | 0 |
|
|
| secret lines in any blob (old key, new key, old token, new token) | 21 | 0 |
|
|
| identity lines in any blob (first name outside the login, surname, personal addresses, second login, the other businesses) | 1839 | 0 |
|
|
| identity lines in commit metadata | 171 | 0 |
|
|
| standing login lines in any blob | 94 | 61 (0 with `--new-login` after the rename) |
|
|
| pass run time | | 67 s; 4 min with the clone and the greps |
|
|
|
|
The report sits next to the clone (`<work>/report.txt`, with `commit-map`, 411 lines). The throwaway clone was
|
|
removed after the run; nothing left the Mac.
|
|
|
|
## 7. The order for the afternoon
|
|
|
|
1. Merge `rotation-2` into master (the Windows build on that push packages with the `_NEXT` secrets only when they
|
|
exist: set them first, section 3a, or expect the payload step to fail on the missing `LOG_INTAKE_KEY`).
|
|
2. Section 3a: the site's `LOG_INTAKE_KEY_NEXT`, the four repository secrets, the curl check.
|
|
3. Section 3b: `--dry-run`, then the cut with `--dl-both`.
|
|
4. Section 4 through the afternoon: `node tools/logs.mjs --rotation` until 0 behind (the slot rule means an hour or
|
|
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 |
|