weiqi-server
apps/weiqi-server is the gateway. It validates session cookies against
auth-app, owns every game record, calls KataGo through the configured
IKatagoClient, persists analysis snapshots, and exposes real-time updates
over Socket.IO. It is the only writer of game state.
Bootstrap
Section titled “Bootstrap”src/main.ts:14 boots NestJS on PORT (default 3002) with:
- Global prefix
/api. - Swagger at
/api-json. cookie-parserand a custom CORS origin allow-list fromCORS_ORIGINS.- A Socket.IO adapter for real-time.
Swagger is published at http://localhost:3002/api-json — useful for
generating client types against bot-game.api.ts.
modules/accounts/presentation/guards/auth.guard.ts:30 reads the
better-auth.session_token cookie. The __Secure- prefix is tried first so
the same code path works in production (HTTPS-only cookie) and dev (plain
cookie). The guard calls AccountsService.validateSession, which proxies to
auth-app, and attaches {user, session} to the request.
Decorators:
Auth(...roles)(auth.decorator.ts:29) — require roles (user,mod,admin,super_admin).Authenticated— any signed-in user.Public— opt out of the guard.WsAuthenticated— Socket.IO counterpart, inws-auth.guard.ts:25.
REST surface
Section titled “REST surface”All paths are /api-prefixed.
accounts (modules/accounts)
Section titled “accounts (modules/accounts)”| Method | Path | Notes |
|---|---|---|
| GET | /accounts/me | Current user profile. |
| PATCH | /accounts/me | Update display name / avatar. |
game (modules/game)
Section titled “game (modules/game)”| Method | Path | Notes |
|---|---|---|
| POST | /games | Create a PvP game record. |
| GET | /games | List games for the current user. |
| GET | /games/:id | Fetch game metadata + last move cursor. |
| PATCH | /games/:id | Update metadata (e.g. archive). |
| POST | /games/:id/moves | Append a move; validates with weiqi-engine. |
| GET | /games/:id/moves | Paginated move history. |
game/bot (modules/bot)
Section titled “game/bot (modules/bot)”| Method | Path | Notes |
|---|---|---|
| GET | /game/bot/levels | Catalog of ten strength levels (see Bot Ladder). |
| POST | /game/bot/games | Start a new bot game. Body: { level, boardSize? }. |
| GET | /game/bot/games/:id | Game state (board, players, last move, status). |
| GET | /game/bot/games/:id/moves | Move list. |
| GET | /game/bot/games/:id/review | Latest KataGo review (runFullReview result). |
| POST | /game/bot/games/:id/move | Player move; replies with the bot’s move. |
| POST | /game/bot/games/:id/resign | Resign the game. |
| POST | /game/bot/games/:id/hint | One-move hint (entitlement-gated; see Bot Ladder). |
| POST | /game/bot/games/:id/undo | Undo last move (if the game allows it). |
| GET | /game/bot/ladder/me | { rating, optIn, today }. |
| POST | /game/bot/ladder/opt-in | Toggle ladder opt-in. Body: { optIn: boolean }. |
| GET | /game/bot/ladder/history?limit=50 | Most recent rating deltas. |
analysis (modules/analysis)
Section titled “analysis (modules/analysis)”| Method | Path | Notes |
|---|---|---|
| POST | /analysis/games/:id/runFullReview | One-call whole-game review via analyzeTurns: [0..N]. See KataGo Review. |
| GET | /analysis/games/:id/snapshots | Per-node snapshots persisted in board_ai_snapshots. |
| GET | /analysis/games/:id/graph | Plottable winrate / score-lead series. |
challenges (modules/challenges)
Section titled “challenges (modules/challenges)”| Method | Path | Notes |
|---|---|---|
| POST | /challenges | Submit a new challenge (SGF / image). |
| GET | /challenges | Browse approved challenges. |
| POST | /challenges/:id/solution-attempts | Submit a solution. |
| GET | /challenges/moderation/list | Moderator queue. Role-gated. |
| POST | /challenges/moderation/approve | Approve a submission. |
| POST | /challenges/moderation/reject | Reject a submission. |
| GET | /challenges/my-submissions/list | Caller’s own submissions. |
agent (modules/agent)
Section titled “agent (modules/agent)”A LangGraph analytics agent backed by WeiqiAnalyticsTool. Used by the admin
console for natural-language queries over solutionAttempts (e.g. “what is
the most failed life-and-death shape this week?”).
Real-time (Socket.IO)
Section titled “Real-time (Socket.IO)”Events emitted by BotRealtimeEmitter:
| Event | Payload | When |
|---|---|---|
gameState | Full game snapshot | After every state mutation. |
botMove | { gameId, move, classification?, rootInfo? } | After the bot plays a move. |
classified | Per-move MoveClassification (good / inaccuracy / mistake / blunder) | After KataGo review run. |
gameEnded | Final { winner, score, reason } | On game termination. |
The AnalysisGateway exposes parallel events for live runFullReview
progress (turns emitted as KataGo returns them).
KataGo clients
Section titled “KataGo clients”modules/game/infrastructure/katago/ defines IKatagoClient
(types.ts:88). The active implementation is selected by env:
GrpcKatagoClient— default; talks tokatago-servicegRPC atKATAGO_GRPC_URL=localhost:50051.HttpKatagoClient— used whenKATAGO_SERVICE_URLis set (http://localhost:4011).BullMqKatagoClient— in-process queue; useful for local dev without the dedicatedkatago-service.MockKataGoClient— tests.
The orchestrator KatagoService (katago.service.ts:21) exposes:
getMove(analyzeOptions): Promise<KatagoTurnResponse>getAnalysis(analyzeOptions): Promise<KatagoAnalysisResponse>getGameReview(analyzeOptions): Promise<KatagoAnalysisResponse>— setsanalyzeTurnsto replay the entire game.getPolicy(analyzeOptions): Promise<KatagoPolicyResponse>analyzeForHint(gameState): Promise<HintResponse>— bounded visits.
Database
Section titled “Database”Drizzle ORM on Postgres. Schema lives in
infrastructure/database/database.module.ts:8. Tables most relevant to the
public API:
botGames,botGameMoves,botGameReviews— bot ladder game records.botRankHistory,botRatings— ladder rating per user.boardRecords,boardNodes— generic board records and node tree.boardAiSnapshots,boardAiReviews— KataGo snapshots and aggregated reviews.solutionAttempts,solutionAttemptMoves,problems— challenge system.players— minimal player metadata; canonical user lives inauth-app.
Local dev
Section titled “Local dev”cp apps/weiqi-server/.env.example apps/weiqi-server/.envcd apps/weiqi-serverdocker compose up -d # Postgres 54320, Redis 6379, MinIO 9000docker compose --profile recognition up -d # optional, for board photo scancd ../..pnpm --dir apps/weiqi-server devTests:
pnpm --dir apps/weiqi-server test # jest