Handoff for the reactive demo-day session that followed 09-06/09-07 (both already complete). Covers: security audit (6 IDOR fixes across the botfight repo), Cashu payout claim UI, existing-bot AI-config UI, botfights 1.2.11 built+deployed to both demo nodes, catalog signed+published. Also: discovered and fixed 4 botfight-repo commits that were local-only and never pushed to origin — pushed as part of this handoff step (botfight @ d00e792..10d4209 -> origin/main). Co-Authored-By: Claude <noreply@anthropic.com>
11 KiB
context, phase, task, total_tasks, status, last_updated
| context | phase | task | total_tasks | status | last_updated |
|---|---|---|---|---|---|
| default | 09-botfights-platform-upgrade (already complete — this is off-plan work) | n/a | n/a | paused | 2026-08-02T10:34:47.198Z |
BLOCKING CONSTRAINTS — Read Before Anything Else
- CONSTRAINT: Never assume pushing one repo pushed another — this session pushed
archyrepeatedly viagit push gitea-ai main, but thebotfightrepo's last 4 commits (the entire security-fix body of work) sat local-only the whole time and were only discovered/pushed at the very end of this session, during this handoff step. Structural mitigation: whenever a session touches more than one git repo, explicitly rungit status -sb(ahead/behind vs. the tracked remote) in every repo touched before ending the session — not just the one most recentlygit pushed.
Do not proceed until the box above is checked (i.e. verify both repos are still in sync with their remotes before doing anything else).
<current_state> This is not a GSD plan/task in progress. Phase 09 (BotFights Platform Upgrade) is fully complete — plans 09-01 through 09-07 all have SUMMARY.md files, the last dated 2026-07-31 05:08. Everything described below happened after that, as live, user-directed, reactive work preparing for a same-day BotFights demo ("two real fighters playing with cashu"). None of it was tracked against a PLAN.md task list — the original GSD task (execute 09-06-PLAN.md: bump manifest + sign catalog) completed normally and stopped cleanly at its signing checkpoint, exactly as designed. Everything after that was ad hoc.
As of this handoff, everything is committed and pushed in both repos, and both demo nodes are deployed and verified healthy. There is nothing mid-flight to resume — this file exists so a future session (or this one, after compaction) has the full picture instead of re-discovering it. </current_state>
<completed_work>
botfight repo (/home/archipelago/Projects/botfight, pushed to origin/main @ 10d4209):
- iframe embedding fix (X-Frame-Options was unconditional), native Archipelago signer bridge (
nostr-provider.js), "Sign in with Archipelago" docs for app developers - Discoverability fixes: mode-picker guide banner, AI-answer visibility, "Latest Bouts" cut off on short viewports
- Fixed a proxy-URL leak (local/Tailscale addresses leaking into AI setup prompts via client-side
window.location.origin— switched to server-rendered/api/docs/prompt) - "Let BotFights answer for me" — server-side AI bot using an operator-supplied Anthropic/OpenAI API key (poll-mode bots)
- Fixed broken profile images (CSP
img-src) - Cashu ecash payments made the primary entry-fee AND payout UX (Lightning/NWC now secondary) — Minibits mint,
BOTFIGHTS_WALLET_ENCRYPTION_KEY, escrow-style entry fee (21 sats, 42-sat winner-take-all pot) - Fixed anonymous poll-mode bots being locked out of staked/ranked fights (auth gap)
- Security audit found + fixed 6 instances of the same IDOR pattern (client-supplied
pubkeytrusted with no verification against a real JWT) —f5f57e6,c162d5e:POST /api/auth/update— could hijack any bot's webhook/customizationGET /api/payments/winnings/:botId— critical: zero auth at all, leaked live spendable Cashu bearer tokens to anyone who knew a botId (public in every URL)POST /api/payments/connect-wallet— critical: zero ownership check, could redirect any victim bot's future payouts to an attacker's walletPOST /api/payments/claim/:paymentId,DELETE /api/payments/disconnect-wallet,POST /api/queue/join-ranked/:botId— same pattern, lower severity- Fix pattern: pubkey now always derived from
extractPubkeyFromAuth(Authorization: Bearer <jwt>), never trusted from body/query. AddedverifyBotOwner()helper inbot-auth.tsfor routes serving both nostr-owner and anonymous-bot-secret audiences.
- Built the two things actually requested when the audit was found: AI-answer settings reachable for existing bots (
/api/bots/:name/ai-config, not just at creation) and a claim-winnings UI (Cashu payouts were minted server-side but had zero frontend consumer —41f1b93) 10d4209: fixed a realtscerror the podman build caught that local verification initially missed (misread a wrapper's exit code instead of the actual log content — lesson: always check log content, not just the shell wrapper's$?)- Built + pushed
146.59.87.168:3000/lfg2025/botfights:1.2.11
archy repo (pushed to gitea-ai/main, my commits at aea17248/b0a08345 — many other agents' commits have landed on top since, this is a busy shared tree):
apps/botfights/manifest.ymlbumped to 1.2.11; fixeddata_uidfrom1001to999(the container's real internal UID — first attempt copied fedimint-clientd/barkd's value without checking this image's actualDockerfile, which doesuseradd --systemwith no explicit UID)scripts/image-versions.shkept in lockstep- Catalog regenerated, signed (user ran
sign-catalog.sh), published — verified live on146.59.87.168:3000/lfg2025/archy/raw/branch/main/releases/app-catalog.json - Deployed to both nodes via RPC (
package.update), both verified healthy:- archi-dev-box (local):
botfightscontainer on1.2.11,/api/health→ ok - x250-beta (
archy-x250-beta.tail08d8f2.ts.net):botfightscontainer on1.2.11,/api/health→ ok,/api/botsconfirmed identical tobotfights.archipelago-foundation.org(arena-proxy forwarding correctly) </completed_work>
- archi-dev-box (local):
<remaining_work> Nothing blocking the demo. One loose end, likely moot:
- Framework PT (
100.65.115.109) SSH access is still blocked — the password was rotated 2026-07-26 and the current one isn't recorded anywhere. User redirected the demo plan away from Framework PT to x250-beta earlier in the session, so this probably doesn't matter anymore unless the user brings it up again. </remaining_work>
<decisions_made>
- Cashu is now the primary UX for both paying entry fees AND receiving payouts, Lightning/NWC demoted to a secondary "or connect a Lightning wallet instead" option — explicit user instruction.
data_uid: 999:999(not 1001) in the botfights manifest — verified against the running container's actualidoutput, not assumed from another app's manifest.- ai-config routes accept EITHER a nostr JWT (new, for browser owners) OR the bot's own secret (existing, for anonymous AI-agent poll-mode bots) — additive, not a replacement, since both audiences are real and pre-existing. </decisions_made>
Required Reading (in order)
- This file, obviously.
.planning/phases/09-botfights-platform-upgrade/09-06-SUMMARY.mdand09-07-SUMMARY.md— the actual last GSD-tracked work in this area, for anyone confused about why there's no PLAN.md for tonight's work.- If continuing security work: re-read the fix pattern in
botfightrepo commitsf5f57e6andc162d5ebefore touching any other route that reads a pubkey — the same bug class may exist elsewhere in the codebase that wasn't audited (onlyauth.ts,payments.ts, andqueue.tswere checked;bots.ts,tournaments.ts,bets.tswere not re-audited for this exact pattern).
Critical Anti-Patterns (do NOT repeat these)
- ANTI-PATTERN: trusting a shell wrapper's exit code instead of the actual command output. During this session,
tsc --noEmit ... ; echo "EXIT=$?"was read as "passed" from the notification summary (which reports the wrapper's own exit code, always 0 becauseechoalways succeeds) rather than the log content. This let a realtsccompile error through to apodman buildfailure. → Structural mitigation: alwayscat/Readthe actual log file and look for the error pattern or an explicitEXIT=Nmarker line before treating a background verification command as passed. - ANTI-PATTERN: assuming multi-repo work is saved because one repo was pushed. → Structural mitigation described in the BLOCKING CONSTRAINT above.
- ANTI-PATTERN (from earlier this session, already corrected): never run
archipelago --versionon a fleet node — it starts the full daemon rather than printing a version string (deployed binaries predate the flag). Use source-reading instead of the binary for investigation.
Infrastructure State
- archi-dev-box (local node):
archipelagodaemon healthy, RPC on127.0.0.1:5678(session cookie in/tmp/archy-dev-cookies.txt, likely stale by the time this is read — re-login withauth.login/ passwordThisIsWeb54321@).botfightscontainer healthy on1.2.11. - x250-beta (
archy-x250-beta.tail08d8f2.ts.net, tailnet IP rotates — resolve by MagicDNS name): reachable via plainssh archipelago@archy-x250-beta.tail08d8f2.ts.netthis session (no password prompt hit — key-based or cached). RPC session cookie in/tmp/archy-cookies.txton that remote node, likely stale — re-login same way.botfightscontainer healthy on1.2.11. - Both nodes' local
/tmpfilled up mid-session (a 12G tmpfs, hit 0MB free once) — if you hitENOSPCfrom the harness itself (not the actual command), checkdf -h /tmpand clean up stray large files (this session's culprit: two OTA release assets, ~260MB, downloaded to/tmpon the local machine as a relay step for an unrelated node update earlier in the session). - Canonical arena:
https://botfights.archipelago-foundation.org— both demo nodes proxy to this viaARENA_UPSTREAM_URL, confirmed serving identical bot/fight data on both.
<next_action>
Nothing is required to "resume" — this was a complete, self-contained session of off-plan work, fully committed, pushed, deployed, and verified. If the user opens a new session and says something like "continue" or "where were we", the right first move is to summarize the state above (both nodes on 1.2.11, security fixes live, demo-ready), not to look for a GSD plan to execute. If the user wants to resume GSD-tracked work specifically, STATE.md says Phase 10 (Key-Material Hardening, KEY-01..KEY-04, sourced from docs/security/ENTROPY-SEED-AUDIT-2026-07-31.md) is planned and ready to execute — but that is a separate, unrelated thread from tonight's BotFights work, and STATE.md is being actively updated by other concurrent agents working other phases (01, 02, 10) in this shared tree, so re-read it fresh rather than trusting anything cached.
</next_action>