feat: support custom server deployment drafts
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-24
|
||||
@@ -0,0 +1,76 @@
|
||||
## Context
|
||||
|
||||
The platform currently creates an `installing` server instance only when a Run endpoint is already online. It records runtime bindings as safe logical references and dispatches only plugin/profile/action metadata. This prevents self-hosted operators from defining a server before Run is installed, from pointing at an existing absolute directory, and from using a nonstandard command such as a Python virtual environment launcher.
|
||||
|
||||
The independent Run repository remains the only host-side executor. Repository rules forbid returning host paths, raw credentials, or direct sockets from Run to Platform or plugins.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Persist an editable server deployment definition without a Run binding.
|
||||
- Support guided install, existing-server adoption, and custom lifecycle command modes.
|
||||
- Accept operator-entered absolute paths and command lines as protected write-only execution inputs.
|
||||
- Render and validate plugin create fields, including port and player-count fields.
|
||||
- Bind a saved definition to an online Run only at deployment/start time and send Run a versioned, redaction-safe execution plan.
|
||||
- Surface queued, claimed, preflight, install, configure, start, and health stages to the operator.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Platform-side SSH, shell execution, direct sockets, or a Run source tree in this repository.
|
||||
- Cloud hosting, billing, provider marketplaces, or automatic network/firewall provisioning.
|
||||
- Returning stored full paths, command text, or raw secrets through normal Platform APIs.
|
||||
- Guaranteeing a generic command works on a node whose Run policy disallows it.
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Separate deployment definitions from runtime bindings
|
||||
|
||||
Add a server deployment definition associated with a server instance. It holds deployment mode, plugin create inputs, protected path/command fields, configuration revision, and a binding state. Runtime bindings remain for plugin-declared logical adapters such as RCON and file transports.
|
||||
|
||||
This avoids weakening the existing logical-reference contract simply to accommodate physical deployment input. Reusing runtime bindings would make host paths appear in APIs that intentionally redact those values.
|
||||
|
||||
### 2. A server can exist as an unbound draft
|
||||
|
||||
`draft` is added as an editable server state. A draft has no `runEndpointId`, no queued lifecycle job, and can be created or edited before any Run registers. Binding and deployment are explicit later operations. `installing`, `ready`, `running`, `stopped`, and `failed` retain their existing lifecycle meaning.
|
||||
|
||||
The alternative—requiring a placeholder Run endpoint—would preserve the current coupling and create misleading jobs.
|
||||
|
||||
### 3. Paths and commands are protected write-only fields
|
||||
|
||||
The browser can submit full paths and command text as an operator action. Platform stores them in a protected deployment record and only sends them to the assigned Run via a leased job input. Read APIs return configured flags, a non-sensitive display mode, and a content fingerprint, never the value. Editing a protected value requires resubmission; an empty update preserves the stored value.
|
||||
|
||||
Raw credentials are rejected from commands and must be represented by secret references. This satisfies the host-path redaction rule while supporting real input such as `/srv/server/.venv/bin/python`.
|
||||
|
||||
### 4. Plugin templates are recommendations; custom commands override per lifecycle action
|
||||
|
||||
Plugins publish create-field schemas and optionally map inputs to recommended install/start/stop templates. Guided mode resolves these templates. Existing-server and custom-command modes permit an operator to provide a working directory plus install/start/stop commands; a missing install command is valid for adoption.
|
||||
|
||||
Run receives an argv-oriented command plan by default. A full shell command is allowed only when the operator explicitly selects a shell kind and the Run endpoint advertises the corresponding custom-process policy. This avoids accidental shell interpretation while allowing deliberate venv, batch, PowerShell, and shell-wrapper deployments.
|
||||
|
||||
### 5. Run preflight and lifecycle phases are first-class job progress
|
||||
|
||||
The lifecycle job execution input includes deployment revision, mode, protected plan, create inputs, and a bounded phase vocabulary: `queued`, `claimed`, `preflight`, `install`, `configure`, `start`, and `health`. Run validates paths/executables, policy, port availability, and plugin compatibility before any write. It reports only phase, percent, safe summary, and structured safe error code.
|
||||
|
||||
Platform shows these phases after submit and distinguishes an unclaimed job from a running job. A Run implementation is required in its independent repository; until it supports this input version, Platform must fail safely with an actionable compatibility reason.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [A custom command can be destructive] → Require server-owner/node-operator authorization, Run policy opt-in, explicit shell selection, bounded timeout, command fingerprint audit, and confirmation before dispatch.
|
||||
- [A path is sensitive operational data] → Treat it as write-only in read models and strip it from logs, job summaries, plugin bridge results, and diagnostics.
|
||||
- [Existing persisted instances assume a Run endpoint] → Migrate existing records unchanged; only newly created drafts omit it.
|
||||
- [Run protocol rollout lags Platform] → Version the execution input and make deployment unavailable with a clear compatibility result rather than silently ignoring user input.
|
||||
- [Port collision cannot be known from Platform] → Validate form shape in Platform, then make the Run preflight authoritative and return its safe diagnostic.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add deployment definition persistence and draft state while accepting all existing bound instances unchanged.
|
||||
2. Release Platform/Web support for draft creation and protected deployment updates.
|
||||
3. Release the versioned contract to Run; enable guided and custom dispatch only after Run reports the deployment-plan capability.
|
||||
4. Update first-party SCUM and Minecraft templates and add Palworld only as a separate plugin change.
|
||||
5. Roll back by retaining deployment definitions as drafts and refusing dispatch to incompatible Run versions; no host-side rollback is initiated automatically.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- The independent Run repository must define its exact supported custom shell identifiers and endpoint policy advertisement.
|
||||
- A separate Palworld plugin remains required; this change provides the shared deployment capability but does not invent a Palworld launcher.
|
||||
@@ -0,0 +1,31 @@
|
||||
## Why
|
||||
|
||||
服务器创建目前要求已注册的 Run 节点,并且只投递固定生命周期动作;插件声明的端口、人数和路径字段没有进入创建请求。真实自托管场景需要先创建和编辑服务器定义,再在 Run 可用时将其部署到任意用户指定的本机目录,并支持引导式或自定义命令部署。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增可在未绑定 Run 时保存的服务器部署草稿,并允许随后绑定 Run 节点和执行部署。
|
||||
- 新增部署方式:插件引导安装、接管已有服务器、用户自定义生命周期命令。
|
||||
- 将插件声明的创建表单字段变为实际可渲染、校验和持久化的游戏配置输入;SCUM 和 Minecraft 首先使用该能力。
|
||||
- 接受用户主动输入的完整服务器根目录、工作目录和命令,但将它们作为受保护执行输入:不在普通详情、任务摘要、日志或插件桥接中回显。
|
||||
- 新增 Run 预检、部署阶段进度和可诊断的排队/领取/执行状态,替代“任务已派发”即结束的体验。
|
||||
- **BREAKING** 扩展服务器创建与生命周期任务契约,使部署定义和受保护执行输入成为显式字段,而不是复用 runtime bindings。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `server-deployment-workflows`: 草稿、Run 绑定、部署方式、受保护执行输入、预检和阶段化部署状态。
|
||||
- `plugin-create-configuration`: 插件创建字段的安全发布、渲染、校验与 SCUM/Minecraft 配置映射。
|
||||
- `run-custom-process-execution`: Run 对用户定义安装/启动/停止命令的受策略控制执行与脱敏进度回报。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None; the repository has no baseline OpenSpec capability specifications.
|
||||
|
||||
## Impact
|
||||
|
||||
- `platform/`:领域模型、DTO、验证、持久化、服务器生命周期服务、任务执行输入和 API。
|
||||
- `platform_web/`:服务器创建向导、草稿编辑、部署进度与 API types/client。
|
||||
- `plugins/`:创建 schema、SCUM/Minecraft 声明和生命周期动作模板。
|
||||
- 独立 Run 仓库:需要实现新任务执行输入、路径预检、自定义进程策略及阶段进度;本仓库不包含其源码。
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Plugin create schemas drive server creation input
|
||||
The system SHALL publish validated plugin create-field schemas to the management console and SHALL render supported fields during server draft creation. Required fields, defaults, select options, numeric values, port values, and boolean values MUST be validated before saving.
|
||||
|
||||
#### Scenario: Create a SCUM definition
|
||||
- **WHEN** an operator chooses the SCUM plugin
|
||||
- **THEN** the console renders the declared server name, game port, query port, and maximum player fields with their declared defaults
|
||||
|
||||
### Requirement: Game configuration is distinct from runtime transport binding
|
||||
The system SHALL persist plugin create inputs as deployment configuration and MUST NOT store game ports, player limits, paths, or startup commands in runtime binding records.
|
||||
|
||||
#### Scenario: Save Minecraft port settings
|
||||
- **WHEN** an operator saves Minecraft game and RCON ports in a draft
|
||||
- **THEN** the values are retained as plugin create configuration and runtime binding remains reserved for declared transports
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Run executes protected custom lifecycle plans under declared policy
|
||||
The system SHALL dispatch custom lifecycle commands only to a Run endpoint that advertises deployment-plan support and the selected execution policy. Run MUST perform local path, executable, timeout, and port preflight before executing a write or process action.
|
||||
|
||||
#### Scenario: Run accepts an argv custom start plan
|
||||
- **WHEN** a compatible Run claims a custom start job using argv execution mode
|
||||
- **THEN** it receives the protected working directory and arguments only through the leased execution input and reports a safe preflight result
|
||||
|
||||
### Requirement: Shell interpretation is explicit
|
||||
The system SHALL require an explicit shell kind for a shell command string and MUST NOT infer shell interpretation from command text. The system MUST reject shell execution when the selected Run policy does not allow that shell kind.
|
||||
|
||||
#### Scenario: Disallowed shell command
|
||||
- **WHEN** an operator selects a shell command mode unsupported by the assigned Run
|
||||
- **THEN** dispatch fails with a safe policy error and does not execute the command
|
||||
|
||||
### Requirement: Run reports redacted phase progress
|
||||
The Run contract SHALL report only a defined deployment phase, percent, and safe message or error code. It MUST NOT return raw host paths, raw command text, raw credentials, or direct socket values.
|
||||
|
||||
#### Scenario: Preflight path failure
|
||||
- **WHEN** a configured working directory is unavailable on Run
|
||||
- **THEN** Run reports a `preflight` failure with a safe reason without echoing the supplied absolute path
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Server definitions can be saved before Run is available
|
||||
The system SHALL allow an authorized server manager to create and edit a draft server definition without a Run endpoint binding. The system MUST NOT dispatch a lifecycle job for an unbound draft.
|
||||
|
||||
#### Scenario: Create an unbound draft
|
||||
- **WHEN** an authorized user saves a server definition without selecting a Run endpoint
|
||||
- **THEN** the system stores it in `draft` state and returns no install job
|
||||
|
||||
#### Scenario: Deploy a draft after Run registration
|
||||
- **WHEN** an authorized user binds a draft to a compatible online Run endpoint and requests deployment
|
||||
- **THEN** the system validates the deployment definition and queues the requested lifecycle job
|
||||
|
||||
### Requirement: Deployment modes support real self-hosted layouts
|
||||
The system SHALL support `guided-install`, `existing-server`, and `custom-command` deployment modes. An operator MAY provide an absolute server root and working directory for all modes and lifecycle command definitions for custom-command mode.
|
||||
|
||||
#### Scenario: Adopt an existing Python virtual-environment server
|
||||
- **WHEN** an operator saves existing-server or custom-command mode with an absolute working directory and a Python virtual-environment startup command
|
||||
- **THEN** the system stores the protected execution input and does not require the server directory to be adjacent to Run
|
||||
|
||||
### Requirement: Protected execution inputs are not exposed by read APIs
|
||||
The system SHALL treat supplied host paths and command text as protected execution inputs. List, detail, job, audit, log, and plugin bridge read responses MUST expose only configured state, deployment mode, and safe fingerprints or summaries.
|
||||
|
||||
#### Scenario: Read a configured custom deployment
|
||||
- **WHEN** an authorized user reads a server deployment definition after saving a path and command
|
||||
- **THEN** the response indicates the protected fields are configured without returning their values
|
||||
|
||||
### Requirement: Deployment requires an execution-capable Run only when dispatching
|
||||
The system SHALL require an online compatible Run endpoint only for preflight, install, start, stop, or status dispatch. The system MUST reject dispatch when the assigned Run does not declare the versioned deployment-plan capability.
|
||||
|
||||
#### Scenario: Attempt deployment with incompatible Run
|
||||
- **WHEN** an operator requests deployment against a Run that lacks deployment-plan support
|
||||
- **THEN** the system returns a safe compatibility reason and does not queue an executable lifecycle job
|
||||
|
||||
### Requirement: Lifecycle status explains waiting and execution phases
|
||||
The system SHALL surface whether a deployment job is queued, claimed, in preflight, installing, configuring, starting, or performing a health check. Safe Run failures MUST remain attached to the job and server state.
|
||||
|
||||
#### Scenario: Run has not claimed deployment
|
||||
- **WHEN** a deployment job remains queued
|
||||
- **THEN** the server UI identifies it as waiting for Run claim rather than reporting installation progress
|
||||
@@ -0,0 +1,29 @@
|
||||
## 1. Platform deployment contracts and persistence
|
||||
|
||||
- [x] 1.1 Add draft server state and protected deployment-definition domain, DTO, repository, and persistence contracts.
|
||||
- [x] 1.2 Add validated create-input schemas, protected path/command updates, and safe deployment read projections.
|
||||
- [x] 1.3 Add draft creation, later Run binding, and deployment dispatch services with versioned execution-plan input.
|
||||
|
||||
## 2. Run-facing lifecycle and diagnostics
|
||||
|
||||
- [x] 2.1 Extend lifecycle jobs with deployment-plan capability checks and redacted phase progress validation/projection.
|
||||
- [x] 2.2 Document the independent Run contract for preflight, custom argv/shell policy, and safe phase reports.
|
||||
- [x] 2.3 Add Platform service/API tests for unbound drafts, protected input redaction, compatibility rejection, and deployment dispatch.
|
||||
|
||||
## 3. Plugin declarations
|
||||
|
||||
- [x] 3.1 Extend plugin create-form declarations with supported field metadata and recommended deployment-template mappings.
|
||||
- [x] 3.2 Update SCUM and Minecraft declarations with usable guided-install fields and defaults; preserve their runtime-binding semantics.
|
||||
- [x] 3.3 Add manifest validation tests for the new create/deployment declaration rules.
|
||||
|
||||
## 4. Management console workflows
|
||||
|
||||
- [x] 4.1 Add API types/client/contracts/schemas for draft creation, deployment-definition updates, Run binding, and deploy dispatch.
|
||||
- [x] 4.2 Replace the create dialog with a staged modal workflow that renders plugin fields and deployment modes, including protected full-path and custom-command inputs.
|
||||
- [x] 4.3 Add server detail deployment editing and stage-aware job status without rendering protected inputs.
|
||||
- [x] 4.4 Add focused frontend tests for field rendering, redaction, drafts, and queued/claimed/preflight status copy.
|
||||
|
||||
## 5. Verification and delivery
|
||||
|
||||
- [x] 5.1 Run focused backend, plugin, and frontend verification plus `scripts/check-structure.sh`.
|
||||
- [x] 5.2 Run `openspec validate support-custom-server-deployment-workflows --strict`, mark verified tasks complete, stage only this task's files, commit, and push the current branch.
|
||||
Reference in New Issue
Block a user