Skip to content

Admin/Bank Split

Status: accepted 2026-07-03 · executed 2026-07-04 (code-complete; deploy-time cutover pending)

What was decided

Dissolve admin-server as a backend. There is no "admin" domain in this codebase — a route-by-route trace found every non-fund route belongs to a service that already owns its state. The end-state is four-way:

  • Banks — chain-specific, fund-moving, sign + submit on-chain. One per chain: evm-bank (was admin-server), solana-bank (was solana-admin-server). Their entire surface is money movement (plus chain-specific reference data: deployments/deploy/reconcile).
  • game-server — real-time play + everything producing a verifiable record, and now the native operator endpoints: config CRUD + reload (/admin/config), /admin/rules, observatory reads, tournament views (list/detail, reading the same table_players.elimination_order the payout path uses), native force-end-tournament (calls orchestrator.forceEnd() directly), and copilot-costs.
  • auth-server — identity + roles, now including /admins list + POST /admins/role grant/revoke (DB-re-checked per call, audited).
  • apps/admin — a thin frontend. Operator panels ride /api/game-server/[...path] + direct auth-server calls; money panels ride /api/bank/[...path] (CHAIN-selected BANK_URL). No admin backend, no BFF aggregator service.

Topology

Solana operator parity falls out for free: the operator panels no longer have a chain axis, so one dashboard works on either deploy.

The env model

ADMIN_SERVER_URL is retired entirely. Money → BANK_URL (CHAIN-selected EVM_BANK_URL/SOLANA_BANK_URL, boot-asserted); operator → GAME_SERVER_URL/AUTH_BASE_URL. A legacy-name grep gate in scripts/check-env-contract.sh keeps the retired family out of code, env templates, compose, CI, and test spawn envs — added after new code (a market-create dispatch) landed reading the retired name.

Key tradeoffs accepted

  • Transitional duplication during the migration (routes lived in both places until callers moved), in exchange for every step being additive + rollback-by-redeploy.
  • Two live fund-critical service renames — gated by the EVM fund-path suite and the Solana cage e2e before AND after each bank-touching phase.
  • The moved game-server operator endpoints ride the pre-existing x-admin-key operator auth (secret held server-side in the dashboard BFF), not JWT-role gating; auth-server's role endpoints DO re-check the DB role per call.
  • Deployment/chain-config parity for Solana (/deployments, /api/deployment) stays bank-owned per chain — deliberate follow-up scope.