platform
Backend control plane for the game server management platform.
Responsibilities
- Users, roles, permissions, sessions, and audit.
- Game management plugin installation metadata and marketplace views.
- Server instance records and lifecycle orchestration.
- AI provider configuration and platform-mediated AI invocation.
- Run registration, capabilities, jobs, artifacts, log stream metadata, and storage adapters.
Required Directory Plan
Implementation should use dedicated directories for:
api/: route wiring and HTTP/gRPC adapters.dto/: request and response structures.domain/: business types and aggregates.model/: database models only.repo/: repository interfaces and persistence implementations.service/: use cases and orchestration.protocol/: run, plugin, artifact, log, and AI contracts.validator/: validation rules.config/: configuration structures and loading.shared/: small shared helpers.
Do not put DTOs, database models, or protocol structs inside handlers or service functions.
Development Baseline
Tooling:
- Go 1.25.1.
- Module:
browser.local/platform.
Commands:
go test ./...
go run ./cmd/platform
Runtime configuration:
PLATFORM_ADDR: local listen address, default:8080.PLATFORM_STORAGE_BACKEND: storage backend, defaultfile; usememoryonly for tests or disposable local runs.PLATFORM_MYSQL_DSN: MySQL DSN used whenPLATFORM_STORAGE_BACKEND=mysql, for exampleplatform:platform@tcp(127.0.0.1:3306)/platform?parseTime=true.PLATFORM_DATA_DIR: default platform data directory, default.platform-data.PLATFORM_METADATA_PATH: file-backed metadata snapshot path, default.platform-data/metadata.json.PLATFORM_LOG_BODY_BACKEND: log body backend, default follows metadata backend except MySQL usesfile; supported values arefileandmemory.PLATFORM_LOG_DIR: segmented log body directory, default.platform-data/logs.PLATFORM_ARTIFACT_DIR: private durable artifact body/transfer directory, default.platform-data/artifacts.PLATFORM_BOOTSTRAP_ADMIN_EMAIL: optional initial platform administrator email.PLATFORM_BOOTSTRAP_ADMIN_PASSWORD: optional one-time bootstrap password; the platform applies no default and persists only a password verifier.PLATFORM_SECRET_ENVELOPE_KEY: external secret used to derive the AES-GCM component-key envelope key; use at least 32 random characters and keep it stable across restarts.PLATFORM_BUILDER_DOCKER_BINARY: Docker-compatible CLI used by the platform builder, defaultdocker.PLATFORM_BUILDER_IMAGE: prebuilt, explicitly versioned or digest-pinned builder image, defaultbrowser-platform-distribution-builder:1.0.0; floating tags such aslatestare rejected.PLATFORM_BUILDER_SOURCE_DIR: read-only Run source snapshot containinggo.mod; this is required for builder readiness.PLATFORM_BUILDER_WORKSPACE_DIR: private per-plugin/per-job build workspace, default<PLATFORM_DATA_DIR>/distribution-builds.PLATFORM_BUILDER_TIMEOUT_SECONDS: positive build deadline, default1800.PLATFORM_RUN_RELEASE_URL: public platform URL embedded into generated components, defaulthttps://scum.npc0.com.
Build the dedicated toolchain image before enabling distribution generation:
docker build --pull -t browser-platform-distribution-builder:1.0.0 distribution-builder
export PLATFORM_BUILDER_SOURCE_DIR=/absolute/path/to/read-only/run-source-snapshot
export PLATFORM_BUILDER_IMAGE=browser-platform-distribution-builder:1.0.0
go run ./cmd/platform
Each build runs in a separate read-only container. The platform mounts source and per-job input read-only, mounts only the job build/output directories writable, and passes the component auth key through a mode-0600 input file. The key is not sent through the machine-side job channel or Docker arguments. Production deployments may use an internal-registry image@sha256:... reference; the selected image must already exist in the Docker daemon because builds run with --pull never.
MySQL configuration example:
export PLATFORM_STORAGE_BACKEND=mysql
export PLATFORM_MYSQL_DSN='platform:platform@tcp(127.0.0.1:3306)/platform?parseTime=true'
export PLATFORM_LOG_BODY_BACKEND=file
export PLATFORM_LOG_DIR=.platform-data/logs
go run ./cmd/platform
MySQL is the platform metadata database here. It stores the platform metadata snapshot table and should later hold normalized users/plugins/servers/jobs/audit/log stream indexes. It is not the high-volume log body store; keep log bodies in segmented files locally, or add a future ClickHouse/Loki/OpenSearch/object-storage LogBodyStore adapter for production scale.
For local direct debugging, copy platform/.env.example to platform/.env, edit the values, and run:
go run ./cmd/platform
The platform process automatically reads root .env and platform/.env before loading configuration. Explicitly exported process environment values still take precedence over values in those files.
For Docker, the root docker-compose.yml sets platform data under /data/platform and mounts it through the platform-data named volume.
Current executable behavior includes the platform API, durable hashed auth/Run sessions with expiry/revocation/rotation, strict production route authorization, durable file-backed metadata, segmented log bodies, authenticated run control/job/log/artifact routes, plugin bridge dispatch, platform-mediated AI invocation, real typed dependency execution orchestration with reviewed plan digests, and target-fenced transactional Run self-update staging/health/rollback projections.
Client Manager lifecycle
Client Manager installations are durable aggregates separate from Run distributions and sessions. Their safe state projection is requested -> building -> available -> deploying -> installed -> registering -> online, with degraded, offline, updating, rolling_back, stopping, failed, and uninstalled recovery states. Deploy, control, update, rollback, revoke-session, retry, and uninstall are typed jobs; Platform persists intent before dispatch and gates each action by actor/server ownership, plugin profile, binding, endpoint capability, artifact target/revision, key generation, and lifecycle state.
Component registration uses the current client-manager key generation, a timestamped nonce, and a short-lived hashed component session. It never reuses a Run session or job lease. Key reset revokes old sessions/artifacts and marks the installation for current-generation rebuild/redeploy. Run reports only logical health, phase, and bounded execution evidence; host paths, PIDs, sockets, raw keys, and credential material are not operator or plugin projections. Production KMS/code-signing, private source credentials, and fleet rollout remain explicit non-goals.
Validated plugin runtime profiles and per-server runtime bindings are part of durable metadata. Server creation requires only the plugin type and server name; operators set a declared profile and complete logical bindings after creation, before any gated lifecycle/runtime action. Browser and plugin-facing responses expose readiness only, not binding values. Platform-owned Docker builds need no registered Run endpoint with distribution.build; component keys remain in platform-controlled per-job input. This change uses controlled secret references and an injectable AES-GCM component-key envelope. The built-in envelope key is a disposable-development compatibility fallback; deployments must set PLATFORM_SECRET_ENVELOPE_KEY. This is not a production vault/KMS or machine-side runtime resolver. Durable scheduling, process supervision, durable log/artifact bodies, bounded metrics/backups, declaration-backed remote adapter envelopes, typed dependency installation, and transactional Run self-update are implemented. Client-manager lifecycle, production signing/fleet rollout, external provider/storage adapters, production scaling/alerts, plugin lifecycle, and real AI-provider integration remain separate tasks.