89 lines
8.4 KiB
Markdown
89 lines
8.4 KiB
Markdown
# Run Job Contract
|
|
|
|
Jobs execute bounded server management work.
|
|
|
|
## Implemented Routes
|
|
|
|
- `POST /api/v1/run/jobs/claim`: claims one queued job for the registered run endpoint.
|
|
- `POST /api/v1/run/jobs/ack`: acknowledges an active leased job before execution.
|
|
- `POST /api/v1/run/jobs/progress`: reports bounded progress for an active leased job.
|
|
- `POST /api/v1/run/jobs/result`: submits a bounded terminal result for an active leased job.
|
|
- `POST /api/v1/run/jobs/cancel`: polls platform cancellation requests for active leased jobs.
|
|
- `POST /api/v1/run/jobs/reconcile`: reconciles platform-known active jobs after run restart or reconnect.
|
|
- `POST /api/v1/run/jobs/dependency-input`: loads a typed dependency probe/plan only for the active fenced attempt.
|
|
- `POST /api/v1/run/jobs/update-input`: loads approved same-server target-matched Run distribution metadata only for the active fenced attempt.
|
|
- `POST /api/v1/run/jobs/update-chunk`: reads one bounded resumable update artifact range; this lower-priority transfer route never carries browser download tokens or storage paths.
|
|
- `POST /api/v1/run/jobs/update-health`: reports a post-registration/post-reconciliation update success or rollback outcome through the current signed session.
|
|
|
|
## Payloads
|
|
|
|
- `RunJobClaimRequest`: session token, run ID, capacity, and supported capabilities.
|
|
- `RunJobClaimResponse`: optional job assignment with identity, capability, server instance, logical target key, scoped input ref, idempotency key, per-job attempt, max attempts, raw one-use lease token, ack deadline, execution lease deadline, and polling hint. Platform persists only the lease hash.
|
|
- `RunJobAckRequest`: job ID, run ID, session token, lease token, attempt, and bounded message.
|
|
- `RunJobProgressRequest`: job ID, run ID, session token, lease token, attempt, percent, sequence, and bounded message.
|
|
- `RunJobResultRequest`: job ID, run ID, session token, lease token, attempt, terminal state, progress, bounded message, error code, retryable flag, and result reference.
|
|
- `RunJobCancelPollRequest`: run ID, session token, job ID, lease token, and attempt.
|
|
- `RunJobReconcileRequest`: run ID, session token, and active journal entries containing job ID, lease token, and attempt. The response confirms matching attempts and returns stale/unknown IDs to discard.
|
|
- Dependency input contains only declared probe/plan summaries, logical bindings, target OS/architecture, and a reviewed plan digest. Update input/chunk responses contain only artifact ID, target, checksum, bounded range metadata, and payload bytes.
|
|
- Update health contains job ID, attempt/lease proof, outcome, and release version. Platform accepts success only after the terminal staged result and current online endpoint registration; Run does not claim success from a hello-only outcome.
|
|
|
|
## Local Journal
|
|
|
|
Run persists a versioned journal under its owner-only workspace state directory. Assignment writes are atomic and happen before acknowledgement. A locally completed terminal result is also persisted without the Run session token before transport; after restart, confirmed attempts replay that result instead of executing again. A staged self-update keeps its activation manifest alongside the pending result so a crash cannot silently discard helper activation. Entries are removed only after the platform accepts the result or reconciliation explicitly discards them. Registration is followed by reconciliation before new claims, including after session rotation.
|
|
|
|
## Lifecycle Executor
|
|
|
|
The runtime worker executes these bounded lifecycle job capabilities:
|
|
|
|
- `process.install`
|
|
- `process.start`
|
|
- `process.stop`
|
|
|
|
Platform-dispatched config/file jobs are now represented in the run job payload and validated before execution by later worker implementations:
|
|
|
|
- `config.write`: writes approved config content addressed by a logical config key plus scoped `input://...` ref.
|
|
- `files.read`: reads a declared logical file key and returns results through bounded metadata or artifact refs.
|
|
- `files.write`: writes content addressed by a logical file key plus scoped `input://...` or `artifact://...` ref.
|
|
|
|
Plugin-declared remote access jobs use the same job channel and remain bounded metadata envelopes:
|
|
|
|
- `remote.ftp.read` / `remote.ftp.write`: platform-mediated FTP file transfer requests.
|
|
- `remote.rsync.read` / `remote.rsync.write`: platform-mediated rsync file transfer requests.
|
|
- `remote.run.files.read` / `remote.run.files.write`: run-mediated logical file operations.
|
|
- `remote.run.process.start` / `remote.run.process.stop`: run-mediated remote process lifecycle operations.
|
|
- `remote.run.db.mysql.query` / `remote.run.db.sqlite.query`: run-mediated database read envelopes with scoped input refs for query payloads.
|
|
- `remote.run.logs.transfer`: run-mediated log transfer through log/artifact channels.
|
|
- `remote.run.rcon.command`: run-mediated RCON command envelopes with scoped input refs.
|
|
|
|
Run distribution and runtime support jobs use the same lightweight job lifecycle:
|
|
|
|
- `run.self-update`: downloads an approved same-server target-matched distribution in bounded resumable ranges, verifies the final checksum, safely extracts exactly the expected executable, preserves config, and reports a rollback-safe staged result. A helper activates only after result acceptance, then waits for health and restores the previous binary on timeout.
|
|
- `dependencies.check`: runs a plugin-declared typed dependency probe addressed by a logical `dependencies/...` key.
|
|
- `dependencies.install`: runs only an approved typed install plan addressed by `dependencies/install/...`; package, verified HTTPS download, SteamCMD, and manual steps are closed adapters, and arbitrary shell snippets, unsafe URLs/tokens, and unsupported targets are rejected.
|
|
- `logs.backfill`: advances historical log cursors for declared process, file, FTP, SQL, or plugin-specific sources and returns bounded cursor/result refs instead of log bodies.
|
|
|
|
The executor resolves lifecycle action templates under the scoped server workspace and runs direct command/argument vectors through the process supervisor. It does not run unrestricted shell strings, execute arbitrary plugin code, expose host paths, return raw credentials, open direct sockets, or embed logs/artifacts in job result payloads.
|
|
|
|
## Rules
|
|
|
|
- Job ack must be sent before execution.
|
|
- Ack deadline and execution lease timestamps are platform-authoritative. Progress and confirmed reconciliation renew only the current fenced attempt.
|
|
- Ack timeout, lease expiry, and retryable results follow the platform's bounded retry/backoff policy; Run never invents a replacement attempt locally.
|
|
- Cancellation polling is fenced and cancellation results are ordinary idempotent terminal results.
|
|
- Terminal result must be replayable while the journal retains the job.
|
|
- Large files must be passed as artifact references, not embedded in job payloads.
|
|
- Config/file job payloads must use logical target keys and scoped input/artifact refs.
|
|
- Remote database and RCON jobs must use scoped input/artifact refs rather than embedding query or command bodies in job results.
|
|
- Run self-update, dependency, and log backfill jobs must use declared capabilities, logical target keys, scoped refs, and bounded result refs.
|
|
- Job payloads must not include logs, artifact chunks, raw host paths, raw credentials, direct sockets, or large inline result bodies.
|
|
- Process stdout/stderr must be redacted and written to the log spool rather than embedded in progress/result bodies.
|
|
- Job ack/progress/result/cancel/reconcile calls are lightweight lifecycle metadata and must be able to complete while artifact/file transfer work is active or retrying.
|
|
- Dependency adapters and update downloads run in the job worker while control heartbeat, cancellation polling, log spool upload, and artifact upload retain independent bounded loops.
|
|
- Terminal results must remain idempotent under log and artifact retry pressure and must reference artifacts by safe `artifact://...` refs rather than embedding transfer payloads.
|
|
|
|
## Deferred Channels
|
|
|
|
Durable log ingest, artifact chunk transfer, and optional game client bridge traffic remain separate channels and must not be multiplexed through job result payloads. Artifact transfer carries chunk payloads only through `/api/v1/run/artifacts/*` routes.
|
|
|
|
Production code signing/KMS, rollout rings/fleet orchestration, client-manager lifecycle, plugin lifecycle, production scaling/alerts, and real AI-provider integration are explicitly outside this contract.
|