Admin & probes
HTTP endpoints share the WS port by default (single-port mode).
Set adminPort on createServer to split
them onto a private listener.
Routes
| Path | Purpose |
|---|---|
| GET /livez | process alive — always 200 |
| GET /readyz | 200 if the platform adapter is connected, else 503 |
| GET /healthz | JSON diagnostics: core / game version, math identity per mode, platform diagnostics. 503 if unhealthy |
| GET /admin/logs | ring buffer of recent log lines. Query ?level=&limit= |
| GET /admin/metrics | Prometheus exposition (text format) |
| GET /admin/sessions | active session list |
| GET /admin/manifest | serialised GameManifest |
| GET /admin/modes | client-visible mode catalog (excludes internal: true) |
| POST /admin/autoclose | external autoclose trigger: { sessionId, roundId?, reason } |
Suffix matching
Every route is suffix-matched. That means
/healthz, /api/healthz, and
/api/<gameId>/healthz all hit the same handler.
Works behind any ingress rewrite without configuration.
/healthz shape
{
"status": "ok" | "degraded",
"core_version": "0.3.0",
"game_version": "1.4.2",
"game_id": "hello-spin",
"declared_rtp": 0.95,
"modes": {
"default": { "name": "hello", "version": "0.1.0", "kind": "simple",
"rtp": 0.95, "hash": "<sha256>" }
},
"platform": { "healthy": true, "diagnostics": { ... } },
"uptime_s": 12345
} POST /admin/autoclose
curl -X POST https://game.example.com/admin/autoclose \
-H 'content-type: application/json' \
-d '{ "sessionId": "abc-123", "reason": "ops-close" }'
# 200 OK
{ "closed": true, "roundId": "r_842" }
# 200 OK (no round to close)
{ "closed": false, "reason": "no_round_open" }
Autoclose is never timer-driven inside the RGS — every autoclose
is initiated by an external signal (this endpoint, or a wallet
autocloseRequested event). Keeps policy decisions
where they belong: upstream.