From 921f450edf014d0d1f1b84774c1eef3ec9e7de6a Mon Sep 17 00:00:00 2001 From: archipelago Date: Fri, 31 Jul 2026 03:49:04 -0400 Subject: [PATCH] =?UTF-8?q?docs(09-06):=20Task=201=20complete,=20signing?= =?UTF-8?q?=20ceremony=20(Task=202)=20pending=20=E2=80=94=20SUMMARY?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Manifest/catalog prep for BotFights 1.2.1 is done and verified; the run stopped intentionally before the human-only release-signing ceremony per explicit instruction. releases/app-catalog.json is regenerated on disk but deliberately not committed until it's signed (Task 3 continuation). Co-Authored-By: Claude Fable 5 --- .../09-06-SUMMARY.md | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 .planning/phases/09-botfights-platform-upgrade/09-06-SUMMARY.md diff --git a/.planning/phases/09-botfights-platform-upgrade/09-06-SUMMARY.md b/.planning/phases/09-botfights-platform-upgrade/09-06-SUMMARY.md new file mode 100644 index 00000000..d86ab881 --- /dev/null +++ b/.planning/phases/09-botfights-platform-upgrade/09-06-SUMMARY.md @@ -0,0 +1,149 @@ +--- +phase: 09-botfights-platform-upgrade +plan: 06 +subsystem: infra +tags: [manifest, app-catalog, secrets, jwt, arena-federation, signing-ceremony] + +# Dependency graph +requires: + - phase: 09-botfights-platform-upgrade (plan 05) + provides: "botfights:1.2.1 image in the registry (146.59.87.168:3000/lfg2025/botfights:1.2.1), the canonical public arena running it at https://botfights.archipelago-foundation.org" +provides: + - "apps/botfights/manifest.yml at 1.2.1 with generated_secrets/secret_env for JWT_SECRET (hex32) and default-on ARENA_UPSTREAM_URL" + - "app-catalog/catalog.json and scripts/image-versions.sh bumped in lockstep (drift-checker clean)" + - "releases/app-catalog.json regenerated on disk with the 1.2.1 manifest embedded (NOT committed — unsigned)" + - "the release-signer binary built and staged at /tmp/archy-sign-bin/release/archipelago" + - "the per-node bot/fight impact briefing for the signing-ceremony gate" +affects: [09-07 (demo verification), the pending Task 2/3 signing+publish continuation] + +tech-stack: + added: [] + patterns: + - "generated_secrets (kind hex32) + secret_env, mirroring apps/netbird-server/manifest.yml and apps/barkd/manifest.yml — per-install secret materialised 0600, never a manifest literal" + - "catalog publish is two-remote: gitea-ai (source.archipelago-foundation.org) is the dev push target; nodes fetch releases/app-catalog.json from gitea-vps2/origin (146.59.87.168:3000) raw URLs specifically — pushing to gitea-ai alone does not publish to the fleet" + +key-files: + created: [] + modified: + - apps/botfights/manifest.yml + - app-catalog/catalog.json + - scripts/image-versions.sh + # releases/app-catalog.json: regenerated on disk, deliberately left uncommitted (see key-decisions) + +key-decisions: + - "Used the POST_PLANNING FACTS override version 1.2.1 (not the plan's original 1.2.0) throughout the manifest, catalog.json, image-versions.sh and the regenerated releases/app-catalog.json, since 09-05 shipped an additional prompt-hardening commit on top of 1.2.0 and the live arena is already on 1.2.1." + - "Left releases/app-catalog.json regenerated-on-disk but UNCOMMITTED. It was regenerated via scripts/generate-app-catalog.sh (66 apps embedded, botfights entry verified at 1.2.1 with the JWT secret/env and ARENA_UPSTREAM_URL intact) and diffed against the last-committed version to confirm the ONLY substantive change is the botfights entry (the rest of the diff is JSON key-reordering noise from a fresh json.dump, confirmed via a structural key-by-key comparison — zero other apps changed). It is not committed because it is unsigned (its previous signature was naturally stripped by the content change), and per CLAUDE.md/memory the release/manifest catalog must never be committed in an unsigned state mid-cycle. Nodes fetch the catalog from the gitea-vps2/origin raw URL (146.59.87.168:3000), a different host than the gitea-ai push target (source.archipelago-foundation.org) used for this commit, so pushing the other 3 files to gitea-ai main does not publish anything to the fleet either way — but out of caution the still-unsigned catalog itself was kept off git entirely until it can be committed already-signed in the Task 3 continuation." + - "Built the release signer binary (scripts/sign-catalog.sh's prerequisite) into /tmp/archy-sign-bin/release/archipelago ahead of the ceremony so the human's signing step is not blocked on a ~50-minute cold compile of the full archipelago workspace." + +requirements-completed: [] # BOT-04 not yet complete — signing/publish (Task 2/3) still pending human ceremony + +coverage: + - id: D1 + description: "apps/botfights/manifest.yml describes BotFights 1.2.1 with a per-install generated JWT_SECRET (hex32) and default-on ARENA_UPSTREAM_URL, verified by both targeted cargo tests and grep-level acceptance checks" + requirement: BOT-04 + verification: + - kind: unit + ref: "cd core && cargo test -p archipelago catalog_overlay_accepts_all_real_image_manifests" + status: pass + - kind: unit + ref: "cd core && cargo test -p archipelago-container manifest (38 passed, incl. parse_every_real_manifest)" + status: pass + - kind: other + ref: "python3 scripts/check-app-catalog-drift.py -> metadata_drift: 0" + status: pass + human_judgment: false + - id: D2 + description: "releases/app-catalog.json regenerated with the 1.2.1 manifest embedded (secrets, secret_env, ARENA_UPSTREAM_URL all present), verified structurally against the previously-committed catalog to show zero other-app drift" + requirement: BOT-04 + verification: + - kind: other + ref: "python3 one-liner asserting botfights.version==1.2.1, image tag :1.2.1, generated_secrets/secret_env/ARENA_UPSTREAM_URL present -> 'catalog ok'" + status: pass + human_judgment: false + - id: D3 + description: "The release-root signing ceremony and fleet publish — this is the blocking human gate this plan session stopped at. Not yet done." + requirement: BOT-04 + verification: [] + human_judgment: true + rationale: "Signing requires the human's 24-word release master mnemonic entered at their own terminal via scripts/sign-catalog.sh — this can never be automated or judged by the agent." + +duration: ~65min (mostly a ~50min cold `cargo build --release` of the signer binary, run in the background) +completed: 2026-07-31 +status: paused +--- + +# Phase 9 Plan 6: BotFights 1.2.1 Manifest + Catalog Prep (Task 1 done, signing ceremony PENDING) Summary + +**Bumped `apps/botfights/manifest.yml` to 1.2.1 with a per-install generated `JWT_SECRET` and default-on shared-arena federation, regenerated the signed-catalog input, and built the release signer — stopped intentionally at the human-only signing ceremony (Task 2) per the execution override; signing/verification/publish (Tasks 2-3) remain for a follow-up session.** + +## Performance + +- **Duration:** ~65 min (dominated by a ~50-minute cold `cargo build --release -p archipelago` for the signer binary, backgrounded while other work proceeded) +- **Tasks:** 1/3 completed (Task 1 auto); Task 2 (human signing ceremony) reached and intentionally halted per the run's explicit override instruction; Task 3 not started (depends on Task 2) +- **Files modified:** 3 committed (`apps/botfights/manifest.yml`, `app-catalog/catalog.json`, `scripts/image-versions.sh`); 1 regenerated-but-uncommitted (`releases/app-catalog.json`) + +## Accomplishments + +- `apps/botfights/manifest.yml` bumped to **1.2.1** (superseding the plan's originally-planned 1.2.0 per the session's POST_PLANNING FACTS — 09-05 shipped one additional prompt-hardening commit after 1.2.0 was built, and the live arena is already on 1.2.1). Image tag updated, `container.generated_secrets` adds `botfights-jwt-secret` (`kind: hex32`, matching `apps/barkd/manifest.yml`'s pattern — not `base64` like netbird, since `jwt.ts` uses the value directly as an HMAC key with no decode step), `secret_env` maps it to `JWT_SECRET`. `environment` gains `PORT=9100` and `ARENA_UPSTREAM_URL=https://botfights.archipelago-foundation.org` with an in-file comment documenting the per-node opt-out (delete the line to run standalone). Every other block (security/ports/volumes/health_check/interfaces/metadata) is untouched. +- `app-catalog/catalog.json`'s `botfights` entry and `scripts/image-versions.sh`'s `BOTFIGHTS_IMAGE` bumped to 1.2.1 in lockstep — `scripts/check-app-catalog-drift.py` reports `metadata_drift: 0`. +- Regenerated `releases/app-catalog.json` via `scripts/generate-app-catalog.sh` (66 apps, 56 embedded manifests). Verified programmatically: `botfights.version == "1.2.1"`, image tag `:1.2.1`, `generated_secrets` contains `botfights-jwt-secret`, `secret_env` contains `JWT_SECRET`, and `environment` contains `ARENA_UPSTREAM_URL`. Structurally diffed against the last-committed catalog and confirmed **zero other apps changed** — the large line-diff is pure JSON key-reordering noise from a fresh `json.dump`, not content drift. +- Built the release-signer prerequisite (`scripts/sign-catalog.sh` refuses to compile its own signer) into `/tmp/archy-sign-bin/release/archipelago` ahead of the ceremony, confirmed executable (`archipelago 1.7.118-alpha-dev`). +- Ran the plan's required verification: `cargo test -p archipelago catalog_overlay_accepts_all_real_image_manifests` (pass) and `cargo test -p archipelago-container manifest` (38 passed, including `parse_every_real_manifest`, confirming the new manifest parses and validates as a real overlay). +- Gathered the fleet-impact briefing the human gate needs: read the local BotFights SQLite DB on archi-dev-box directly (`/var/lib/archipelago/botfights/botfights.db`, read-only connection) — **115 bots, 102,440 fights**, matching the plan's stated pre-measurement exactly. Checked reachability of two other known nodes: x250-dev (100.72.136.6) timed out (unreachable this session); the .228 resilience node (100.64.204.114) is reachable but has **no** `botfights.db` (app not installed there). No other node currently holds local BotFights data that would be affected. +- Confirmed the live public arena is healthy and already on 1.2.1: `GET https://botfights.archipelago-foundation.org/api/health` → `{"status":"ok","name":"botfights"}`; `skopeo inspect` confirms `146.59.87.168:3000/lfg2025/botfights:1.2.1` exists in the registry. + +## Task Commits + +1. **Task 1: Manifest 1.2.1 — generated JWT secret, default-on arena, catalogs in lockstep** — `f281c7aa` (feat) — `apps/botfights/manifest.yml`, `app-catalog/catalog.json`, `scripts/image-versions.sh`. Pushed to `gitea-ai main`. + +**releases/app-catalog.json is deliberately NOT committed** — see Deviations/Decisions below. + +**Task 2 (checkpoint:human-action, blocking):** reached, not executed — the signing ceremony requires the human's 24-word release master mnemonic at their own terminal. This session never attempted it, never asked for it, and never scripted around it, per the run's explicit override instruction. + +**Task 3:** not started — depends on Task 2 completing. + +## Files Created/Modified + +- `apps/botfights/manifest.yml` — version/image → 1.2.1, `generated_secrets`/`secret_env` for `JWT_SECRET`, `ARENA_UPSTREAM_URL` added to `environment`. +- `app-catalog/catalog.json` — legacy `botfights` entry version/dockerImage → 1.2.1. +- `scripts/image-versions.sh` — `BOTFIGHTS_IMAGE` tag → 1.2.1. +- `releases/app-catalog.json` — regenerated on disk (not committed; see below). + +## Decisions Made + +See `key-decisions` in frontmatter. Most notably: **`releases/app-catalog.json` was intentionally left uncommitted.** It is correctly regenerated and verified on disk, but it is unsigned (any prior signature was naturally invalidated by the content change), and CLAUDE.md/project memory are explicit that an unsigned/dead-URL release-manifest state must never be committed mid-cycle. Nodes actually fetch the catalog from the `gitea-vps2`/`origin` raw URL (`146.59.87.168:3000`) — a different host than the `gitea-ai` push target (`source.archipelago-foundation.org`) used for this session's commit — so pushing the other 3 files to `gitea-ai main` does not, by itself, publish anything to the fleet. Out of caution (unable to fully rule out an automatic mirror/replication between the two Gitea hosts from this session), the unsigned catalog itself was kept off git entirely rather than relying on that distinction. It will be committed already-signed in the Task 3 continuation, immediately after the ceremony succeeds. + +## Deviations from Plan + +**1. [User-directed] Version 1.2.1 instead of the plan's 1.2.0.** The plan text was written against 1.2.0; the session's POST_PLANNING FACTS explicitly superseded this with 1.2.1 (an additional prompt-hardening commit `d2fc998` landed on top of 09-05's 1.2.0 build, and the live arena is already running 1.2.1). Applied everywhere the plan said 1.2.0 — manifest, both catalog files, image-versions.sh, and the regenerated `releases/app-catalog.json`. + +**2. [User-directed] Stopped before Task 2's signing ceremony.** The plan's own Task 2 is a `checkpoint:human-action` gate; the run's explicit instruction additionally forbade attempting to sign or ask for the mnemonic. This session did all automatable prep (manifest/catalog edits, catalog regeneration + verification, signer binary build, impact briefing) and returns with the exact ceremony instructions for the user, rather than proceeding into Task 2's interactive flow. + +No Rule 1-3 auto-fixes were needed — the manifest/catalog edits matched the plan and the analog patterns (`netbird-server`, `barkd`) exactly, and both required cargo tests passed on the first run. + +## Issues Encountered + +- The signer binary build (`cargo build --release -p archipelago`, a fresh `CARGO_TARGET_DIR` with no incremental cache) took ~50 minutes on this heavily-loaded shared dev box (load average 24+ during the build, other agents/containers active on the same host) — far longer than a typical incremental build. Backgrounded and monitored to completion; no errors, `BUILD_EXIT=0`. The two required `cargo test` invocations (which share `core/target/debug`, unaffected by the release build's separate `CARGO_TARGET_DIR`) both completed successfully in parallel with the signer build. +- x250-dev (100.72.136.6) was unreachable this session (SSH connection timed out) — could not check whether it holds local BotFights data. Not blocking: the plan's own pre-measured reference count (115 bots/102,440 fights on archi-dev-box) was independently reproduced exactly, and the other checked node (.228) has no local install. + +## User Setup Required + +**The signing ceremony (Task 2) is the next required action — see the report returned alongside this summary for exact instructions.** In short: run `bash /home/archipelago/Projects/archy/scripts/sign-catalog.sh` at your own terminal, paste your 24-word release master mnemonic, press Enter then Ctrl-D. The signer binary is already built and staged, so this step should run immediately with no compile wait. + +## Next Phase Readiness + +- **Not ready to proceed to 09-07 (demo verification) for the manifest/catalog side of BOT-04** until the signing ceremony (Task 2) and publish (Task 3) complete. The live public arena itself (from 09-05) is already healthy at 1.2.1 and unaffected by this plan's remaining steps — only node-fleet catalog distribution is pending. +- Once the human runs the ceremony and replies "signed", a continuation session should: (1) independently re-verify the signature and `signed_by` DID and that the `botfights` payload wasn't altered by signing, (2) commit `releases/app-catalog.json` (staged by explicit path) with a message describing the BotFights 1.2.1 catalog publish, (3) push `gitea-ai main`, (4) ensure `main` also lands on `gitea-vps2` (the host nodes actually fetch from) and confirm via `curl` of the raw URL that the published bytes match the signed local file, exactly as Task 3 specifies. +- If the user instead says "hold federation": regenerate `releases/app-catalog.json` with `ARENA_UPSTREAM_URL` removed from `apps/botfights/manifest.yml` first, then re-run the ceremony — this reverts BOT-03's default-on behavior while keeping the JWT-secret crash-loop fix (BOT-04's other half) intact. + +--- +*Phase: 09-botfights-platform-upgrade* +*Completed: 2026-07-31* + +## Self-Check: PASSED + +- `apps/botfights/manifest.yml`, `app-catalog/catalog.json`, `scripts/image-versions.sh` confirmed present on disk with 1.2.1 content. +- Commit `f281c7aa` confirmed present in `git log --oneline` and confirmed pushed to `gitea-ai main` (remote ref updated `6904e789..f281c7aa`). +- `releases/app-catalog.json` confirmed present on disk, regenerated, `botfights` entry verified at 1.2.1 with secrets/env intact — confirmed intentionally absent from `git status` staged/committed state (still shows as modified-but-uncommitted). +- `/tmp/archy-sign-bin/release/archipelago` confirmed executable. +- Both required `cargo test` invocations confirmed passing from their captured output.