We have made significant progress on our way to the 1.0 release.
What Shipped
Control plane skeleton. ggscale-server is a single Go binary using the chi router, slog structured JSON logging, and Prometheus metrics at /metrics. It starts in under 200ms and exposes GET /v1/healthz returning {"status":"ok","version":"v1","commit":"<sha>"}.
Postgres + Row-Level Security. Migration 0009_rls.up.sql enables RLS on every tenant-scoped table with a single policy: tenant_id = current_setting('app.tenant_id', true)::bigint. The , true flag makes a missing GUC return NULL, so the policy fails closed. Combined with the HTTP middleware that injects tenant_id into every authenticated request, this gives us defence-in-depth tenant isolation from day one.
K3s + Agones smoke test. The CI e2e job starts the full compose stack including a single-node K3s cluster and an Agones install. The smoke test (TestAgonesAllocation_AssignsHostPort_ReachableViaUDP) allocates a GameServer CRD, waits for Status.State == Ready, reads the dynamic UDP port, and asserts the simple-game-server image echoes a packet back. This is the parity contract the rest of the fleet work builds on.
CI pipeline. Three jobs on ubuntu-24.04: lint-test (golangci-lint, go test -race, govulncheck), docker-build (multi-stage, exported as artifact), and e2e (loads the artifact, starts the k8s compose profile, runs the smoke test). Action versions are SHA-pinned; workflow permissions default to contents: read.
Olric embedded cache. CACHE_BACKEND=olric starts an embedded Olric cluster in-process across the app VMs in each region. Rate limiting and connection-cap state are shared regionally without a separate cache service. CACHE_BACKEND=memory (default) covers dev, single-VM self-host, and integration tests.
What’s Next:
The next chunk of work adds the tenant-gated API surface:
POST /v1/auth/signup,/v1/auth/login,/v1/auth/refresh,/v1/auth/logout/v1/storage/*: tenant-isolated key-value blob storage/v1/leaderboards/*: per-project ranked leaderboardsinternal/tenantHTTP middleware: extractsAuthorization: Bearer <api_key>, hashes SHA-256, looks upapi_keystable, injectstenant_idinto context- HTTP rate limiting (sliding window per API key via Olric/memory token bucket) and WebSocket connection caps