run
Machine-side executor for scoped server operations.
Responsibilities
- Register with platform and report heartbeat, version, capabilities, and capacity.
- Claim and execute jobs for server lifecycle, file/config work, backups, updates, and bounded database or command work.
- Collect server logs into local spool and upload acknowledged batches.
- Transfer artifacts with chunking, checksums, resume, throttling, and low priority.
- Optionally coordinate with a game client bridge when a specific game requires in-game commands or snapshots.
Required Directory Plan
Implementation should use dedicated directories for:
api/: platform-facing HTTP/gRPC client adapters.protocol/: control, job, log, artifact, and game-client bridge DTOs.domain/: executor domain types.runtime/: local execution and server process orchestration.spool/: local durable log/job/artifact queues.artifact/: chunk transfer implementation.logingest/: log collectors and uploaders.config/: configuration structures and loading.shared/: small shared helpers.
Logs and artifacts must have separate queues and priority controls.
Development Baseline
Tooling:
- Go 1.25.1.
- Module:
browser.local/run.
Commands:
go test ./...
go run ./cmd/run
Runtime configuration:
RUN_MODE: local mode, defaultsmoke.RUN_PLATFORM_URL: platform base URL, defaulthttp://127.0.0.1:8080.RUN_ENDPOINT_ID,RUN_DISPLAY_NAME,RUN_VERSION,RUN_REGISTRATION_TOKEN: worker identity and registration metadata.RUN_PACKAGE_CONFIG: optional path to a generated platform package config. When set, run validates the config, uses itsauthKeyas the registration token, and sends server/component identity plus key generation during control hello.RUN_WORKSPACE_ROOT,RUN_SPOOL_ROOT: scoped local server workspace and separate local log/artifact queues.RUN_MAX_JOBS,RUN_HEARTBEAT_INTERVAL_MS,RUN_POLL_INTERVAL_MS,RUN_RETRY_BACKOFF_MS: worker capacity and scheduling controls.
For local direct debugging, copy run/.env.example to run/.env, edit the values, and run:
set -a
source .env
set +a
go run ./cmd/run
Use RUN_MODE=worker when you want the executor to register, heartbeat, claim jobs, and execute lifecycle templates. Use RUN_MODE=smoke for a one-shot config summary.
Generated run and client-manager packages carry a secret-bearing JSON config created by platform. The config contains:
- component kind:
runorclient-manager. - server instance ID, plugin ID, optional run endpoint ID, optional client-manager profile key.
- target OS/architecture, redacted
secret://runtime-keys/.../currentref, key generation, and the raw current auth key needed by the remote executable.
The raw auth key is valid only while it matches the single current encrypted key stored in platform for that server/component. Resetting the run key or a client-manager key increments generation and makes older packages fail control hello authentication until the operator regenerates and redeploys the affected package. Local diagnostics and smoke summaries use fingerprints and secret refs, not raw keys.
In Docker, RUN_PLATFORM_URL must be http://platform:8080 because platform is the compose service name. Locally, keep it as http://127.0.0.1:8080.
Current executable behavior includes smoke mode plus worker mode. Worker mode registers with platform, opens a signed persistent control event stream for lightweight wakeups, sends heartbeat metadata, claims lifecycle jobs, acknowledges leases, reports bounded progress, executes scoped process.install, process.start, and process.stop command templates inside per-server workspaces, polls cancellation, submits terminal results, and reconciles active jobs.
Lifecycle templates are JSON files addressed by logical keys under the server workspace. They resolve to direct executable/argument vectors, not shell strings. Absolute paths, parent traversal, raw credentials, direct sockets, shell launchers, unsafe environment keys, and unsafe output are rejected or redacted. Plugin-declared Windows .cmd and .bat assets are launched through a bounded cmd.exe adapter and remain under the same process supervisor. Process identity journals are namespaced by Run endpoint, server, plugin, and component profile, so multiple Run services cannot overwrite one another; a restart migrates matching legacy state, reopens the persisted output files, reconciles the PID, and resumes stdout/stderr tailing. Process stdout/stderr is written to the log spool, and lifecycle result metadata is queued through artifact hooks so control heartbeat and job result submission stay independent from log and artifact work.
The control event stream carries only small hints such as control.ready, control.heartbeat, and job.changed. It never carries assignments, logs, artifact chunks, file bodies, host paths, credentials, or direct sockets; Run still fetches work through the durable job claim channel after a wake event.
Runtime Profiles And Distribution Jobs
Run resolves plugin-declared runtime profiles using server runtime bindings supplied by platform. Supported modes are:
local-process: run starts/stops the third-party server through scoped lifecycle action refs and tails stdout/stderr.hosted-ftp-rcon: run exposes only declared FTP/log/RCON adapters for hosted servers that cannot be started locally.ftp-only: run exposes declared FTP and log transfer surfaces without lifecycle or RCON control.custom-client: run coordinates with a plugin-declared companion client manager using a separate component key and profile ref.
Profile resolution returns logical capabilities, transport keys, declared log sources, discovery probes, and missing binding keys. It must not return raw host paths, FTP credentials, SQL DSNs, RCON passwords, direct sockets, or component auth keys.
Worker mode now dispatches distribution capabilities in addition to lifecycle work:
run.self-update: validates the update assignment, downloads by artifact ref, verifies checksum/signature hooks, stages the replacement, and reports rollback-safe status through a bounded result ref.dependencies.check: executes a typed plugin-declared probe using logical target keys such asdependencies/java-21.dependencies.install: executes only typed install plans addressed underdependencies/install/...; arbitrary shell snippets are rejected before execution.logs.backfill: advances historical log cursors for declared sources and returns a cursor/result artifact ref instead of embedding large log bodies in job results.
Declared file log sources use a tailer with offset checkpoints and redaction before entries enter the durable log channel. FTP/rsync, SQL read, RCON command, and file transfer adapters are represented as bounded envelopes with scoped input or artifact refs. Long transfers remain lower priority than heartbeat, job ack/result, cancellation polling, reconcile, and log acknowledgement.
Protected SQL, RCON, and management-program requests use a separate signed one-time input route after Run claims a single-attempt fenced job. Run rechecks approval, expiry, server/endpoint/fence, capability kind, and logical transport/target bindings before dispatching to a local handler. Request text, private connection configuration, and response bodies do not enter assignments, journals, or terminal results. Management-program stdout/stderr is redacted into the durable management-program log source rather than file execution logs. See protocol/protected-request.md.