Complete SCUM controlled deployment lifecycle

This commit is contained in:
npc0-hue
2026-07-25 10:13:53 +08:00
parent 6cfd929f7f
commit 15789e15b4
28 changed files with 1349 additions and 123 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-07-25
@@ -0,0 +1,63 @@
## Context
`ServerDeploymentDefinition` currently carries generic mode, paths, commands, and create inputs. `dispatchLifecycleJob` forwards that definition, while `projectLifecycleJobResult` only projects a generic ready/running/stopped state. The SCUM manifest has a SteamCMD app id and create fields, but no contract tying those fields to a real SCUM config file or verification evidence. The Run executor is a separate repository, so Platform must define a complete, bounded wire contract without pretending to implement host execution locally.
## Goals / Non-Goals
**Goals:**
- Make install and adoption separate operations with authoritative Run preflight.
- Freeze a SCUM template into each leased job so plugin changes cannot mutate an in-flight deployment.
- Return safe, structured scan/config/verification projections that the future UI can render.
- Keep all raw paths, commands, credentials, and sockets inside Run; public Platform views expose only configured flags, logical keys, facts, and stable error codes.
- Preserve idempotency, retry, cancellation, and channel separation already used by lifecycle jobs.
**Non-Goals:**
- Implementing SteamCMD, SCUM binaries, Windows process control, or filesystem scanning in this repository.
- Allowing arbitrary plugin commands, arbitrary config paths, or direct browser-to-Run access.
- Replacing the existing generic lifecycle protocol for non-SCUM plugins.
## Decisions
### 1. Add a typed SCUM deployment template to runtime profiles
Add `serverDeployments` to `GamePluginRuntimeProfiles`. A profile contains a stable key/version, target OS/architecture, Steam app id, executable marker, install root logical key, config file logical key, field-to-config mappings, discovery markers, and verification checks. The SCUM manifest declares one Windows template for app `3792580` and explicit mappings for `serverName`, `gamePort`, `queryPort`, and `maxPlayers`.
This is preferred over teaching Run to infer SCUM behavior from `createInputs` or free-form action JSON. Inference would make the same directory mean different things in different versions and would be impossible to audit.
### 2. Freeze the template into the leased assignment
`JobExecutionInput` gains a `ServerDeploymentPlan` containing `schemaVersion`, operation (`install` or `adopt`), template identity, and bounded template data. The existing protected `ServerDeploymentDefinition` remains the source of operator paths/commands. DTO conversion exposes the plan only in `RunJobAssignmentResponse.executionInput`, never in browser-facing job or server responses.
### 3. Return bounded lifecycle evidence through the terminal result
`JobExecutionResult` gains an optional `ServerDeploymentEvidence` object. It records preflight checks, discovery facts (executable/version/ports/config/log markers as logical names), config mapping outcomes, verification checks, and a stable failure code. Values are bounded and path/command redacted. Platform persists a safe projection on `ServerInstance` and only projects `ready` when the required verification checks pass.
This uses the existing job result channel so control, logs, and artifacts remain independent. Large scan output or logs use existing artifact/log channels and are referenced, not inlined.
### 4. Use explicit install/adopt operation semantics
Guided install dispatches `install`: preflight → SteamCMD install → config materialization → launch/status health checks. Existing-server adoption dispatches `adopt`: preflight → scan → optional reviewed config mapping → status health checks. A failed scan never silently falls back to install, and a failed verification projects `failed` with an actionable code.
### 5. Persist safe projection, not host evidence
Add a `ServerDeploymentProjection` to `ServerInstance` with state, operation, template key/version, safe discovered facts, mapping status, verification status, failure code, and timestamps. No raw path, command, credential, process id, or socket appears in the projection or DTO.
## Risks / Trade-offs
- [Run is in an independent repository] -> Version the contract and add fixture-based Platform tests; mark real execution dependent on the coordinated Run implementation.
- [Existing installations have different config layouts] -> Discovery reports marker confidence and config mapping status; adoption requires explicit operator approval when mapping is incomplete.
- [Evidence can grow large] -> Enforce bounded counts/lengths and use artifact references for detailed reports.
- [Old Run versions cannot understand the plan] -> Gate dispatch on a new capability string and reject before changing server state.
## Migration Plan
1. Ship additive domain/DTO/protocol types and manifest declarations; old plugins continue using the legacy lifecycle path.
2. Gate SCUM controlled install/adopt on `deployment.scum.v1` capability. Existing generic `deployment.plan.v1` remains valid for other plugins.
3. Coordinate the independent Run implementation and enable the capability only after its contract tests pass.
4. Update the frontend to render the persisted projection and evidence; rollback leaves legacy deployments untouched.
## Open Questions
- The exact SCUM config filename can vary by distribution. The first template uses the known `ServerSettings.ini` logical marker and allows Run to report a discovered alternate marker without exposing its absolute path; a later template version can add mappings without changing the Platform projection.
@@ -0,0 +1,28 @@
## Why
The current SCUM workflow treats a directory and a few generic fields as if they were a complete installation. That cannot distinguish a new SteamCMD install from adoption of an existing server, cannot prove that SCUM configuration was materialized, and marks a job ready without a game-specific health check.
## What Changes
- Add a versioned SCUM deployment template that declares the Steam app, supported target, executable markers, config file mappings, discovery markers, and post-install verification checks.
- Extend the Platform-to-Run job contract with bounded preflight, install/scan projection, config mapping, and verification evidence; keep protected paths and commands Run-local.
- Persist a safe deployment projection for operators: preflight state, discovered runtime facts, config mapping status, verification state, and stable failure codes without raw host paths or command text.
- Make SCUM install and adopt operations explicit and idempotent. A new install must run install and configure phases; adoption must scan before any managed write.
- Add contract tests and manifest validation for the complete SCUM lifecycle. The UI will consume these projections after the backend contract is in place.
## Capabilities
### New Capabilities
- `scum-deployment-lifecycle`: Game-specific controlled install/adopt plans, scan projections, config mappings, and post-install verification.
### Modified Capabilities
- `run-job-channel`: Leased deployment jobs carry a validated SCUM template and return bounded lifecycle evidence.
## Impact
- Affects `platform/domain`, `platform/dto`, `platform/service`, `platform/validator`, and `platform/protocol`.
- Affects `plugins/manifests/game-plugin.manifest.schema.json`, SCUM manifest assets, and plugin validation tests.
- Requires a coordinated implementation in the independent Run repository before real machines can execute the new template; this repository provides the authoritative contract and safe projection.
- Does not add billing, cloud host sales, direct SSH, raw host paths to browser/plugin responses, or a Run source tree here.
@@ -0,0 +1,59 @@
## ADDED Requirements
### Requirement: SCUM deployments use a versioned game template
The Platform SHALL register a versioned SCUM server deployment template that declares the Steam app id, compatible target, executable marker, install root logical key, config file logical key, supported field mappings, discovery markers, and required verification checks. A leased install or adoption job MUST freeze the template version used for that job.
#### Scenario: Guided SCUM install template
- **WHEN** an operator creates a SCUM server with guided installation on a compatible Windows Run node
- **THEN** Platform dispatches an `install` job with the frozen SCUM template, Steam app `3792580`, and mappings for the declared SCUM fields
- **AND** the assignment contains no raw browser credential or direct socket
#### Scenario: Unsupported Run is rejected
- **WHEN** the selected Run node does not advertise `deployment.scum.v1`
- **THEN** Platform rejects the deployment before changing the instance to installing
- **AND** the response identifies the missing capability without exposing host details
### Requirement: New install and existing-server adoption are distinct
The Platform SHALL dispatch guided installation and existing-server adoption as different operations. Installation SHALL perform preflight, SteamCMD install, configuration materialization, and health verification. Adoption SHALL perform preflight and discovery first, and SHALL NOT reinstall or overwrite existing configuration without an explicit approved mapping request.
#### Scenario: Adoption discovers an existing server
- **WHEN** an operator chooses existing-server adoption
- **THEN** Run scans the selected logical server root and returns bounded executable, version, port, config-marker, and log-marker facts
- **AND** Platform persists those facts as a safe deployment projection
#### Scenario: Adoption scan fails
- **WHEN** the scan cannot identify a compatible SCUM executable or required marker
- **THEN** the instance remains failed or draft with a stable failure code
- **AND** Platform does not silently switch to install
### Requirement: SCUM configuration mappings are explicit and reviewable
The SCUM template SHALL map only declared create fields to known logical configuration keys. Run SHALL report each mapping as `applied`, `unchanged`, `skipped`, or `failed` with a bounded reason code. Platform SHALL require successful required mappings before reporting an install as ready.
#### Scenario: Materialize SCUM settings
- **WHEN** a new SCUM install completes SteamCMD setup with valid inputs
- **THEN** Run applies `serverName`, `gamePort`, `queryPort`, and `maxPlayers` through the frozen mappings
- **AND** the evidence reports the mapping outcomes without returning the absolute config path
#### Scenario: Unsupported field is submitted
- **WHEN** a create request includes a field not present in the template mapping
- **THEN** Platform rejects the request before dispatch
### Requirement: Installation completion requires verification evidence
The Platform SHALL accept SCUM installation as ready only when Run returns successful required checks for executable presence/version, configured ports, config readability, and process health. A terminal success without required evidence SHALL be rejected as an invalid result.
#### Scenario: Health verification succeeds
- **WHEN** Run reports all required SCUM checks as passed
- **THEN** Platform projects the instance to ready after install, or running after start
- **AND** the deployment projection records the verification timestamp and template version
#### Scenario: Verification fails
- **WHEN** any required check fails
- **THEN** Platform projects the job as failed with a stable error code and keeps the raw diagnostic local to Run
### Requirement: Deployment evidence is safe for browser projection
Public server, job, marketplace, and plugin bridge responses SHALL expose only bounded logical facts and configured/reviewable state. They MUST NOT expose raw host paths, command text, credentials, process ids, or direct sockets.
#### Scenario: Operator reads deployment status
- **WHEN** an operator opens a SCUM deployment status view
- **THEN** the response includes operation, template version, discovery/mapping/verification states, and safe failure code
- **AND** it omits the supplied server root, working directory, install/start/stop commands, and any secret material
@@ -0,0 +1,23 @@
## 1. Contract and domain model
- [x] 1.1 Add typed SCUM deployment templates, config mappings, discovery markers, verification checks, and safe deployment projections to `platform/domain`.
- [x] 1.2 Extend Run assignment/result DTOs and conversion with versioned deployment plans and bounded evidence; keep public projections redacted.
- [x] 1.3 Add validator rules and capability gating for `deployment.scum.v1`, bounded evidence, operation-specific requirements, and required verification checks.
## 2. Platform lifecycle behavior
- [x] 2.1 Freeze the selected SCUM template into install/adopt jobs and distinguish `install` from `adopt` dispatch semantics.
- [x] 2.2 Persist Run evidence into the safe server deployment projection and gate ready/running state on required verification.
- [x] 2.3 Add server deployment status DTO/API projection for preflight, scan, mapping, verification, and stable failure codes.
## 3. SCUM plugin assets
- [x] 3.1 Extend the manifest schema and domain conversion for `serverDeployments`.
- [x] 3.2 Declare the SCUM Windows SteamCMD template, executable/config markers, field mappings, adoption scan markers, and post-install checks in the first-party manifest.
- [x] 3.3 Add manifest validation and fixture tests for the SCUM template and unsafe-value rejection.
## 4. Verification and handoff
- [x] 4.1 Add Platform unit/contract tests covering install/adopt semantics, target/capability rejection, mapping validation, evidence projection, and redaction.
- [x] 4.2 Add protocol documentation and Run coordination notes for the independent executor implementation.
- [x] 4.3 Run Go tests, plugin typecheck/test/manifest validation, `scripts/check-structure.sh`, and `openspec validate complete-scum-deployment-lifecycle --strict`.