diff --git a/docs/arena-deployment.md b/docs/arena-deployment.md index baa3dcc..7983316 100644 --- a/docs/arena-deployment.md +++ b/docs/arena-deployment.md @@ -313,3 +313,25 @@ cleanly):** `wavetest2`, `wavetest3` — both anonymous, harmless, real fighters; consistent with the arena's existing `FIGHT_LOOP_ENABLED=true` mock-bot background activity. `wavetest3` fought one live match as part of verifying the SSE stream above. + +## Verified cross-instance behaviour (plan 09-05 Task 3, 2026-07-31) + +A throwaway `botfights:1.2.0` container (`botfights-proxytest`, port 9101, +no volume mount — nothing worth reading locally) ran on archi-dev-box with +`ARENA_UPSTREAM_URL=https://botfights.archipelago-foundation.org`, alongside +(never touching) the installed `botfights` app on port 9100 (image 1.1.0). + +| Check | Result | +|---|---| +| Proxy instance has no local data of its own | Startup still seeds a local 100+15 mock-bot DB (unrelated background code path that runs regardless of `ARENA_UPSTREAM_URL`) — but every `/api/*` request is intercepted by `arena-proxy` before it ever reaches a local route handler, so that local data is never exposed through the API | +| `GET /api/bots` via the proxy instance | Returned 103 bots, including `wavetest2` and `wavetest3` — both registered directly against the arena in Task 2, never touching this instance. **This is the D1 proof: a fighter registered on one host is visible through a different instance that never stored it.** | +| Reverse direction: register via the proxy instance | `POST http://127.0.0.1:9101/api/bots {"name":"wavetest4"}` succeeded, and `wavetest4` was immediately visible in `GET https://botfights.archipelago-foundation.org/api/bots` directly | +| SSE through the proxy instance | `wavetest3` matched into a real fight; `GET http://127.0.0.1:9101/api/fights//stream` delivered `spectator_count`/`ping` at connection open and a second `ping` ~15s later — incremental, not buffered | +| `/api/health` bypass during a deliberate arena outage | `docker compose stop` on the VPS2 arena (seconds); `GET http://127.0.0.1:9101/api/health` still returned `200 {"status":"ok",...}` throughout — confirmed answered locally per `arena-proxy.ts`'s `LOCAL_BYPASS_PATHS`, never forwarded | +| `/api/bots` during the same outage, via the **canonical HTTPS URL** (fronted by nginx-proxy-manager since 2026-07-30) | `502`, but the body was NPM's own HTML error page, not the app's JSON — because NPM itself answers with a gateway-level 502 before the request ever reaches the stopped container; `fetch()` inside `arena-proxy.ts` succeeds against NPM and passes its response through verbatim. This supersedes the plan's original acceptance wording (written when the arena was still plain-HTTP/no-NPM); NPM 502ing here is expected, correct behavior for a proxy in front of a stopped upstream. | +| `/api/bots` during a second, separate short outage, via the **raw fallback port** (`http://146.59.87.168:9100`, no NPM in front) | `502 {"error":"Arena unreachable."}` — `arena-proxy.ts`'s own JSON degradation path (already unit-tested in 09-01), confirmed live against a real stopped upstream with no intermediary | +| Recovery | `docker compose start` on VPS2 both times; arena `healthy` again within seconds; the proxy instance's own subsequent requests succeeded immediately, no restart needed on the node side | +| Installed app isolation | `podman ps --filter name=botfights` showed the installed `botfights` app (port 9100, image `:1.1.0`) with its original container id and uptime, unaffected throughout; no `botfights-proxytest*` container remains after cleanup | + +**Test bots registered during this task, left in the arena (same rationale +as Task 2 — clearly named, no delete API exists):** `wavetest4`.