feat: 清理openspec
This commit is contained in:
@@ -43,10 +43,6 @@ Do not place implementation code outside the matching root. Shared contracts mus
|
||||
|
||||
Any task that touches CSS must keep CSS declarations compressed and compact. Do not expand a single selector's style block across many lines when it can be written as a concise one-line rule.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
- Do not use OpenSpec artifacts, commands, or skills for new work. Implement requested changes directly in the appropriate project root and record the relevant verification evidence in the handoff.
|
||||
|
||||
## Task Creation Rules
|
||||
|
||||
When creating a task, include the following prompt boundaries before implementation starts:
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# Design
|
||||
|
||||
## Deployment shape
|
||||
|
||||
The local Docker deployment runs three services:
|
||||
|
||||
- `platform`: Go backend listening on `:8080`, using file-backed storage under `/data/platform`.
|
||||
- `run`: Go worker in `worker` mode, connecting to `http://platform:8080`, using `/data/run/workspace` and `/data/run/spool`.
|
||||
- `platform_web`: static Vite build served by Nginx, proxying `/api/v1` and `/healthz` to `platform:8080`.
|
||||
|
||||
This matches the current architecture without introducing a new database adapter. The platform metadata and segmented log bodies are persisted in a Docker named volume. The worker has its own named volume for local workspace and spool data.
|
||||
|
||||
## Local debugging
|
||||
|
||||
Direct local execution remains environment-variable based:
|
||||
|
||||
- Root `.env.example` documents the common three-process setup.
|
||||
- `platform/.env.example` documents backend storage knobs.
|
||||
- `run/.env.example` documents worker identity, platform URL, workspace, and scheduling knobs.
|
||||
- `platform_web/.env.example` documents Vite browser API and dev proxy knobs.
|
||||
|
||||
Developers can copy the example files to `.env` or source/export the variables before running `go run` / `npm run dev`. The project intentionally keeps Go config loading simple and does not require a checked-in secret-bearing config file.
|
||||
|
||||
## Storage guidance
|
||||
|
||||
The Docker compose default uses the durable file backend because it works without external services:
|
||||
|
||||
- `PLATFORM_METADATA_PATH=/data/platform/metadata.json`
|
||||
- `PLATFORM_LOG_DIR=/data/platform/logs`
|
||||
|
||||
For larger production deployments, MySQL/Postgres should be introduced as a metadata repository adapter in a future OpenSpec change. High-volume log bodies should use a log-optimized backend such as ClickHouse, Loki, OpenSearch/Elasticsearch, or object-storage segments behind `LogBodyStore`; Docker compose does not pretend that MySQL is an adequate row-per-log-line body store.
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Add local Docker deployment
|
||||
|
||||
## Why
|
||||
|
||||
Operators need a repeatable way to run the platform backend, run worker, and platform web console with persistent local data. Local debugging also needs clear environment files so storage paths, run identity, platform API proxying, and browser-facing API URLs are easy to modify without changing code.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add Dockerfiles for `platform/`, `run/`, and `platform_web/`.
|
||||
- Add a root `docker-compose.yml` that starts platform, run worker, and web console with named volumes for platform data and run workspace/spool data.
|
||||
- Add local `.env.example` files documenting the runtime variables for Docker and direct local execution.
|
||||
- Update README files to explain Docker deployment, local direct execution, and which config files to edit.
|
||||
|
||||
## Impact
|
||||
|
||||
- Adds local deployment configuration only; it does not add billing, cloud host sales, external provider workflows, or production log database adapters.
|
||||
- Keeps platform data durable through mounted volumes and the existing file storage backend.
|
||||
- Keeps frontend/browser access platform-mediated through `/api/v1` proxying.
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# local-docker-deployment Specification
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Docker deployment files
|
||||
|
||||
The repository SHALL provide a local Docker deployment that starts the platform backend, run worker, and platform web console.
|
||||
|
||||
#### Scenario: Compose starts local services with persistent directories
|
||||
|
||||
- **GIVEN** an operator runs the local compose file
|
||||
- **WHEN** the services start
|
||||
- **THEN** the platform SHALL use a durable mounted data directory
|
||||
- **AND** the run worker SHALL use a mounted workspace/spool directory
|
||||
- **AND** the web console SHALL proxy platform API calls through platform-owned routes.
|
||||
|
||||
### Requirement: Local debugging configuration examples
|
||||
|
||||
The repository SHALL document direct local execution configuration through example environment files.
|
||||
|
||||
#### Scenario: Developer wants to change ports or storage paths
|
||||
|
||||
- **GIVEN** a developer wants to run the platform, run worker, and web console directly
|
||||
- **WHEN** they inspect the environment examples
|
||||
- **THEN** they SHALL find the platform listen address, storage backend, metadata path, log directory, run platform URL, run workspace/spool roots, and web API/proxy settings.
|
||||
|
||||
### Requirement: Storage guidance remains scoped
|
||||
|
||||
The deployment documentation SHALL distinguish metadata storage from log body storage.
|
||||
|
||||
#### Scenario: Operator asks where large server logs should go
|
||||
|
||||
- **GIVEN** a deployment with hundreds or thousands of servers
|
||||
- **WHEN** the operator reads the deployment guidance
|
||||
- **THEN** it SHALL say relational databases are for metadata and indexes
|
||||
- **AND** it SHALL recommend log-optimized backends for high-volume log bodies in future adapters.
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
## 1. OpenSpec Artifacts
|
||||
|
||||
- [x] 1.1 Create proposal, design, spec, and tasks for local Docker deployment and debugging configuration.
|
||||
- [x] 1.2 Validate the change with `openspec validate add-local-docker-deployment --strict`.
|
||||
|
||||
## 2. Docker Deployment
|
||||
|
||||
- [x] 2.1 Add Dockerfiles for platform, run, and platform_web.
|
||||
- [x] 2.2 Add a root compose file with persistent volumes and safe service wiring.
|
||||
- [x] 2.3 Add Docker ignore rules to keep builds small and avoid copying local data.
|
||||
|
||||
## 3. Local Debug Configuration
|
||||
|
||||
- [x] 3.1 Add example environment files for root orchestration, platform, run, and platform_web.
|
||||
- [x] 3.2 Document which variables to modify for Docker and direct local execution.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Validate compose syntax with `docker compose config`.
|
||||
- [x] 4.2 Run focused backend tests for platform and run config packages.
|
||||
- [x] 4.3 Run `scripts/check-structure.sh`.
|
||||
- [x] 4.4 Run `openspec validate add-local-docker-deployment --strict`.
|
||||
@@ -1,36 +0,0 @@
|
||||
# Design
|
||||
|
||||
## Metadata backend
|
||||
|
||||
`PLATFORM_STORAGE_BACKEND` selects the platform metadata store:
|
||||
|
||||
- `file`: default local durable snapshot at `PLATFORM_METADATA_PATH`.
|
||||
- `memory`: test/disposable storage.
|
||||
- `mysql`: MySQL-backed metadata snapshot using `PLATFORM_MYSQL_DSN`.
|
||||
|
||||
The first MySQL implementation stores one platform-owned JSON snapshot in a `platform_metadata_snapshots` table. This gives operators a real durable MySQL option now while preserving the existing `repo.Store` boundary. Later changes can normalize individual repositories into relational tables without changing handlers or services.
|
||||
|
||||
## Log body backend
|
||||
|
||||
`PLATFORM_LOG_BODY_BACKEND` selects log body storage separately:
|
||||
|
||||
- empty: follows the metadata backend, except `mysql` maps to `file`.
|
||||
- `file`: segmented JSONL log files in `PLATFORM_LOG_DIR`.
|
||||
- `memory`: tests/disposable local runs.
|
||||
|
||||
MySQL metadata storage does not imply MySQL log bodies. Hundreds or thousands of servers should use segmented files for local deployments and log-optimized stores such as ClickHouse, Loki, OpenSearch/Elasticsearch, or object-storage segments in production.
|
||||
|
||||
## Docker guidance
|
||||
|
||||
The root `docker-compose.yml` keeps the default file backend. It includes commented MySQL service/config blocks so operators can uncomment them when they want local MySQL metadata:
|
||||
|
||||
```text
|
||||
PLATFORM_STORAGE_BACKEND=mysql
|
||||
PLATFORM_MYSQL_DSN=platform:platform@tcp(mysql:3306)/platform?parseTime=true
|
||||
PLATFORM_LOG_BODY_BACKEND=file
|
||||
```
|
||||
|
||||
## Failure behavior
|
||||
|
||||
If `PLATFORM_STORAGE_BACKEND=mysql` is set without `PLATFORM_MYSQL_DSN`, platform startup fails with a direct configuration error. If the DSN is present but the database is unreachable, startup fails fast rather than silently falling back to memory.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# Add MySQL platform metadata storage
|
||||
|
||||
## Why
|
||||
|
||||
The platform now has durable file storage, but Docker/local configuration does not expose a real MySQL option. Operators need a clear `PLATFORM_STORAGE_BACKEND=mysql` path with commented configuration examples. They also need the deployment docs to make the log storage boundary explicit: MySQL is for platform metadata, not high-volume row-per-log-line bodies.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add MySQL metadata storage configuration through `PLATFORM_MYSQL_DSN`.
|
||||
- Add a MySQL-backed `repo.Store` implementation that persists platform metadata snapshots in a platform-owned table.
|
||||
- Separate metadata backend selection from log body backend selection with `PLATFORM_LOG_BODY_BACKEND`.
|
||||
- Update Docker compose/env examples with commented MySQL configuration.
|
||||
- Document how to configure MySQL locally and in Docker, and clarify that log bodies remain on `LogBodyStore`.
|
||||
|
||||
## Impact
|
||||
|
||||
- Operators can configure platform metadata persistence with MySQL without changing code.
|
||||
- Existing file-backed storage remains the default.
|
||||
- Logs continue to use file segments by default; production log analytics backends remain a future adapter behind `LogBodyStore`.
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
# mysql-platform-metadata-storage Specification
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: MySQL metadata backend configuration
|
||||
|
||||
The platform SHALL support `PLATFORM_STORAGE_BACKEND=mysql` for metadata persistence.
|
||||
|
||||
#### Scenario: MySQL backend is configured with a DSN
|
||||
|
||||
- **GIVEN** `PLATFORM_STORAGE_BACKEND=mysql`
|
||||
- **AND** `PLATFORM_MYSQL_DSN` points to a reachable database
|
||||
- **WHEN** the platform starts
|
||||
- **THEN** it SHALL initialize a MySQL metadata store
|
||||
- **AND** it SHALL create required metadata storage structures when missing.
|
||||
|
||||
#### Scenario: MySQL backend is missing a DSN
|
||||
|
||||
- **GIVEN** `PLATFORM_STORAGE_BACKEND=mysql`
|
||||
- **AND** `PLATFORM_MYSQL_DSN` is empty
|
||||
- **WHEN** the platform starts
|
||||
- **THEN** startup SHALL fail with a clear configuration error.
|
||||
|
||||
### Requirement: Log body backend remains separate
|
||||
|
||||
The platform SHALL configure log body storage separately from metadata storage.
|
||||
|
||||
#### Scenario: MySQL metadata uses file log bodies by default
|
||||
|
||||
- **GIVEN** `PLATFORM_STORAGE_BACKEND=mysql`
|
||||
- **AND** `PLATFORM_LOG_BODY_BACKEND` is empty
|
||||
- **WHEN** the platform starts
|
||||
- **THEN** log bodies SHALL use the file segmented backend
|
||||
- **AND** log entries SHALL NOT be stored as row-per-line MySQL metadata.
|
||||
|
||||
### Requirement: MySQL configuration is documented
|
||||
|
||||
The repository SHALL include commented MySQL examples in local env and Docker configuration docs.
|
||||
|
||||
#### Scenario: Operator wants to configure MySQL
|
||||
|
||||
- **GIVEN** an operator reads the env examples or README
|
||||
- **WHEN** they search for MySQL configuration
|
||||
- **THEN** they SHALL find `PLATFORM_STORAGE_BACKEND=mysql`, `PLATFORM_MYSQL_DSN`, and `PLATFORM_LOG_BODY_BACKEND=file` examples.
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
## 1. OpenSpec Artifacts
|
||||
|
||||
- [x] 1.1 Create proposal, design, spec, and tasks for MySQL metadata storage configuration.
|
||||
- [x] 1.2 Validate the change with `openspec validate add-mysql-platform-metadata-storage --strict`.
|
||||
|
||||
## 2. MySQL Metadata Storage
|
||||
|
||||
- [x] 2.1 Add platform config fields for `PLATFORM_MYSQL_DSN` and `PLATFORM_LOG_BODY_BACKEND`.
|
||||
- [x] 2.2 Implement a MySQL-backed metadata snapshot store behind `repo.Store`.
|
||||
- [x] 2.3 Wire router startup to support `PLATFORM_STORAGE_BACKEND=mysql`.
|
||||
- [x] 2.4 Add tests for MySQL config loading, missing DSN failure, and log body backend selection.
|
||||
|
||||
## 3. Documentation And Comments
|
||||
|
||||
- [x] 3.1 Add commented MySQL examples to root/platform env examples and Docker compose.
|
||||
- [x] 3.2 Update README docs with exact MySQL DSN examples and log storage guidance.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run `cd platform && go test ./config ./api ./repo -count=1`.
|
||||
- [x] 4.2 Run `docker compose config`.
|
||||
- [x] 4.3 Run `scripts/check-structure.sh`.
|
||||
- [x] 4.4 Run `openspec validate add-mysql-platform-metadata-storage --strict`.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-13
|
||||
@@ -1,65 +0,0 @@
|
||||
## Context
|
||||
|
||||
The platform already has separate run control, job, log, and artifact channels. Plugin manifests currently declare lifecycle, file, log, artifact, and AI capabilities, but they do not describe whether a server may be reached by FTP, rsync, or run, nor do they declare run-only operations such as remote database reads or RCON. The previous SCUM codebase used FTP/SFTP workers for file upload, scum_run for server-side operations, SQLite query forwarding, log transfer, and game-client command handling; this change brings those ideas into the new platform as typed, plugin-declared capabilities.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Model remote access methods and remote run operations in the plugin manifest.
|
||||
- Require installed plugins to declare remote capabilities before platform bridge or direct job dispatch can queue them.
|
||||
- Keep remote file/database/RCON/log operations behind platform and run channels.
|
||||
- Allow both SCUM and Minecraft plugins to declare compatible remote access needs.
|
||||
- Keep job payloads bounded: logical target keys, scoped input/artifact refs, and safe result refs only.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No raw FTP, rsync, database, or RCON credentials in plugin manifests or plugin pages.
|
||||
- No browser-to-run, plugin-to-run, or plugin-to-database direct connection.
|
||||
- No production FTP/rsync client, MySQL client, SQLite parser, or RCON protocol implementation in this change.
|
||||
- No cloud host provider workflow or server rental/billing feature.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Manifest declares methods and capabilities separately
|
||||
|
||||
`remoteAccess.methods` describes how a server may be reached (`ftp`, `rsync`, `run`). `remoteAccess.runCapabilities` lists the exact run operations the plugin can use. This keeps transport choice visible while still preserving the existing run capability matching model.
|
||||
|
||||
Alternative considered: encode everything as free-form tags. Rejected because marketplace and authorization need deterministic validation and filtering.
|
||||
|
||||
### Decision 2: Remote access uses a dedicated bridge action
|
||||
|
||||
Plugin pages use `remote.access.request` for database, RCON, log transfer, and remote file jobs. Existing `files.request` remains for generic scoped file operations; lifecycle `jobs.dispatch` remains for start/stop. The new action lets platform apply a distinct `server.remote.access` permission and capability declaration check.
|
||||
|
||||
Alternative considered: overload `jobs.dispatch` for every remote operation. Rejected because RCON/database/log transfer should not be authorized only by `server.lifecycle`.
|
||||
|
||||
### Decision 3: Direct server-bound jobs are plugin-gated
|
||||
|
||||
When a job includes a `serverInstanceId`, platform validates the instance plugin declares the requested capability. This prevents callers from bypassing plugin bridge and enabling remote DB/RCON/log transfer jobs on plugins that did not opt in.
|
||||
|
||||
Alternative considered: enforce declaration only in plugin bridge. Rejected because platform API callers can create jobs directly in tests and future admin flows.
|
||||
|
||||
### Decision 4: Run remote executor is bounded metadata first
|
||||
|
||||
Run reports remote capabilities and accepts remote jobs, but returns safe metadata/result refs rather than opening real network connections in this change. Real FTP/rsync/database/RCON adapters can later attach behind the same job envelopes without changing plugin manifests.
|
||||
|
||||
Alternative considered: implement protocol clients now. Rejected because credential storage, network policy, and result artifact formats need a separate change and should not be rushed into manifest plumbing.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Operators may expect real FTP/rsync/DB/RCON execution immediately. Mitigation: docs and result messages state this is the declared, bounded job contract; adapter implementation remains a follow-up.
|
||||
- [Risk] Capability names may grow numerous. Mitigation: keep them grouped under `remote.*` and validate them centrally.
|
||||
- [Risk] Existing tests using generic jobs may fail once server-bound jobs are plugin-gated. Mitigation: lifecycle/file capabilities remain declared in existing test plugin fixtures.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add OpenSpec, schema, domain, DTO, validator, and service support for remote access declarations.
|
||||
2. Update SCUM and add Minecraft example manifests with declared remote access.
|
||||
3. Extend run protocol and runtime to validate/report remote capabilities and complete bounded remote jobs.
|
||||
4. Add tests for manifest validation, platform authorization, direct job gating, and run remote job handling.
|
||||
5. Run manifest validation, platform/run tests, structure check, and strict OpenSpec validation.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which follow-up change should own real FTP/rsync credential storage and connection testing?
|
||||
- Should RCON results become log entries, artifacts, or both when full adapters land?
|
||||
@@ -1,29 +0,0 @@
|
||||
## Why
|
||||
|
||||
The platform needs one safe model for remote game server access across hosted files, run-managed hosts, databases, logs, and RCON. The old SCUM stack handled FTP/SFTP, run-side process control, SQLite queries, logs, and client commands in separate paths; the new platform must make those abilities plugin-declared before they can be used.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add plugin manifest metadata for declared remote access methods: `ftp`, `rsync`, and `run`.
|
||||
- Add remote run capabilities for remote file read/write, process start/stop, MySQL and SQLite query, log transfer, and RCON command dispatch.
|
||||
- Add platform registry and marketplace projection fields so operators can see which remote access methods a game plugin enables.
|
||||
- Add a platform-mediated bridge action for remote access requests that queues only capabilities declared by the installed plugin.
|
||||
- Extend run capability reporting and bounded remote job handling so MC and SCUM plugins can opt into the same contract.
|
||||
- Add first-party Minecraft and SCUM example manifests proving the shared declaration model.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `plugin-declared-remote-access`: Plugin-declared remote server access through ftp, rsync, or run with scoped run jobs for remote files, lifecycle, database reads, log transfer, and RCON.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `plugins/` manifest schema, manifest validator tests, and first-party example manifests.
|
||||
- Affects `platform/` domain, DTO, validators, service bridge dispatch, marketplace projections, docs, and tests.
|
||||
- Affects `run/` protocol capability constants, job validation, runtime capability reporting, worker execution, docs, and tests.
|
||||
- Does not add billing, cloud host sales, plugin-owned credentials, browser-to-run access, raw host paths, or raw database/RCON credentials in plugin pages.
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Plugin manifests declare remote access methods
|
||||
Game management plugin manifests SHALL declare remote access methods before platform exposes FTP, rsync, or run-mediated remote server operations for server instances created from that plugin.
|
||||
|
||||
#### Scenario: Manifest declares supported methods
|
||||
- **WHEN** a plugin manifest lists `ftp`, `rsync`, or `run` under remote access methods
|
||||
- **THEN** platform registry and marketplace responses MUST preserve those methods without exposing host paths, remote credentials, direct sockets, or provider secrets
|
||||
|
||||
#### Scenario: Unsafe remote access declaration is rejected
|
||||
- **WHEN** a plugin manifest includes raw credentials, host paths, direct run socket details, or unknown remote access methods
|
||||
- **THEN** plugin workspace validation and platform registration MUST reject the manifest before it becomes installable
|
||||
|
||||
### Requirement: Remote run operations are capability gated
|
||||
Remote run operations SHALL be represented as explicit run capabilities and SHALL require both the run endpoint and the installed game plugin to declare the requested capability.
|
||||
|
||||
#### Scenario: Declared remote run job is queued
|
||||
- **WHEN** a plugin declares a remote run capability and the selected run endpoint reports the same capability
|
||||
- **THEN** platform MAY queue a bounded job for that server instance using logical target keys and scoped input or artifact refs
|
||||
|
||||
#### Scenario: Undeclared remote run job is denied
|
||||
- **WHEN** a caller requests remote database, RCON, log transfer, or remote file work for a server instance whose plugin did not declare the requested capability
|
||||
- **THEN** platform MUST reject or deny the request before creating a job
|
||||
|
||||
### Requirement: Remote access bridge is platform mediated
|
||||
Plugin pages SHALL request remote access through a platform-mediated bridge action and MUST NOT connect directly to FTP, rsync, run, MySQL, SQLite, log storage, or RCON endpoints.
|
||||
|
||||
#### Scenario: Bridge queues declared remote access
|
||||
- **WHEN** a plugin page has `server.remote.access` permission and requests `remote.access.request` for a declared capability
|
||||
- **THEN** platform MUST authorize the action and queue the corresponding bounded run job
|
||||
|
||||
#### Scenario: Bridge denies undeclared remote access
|
||||
- **WHEN** a plugin page requests `remote.access.request` for a capability not declared by the plugin
|
||||
- **THEN** platform MUST return a safe denial and MUST NOT expose run credentials, host paths, database DSNs, RCON passwords, or remote storage endpoints
|
||||
|
||||
### Requirement: Run handles bounded remote jobs
|
||||
Run SHALL report supported remote capabilities and complete remote job assignments with bounded progress and safe result references while keeping control, job, logs, and artifact channels separate.
|
||||
|
||||
#### Scenario: Run accepts remote database and RCON assignments
|
||||
- **WHEN** run receives declared remote MySQL, SQLite, RCON, log transfer, or remote file assignments
|
||||
- **THEN** run MUST validate bounded job metadata and return terminal results without embedding raw credentials, host paths, query result bodies, log bodies, or RCON output in the job result payload
|
||||
|
||||
#### Scenario: Run rejects unsafe remote job payload
|
||||
- **WHEN** a remote job assignment includes an absolute path, parent traversal, raw secret, direct socket, or oversized inline content
|
||||
- **THEN** run MUST reject the assignment with a bounded failure result
|
||||
|
||||
### Requirement: MC and SCUM plugins share the remote access model
|
||||
First-party Minecraft and SCUM plugin manifests SHALL validate against the same remote access schema and declare only the capabilities each game needs.
|
||||
|
||||
#### Scenario: Minecraft plugin validates
|
||||
- **WHEN** the Minecraft example plugin declares run-managed files, logs, and RCON access
|
||||
- **THEN** plugin workspace manifest validation MUST pass
|
||||
|
||||
#### Scenario: SCUM plugin validates
|
||||
- **WHEN** the SCUM example plugin declares FTP/rsync/run file access, run lifecycle, SQLite/MySQL database read compatibility, log transfer, and RCON access
|
||||
- **THEN** plugin workspace manifest validation MUST pass
|
||||
@@ -1,40 +0,0 @@
|
||||
## 1. OpenSpec Contracts
|
||||
|
||||
- [x] 1.1 Create proposal, design, and spec for plugin-declared remote access.
|
||||
- [x] 1.2 Validate the new change artifacts with `openspec validate --strict`.
|
||||
|
||||
## 2. Plugin Manifest Contracts
|
||||
|
||||
- [x] 2.1 Extend the game plugin manifest schema with `remoteAccess` methods, run capabilities, database engines, RCON, and log transfer declarations.
|
||||
- [x] 2.2 Update manifest validation tests and examples so SCUM and Minecraft validate with remote access declarations.
|
||||
|
||||
## 3. Platform Registry and Authorization
|
||||
|
||||
- [x] 3.1 Add domain and DTO remote access metadata to game plugin, manifest, and marketplace projections.
|
||||
- [x] 3.2 Extend platform validators for remote methods, remote run capabilities, `server.remote.access`, and `remote.access.request`.
|
||||
- [x] 3.3 Gate server-bound jobs against the server instance plugin's declared capabilities.
|
||||
- [x] 3.4 Add bridge execution for declared remote access requests and tests for denied undeclared capabilities.
|
||||
|
||||
## 4. Run Protocol and Worker
|
||||
|
||||
- [x] 4.1 Add remote run capability constants and validation rules for bounded remote assignments.
|
||||
- [x] 4.2 Report remote capabilities from run smoke and worker mode.
|
||||
- [x] 4.3 Add bounded remote job execution results that keep heavy payloads in artifact/log channels.
|
||||
- [x] 4.4 Add run tests for remote DB/RCON/log/file capabilities and unsafe payload rejection.
|
||||
|
||||
## 5. Documentation and Verification
|
||||
|
||||
- [x] 5.1 Update platform, run, and plugin docs for remote access capability declarations.
|
||||
- [x] 5.2 Run plugin manifest validation, platform tests, run tests, and `scripts/check-structure.sh`.
|
||||
- [x] 5.3 Record verification evidence in `tasks.md`.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `openspec validate add-plugin-declared-remote-access --strict` - passed; PostHog telemetry flush logged DNS warnings only after validation succeeded.
|
||||
- `go test ./...` in `platform/` - passed.
|
||||
- `go test ./...` in `run/` - passed.
|
||||
- `npm test` in `plugins/` - passed: 14 manifest/SDK tests.
|
||||
- `npm run typecheck` in `plugins/` - passed.
|
||||
- `TMPDIR=/private/tmp npm run validate:manifest` in `plugins/` - passed for dev, SCUM, and Minecraft manifests.
|
||||
- `scripts/check-structure.sh` - passed.
|
||||
- `git diff --check` - passed.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-13
|
||||
@@ -1,107 +0,0 @@
|
||||
## Context
|
||||
|
||||
The platform already has control, job, log, and artifact channels, plus plugin-declared remote access capabilities for FTP, rsync, run-mediated files, SQL, logs, and RCON. The missing layer is operational delivery: operators need to generate a per-server run executable, download it for a selected OS/architecture, authenticate it with the server's current database-backed run key, update it after it is online, and let plugins declare how run finds and controls the actual game server.
|
||||
|
||||
The old SCUM stack has useful patterns: a run-side process controller, a separate client/robot manager for cases where server control requires a game client or custom automation, Git-based source updates, Go toolchain checks, FTP log polling, SQLite reads, and command forwarding. This design generalizes those patterns without making SCUM special in platform core.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Let server owners generate and download a server-scoped run package from the server list or server action menu.
|
||||
- Store one current run key and one current client-manager key per server/component in the database, encrypted at rest, with redacted secret references in APIs and logs.
|
||||
- Let online run endpoints self-update through a platform job that stages, verifies, swaps, and reports rollback-safe status.
|
||||
- Let plugins declare runtime profiles that explain how to find a server, start/stop it, check dependencies, install missing dependencies, collect live and historical logs, and expose files, FTP/rsync, SQL, and RCON.
|
||||
- Let plugins declare optional client-manager build profiles for cases like SCUM where a separate executable must be compiled from an open repository with a distinct authentication key.
|
||||
- Keep all browser and plugin operations platform-mediated and preserve channel isolation for control, jobs, logs, files, and artifacts.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No billing, cloud host sales, server rental marketplace, or cloud-provider provisioning workflow.
|
||||
- No raw run keys, client-manager keys, FTP passwords, database DSNs, RCON passwords, direct sockets, or host paths in plugin pages or platform_web responses.
|
||||
- No arbitrary plugin shell scripts for dependency installation or build execution.
|
||||
- No requirement that every game use run; FTP-only, FTP+RCON, and custom-client modes remain valid when declared by the plugin.
|
||||
- No production package-signing infrastructure beyond local checksums/signature hooks in the first implementation.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Distribution artifacts are secret-bearing platform records
|
||||
|
||||
Platform stores generated run and client-manager packages as artifacts with a distribution record containing kind, server instance, plugin ID, target OS/architecture, source revision, checksum, status, component kind, and key generation. The package config contains the current active key for that server/component because the remote executable must authenticate with it. API responses, logs, job payloads, plugin SDK payloads, and UI state expose only artifact IDs, key generation, and redacted secret refs.
|
||||
|
||||
Alternative considered: ship one global run binary and ask users to hand-edit config files. Rejected because it causes copy/paste key exposure, weak auditability, and poor operator experience.
|
||||
|
||||
Distribution generation is asynchronous. Platform creates a bounded `distribution.build` job on the assigned run endpoint and returns a `building` distribution with the real job ID. The run worker obtains the secret-bearing build input only through its authenticated leased-job channel, builds in an isolated workspace, and uploads the resulting archive through the artifact channel. Platform marks a distribution `available` only after the job succeeds and the referenced artifact is present and available. A JSON build plan, generated config, or synthetic build log is never a downloadable distribution artifact.
|
||||
|
||||
Run packages are built from the trusted run worker checkout. Plugin-declared client managers are checked out from the approved HTTPS Git repository and revision carried by the build job. Build execution uses a fixed build-system adapter and target tuple; repository content cannot supply arbitrary platform-side commands.
|
||||
|
||||
### Decision 2: Run and client-manager credentials are separate singleton keys
|
||||
|
||||
Each server/component has exactly one active run key and, when needed, exactly one active client-manager key. Run and client-manager keys remain different secrets, but platform does not keep multiple simultaneously valid keys for the same component. Resetting a key replaces the encrypted database value, increments the key generation, invalidates every older run or client package for that component, and requires regenerating and redeploying the affected package.
|
||||
|
||||
Alternative considered: reuse the run key for plugin client managers. Rejected because client managers may have broader game-specific control surfaces and need independent reset, revocation, and audit.
|
||||
|
||||
Alternative considered: issue temporary enrollment tokens and exchange them for runtime keys. Rejected because the desired operator model is a single database-backed current key per server/component, with explicit reset when trust must be revoked.
|
||||
|
||||
### Decision 3: Plugins declare runtime profiles, not raw local paths
|
||||
|
||||
Plugins define runtime profiles with logical server discovery probes, lifecycle actions, dependency probes, dependency install plans, log sources, transport profiles, and optional client-manager profiles. Operators bind those logical keys to a server instance at setup time. Run resolves bindings locally and returns logical status, not raw host paths.
|
||||
|
||||
Alternative considered: hardcode Minecraft and SCUM discovery rules into platform. Rejected because the platform should remain a game server management core, while game-specific control knowledge belongs in plugins.
|
||||
|
||||
### Decision 4: Dependency install is typed and reviewable
|
||||
|
||||
Dependency checks are read-only probes such as command version, service existence, port availability, file presence under scoped roots, Steam app presence, Java version, Docker availability, or Windows package presence. Install plans are typed steps with approved package managers or verified downloads. Platform shows the plan and queues it only after operator approval.
|
||||
|
||||
Alternative considered: let plugins provide arbitrary install shell scripts. Rejected because it creates an unrestricted execution path and conflicts with run security rules.
|
||||
|
||||
### Decision 5: Client-manager builds are source-pinned build jobs
|
||||
|
||||
Plugin client-manager profiles declare a repository URL, branch/tag or pinned revision policy, supported targets, build system, config template keys, dependency hints, and produced artifact paths. Platform creates a build job in an isolated workspace or future build worker, redacts secrets from logs, writes generated config from secret refs, and publishes a downloadable artifact.
|
||||
|
||||
Alternative considered: require plugin authors to upload prebuilt binaries only. Rejected because SCUM-style managers need reproducible platform-side injection of per-server config and keys.
|
||||
|
||||
### Decision 6: Run owns local execution and transport adapters
|
||||
|
||||
Run is the multi-platform server launcher and transport agent. It starts/stops third-party programs through plugin lifecycle profiles, tails stdout/stderr and declared log files, transfers files through the artifact channel, and performs declared FTP/rsync, SQL, and RCON operations through scoped adapters. Long transfers must not block heartbeat, job ack/result, or log ingest.
|
||||
|
||||
Alternative considered: let platform_web or plugin pages connect directly to FTP/RCON/SQL. Rejected because that exposes credentials and bypasses platform authorization, audit, and channel isolation.
|
||||
|
||||
### Decision 7: Live and historical logs share durable sequence semantics
|
||||
|
||||
Run streams live process output and file tails through the log channel with source IDs and monotonically increasing sequences. Historical logs are fetched through backfill jobs that use checkpoints, file fingerprints, FTP polling cursors, or database cursors to avoid duplicates. Platform_web displays live tail and history through platform APIs only.
|
||||
|
||||
Alternative considered: return log bodies inside job results. Rejected because logs can be large and must not compete with control and job metadata.
|
||||
|
||||
### Decision 8: Self-update is staged and rollback-safe
|
||||
|
||||
When run is online and supports the update capability, platform queues an update job with an artifact ref and checksum. Run downloads via the artifact channel, verifies checksum/signature metadata, stages the new binary, drains or rejects new local work, swaps atomically where supported, restarts, and reports success or rollback failure. Offline endpoints keep the latest downloadable package for manual replacement.
|
||||
|
||||
Alternative considered: send a raw command to pull the latest repository. Rejected because it is platform-specific, hard to verify, and unsafe to audit.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Build jobs can execute untrusted repository code. Mitigation: require plugin-declared build profiles, pinned refs, isolated workspaces, bounded logs, and a later sandboxed build worker before public plugin builds.
|
||||
- [Risk] Self-update can leave a remote run offline. Mitigation: stage artifacts, verify checksums, retain previous binary, report last-known version, and keep manual download available.
|
||||
- [Risk] Dependency install plans differ across Windows, Linux, and macOS. Mitigation: model probes and install steps per target platform, and show unsupported targets before dispatch.
|
||||
- [Risk] Historical log backfill can duplicate records. Mitigation: persist per-source checkpoints with file fingerprints, offsets, sequence acknowledgements, and cursor metadata.
|
||||
- [Risk] Resetting a key immediately breaks deployed run or client-manager binaries. Mitigation: make reset confirmations explicit, mark old packages revoked, show that regeneration is required, and keep online update/manual download paths visible.
|
||||
- [Risk] Operators may expect plugin profiles to work without binding server-specific values. Mitigation: require server setup validation before showing actions that depend on missing bindings.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Extend plugin manifest schema and examples with runtime profiles, dependency probes, log sources, transport profiles, and client-manager build profiles.
|
||||
2. Add platform domain, model, DTO, validator, and service support for distribution records, encrypted database key storage, key reset, key generation checks, build jobs, dependency status, runtime bindings, and update jobs.
|
||||
3. Add run package config loading, registration authentication against the current database key generation, dependency probes, discovery probes, log source checkpoints, transport adapter envelopes, and self-update executor.
|
||||
4. Add platform_web server-list and server-detail action menus for generate/download/update run, generate/download client manager, dependency checks, live logs, and historical logs.
|
||||
5. Add tests and docs across plugins, platform, run, and platform_web; validate with OpenSpec, structure checks, backend tests, plugin validation, run tests, frontend tests, and browser walkthroughs for touched UI.
|
||||
|
||||
Rollback removes the new distribution/client-manager routes and UI actions, leaves existing run endpoints and plugin-declared remote access behavior intact, and preserves already-created artifacts as inert downloadable records until manually cleaned.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which envelope-key source should protect the encrypted key columns stored in the platform database?
|
||||
- Should platform-side builds run in the platform process for the first version, or require a separate build worker from day one?
|
||||
- What default retention should apply to historical logs and generated binaries?
|
||||
- Which target packaging formats should be first-class first: zip/tar.gz only, or Windows service installer, systemd unit bundle, and launchd plist bundles?
|
||||
- Should plugin client-manager profiles support private repositories later, and if so how should source credentials be stored and audited?
|
||||
@@ -1,30 +0,0 @@
|
||||
## Why
|
||||
|
||||
Run is becoming the platform's cross-platform server launcher and transport agent, but operators still need a safe way to generate, download, authenticate, update, and observe per-server run binaries. Some games also need plugin-declared companion clients, such as SCUM-style client managers, that are built from plugin-provided source repositories with separate credentials and lifecycle from run.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a platform-managed run distribution workflow from the server list or server actions menu: generate executor, choose target OS/architecture, write the current server/component authentication key into the generated package config, download the artifact, and store the single active encrypted key in the database.
|
||||
- Add run self-update orchestration: if an assigned run is already online, platform can enqueue an update command that instructs the remote run to pull or replace itself with the latest approved run build.
|
||||
- Add plugin-declared external controller/client-manager build profiles for games that cannot be controlled only through run, FTP, SQL, logs, and RCON.
|
||||
- Add separate database-backed active keys for run and plugin-declared client managers; resetting a server's run or client key invalidates every previous package and requires regenerating the corresponding run or client artifact.
|
||||
- Extend plugin manifests with server discovery, dependency checks, dependency install guidance, log source declarations, historical log retention hints, and transport wiring so run knows how to find and manage the target server without hardcoded game logic.
|
||||
- Add UI/API contracts for server action menu entries: generate run, download latest run package, push run update, generate plugin client manager, inspect dependency status, open live logs, and browse historical logs.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `run-distribution-and-client-managers`: Platform-managed run packaging, download, key provisioning, remote self-update, plugin-declared companion client builds, dependency checks, server discovery, and live/historical observability.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `plugins/` manifest schema, SDK docs, SCUM and Minecraft example manifests, and validation tests.
|
||||
- Affects `platform/` domain, DTOs, encrypted secret references, build records, artifact records, run endpoint provisioning, job creation, audit events, and API routes.
|
||||
- Affects `run/` generated package config, updater job handling, dependency probes, server discovery adapters, live log tailing, historical log checkpoints, file/FTP/SQL/RCON transport adapters, and docs.
|
||||
- Affects `platform_web/` server list and server detail actions, live log views, historical log views, dependency status surfaces, and browser walkthrough coverage.
|
||||
- Does not add billing, host rental, cloud host sales, raw credential exposure, plugin-owned direct sockets, or unrelated SaaS marketplace workflows.
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Platform generates server-scoped run packages
|
||||
The platform SHALL let an authorized operator generate a run package for a selected server instance and target platform using the server's single current run key stored encrypted in the platform database.
|
||||
|
||||
#### Scenario: Operator generates run from server actions
|
||||
- **WHEN** an authorized operator selects generate executor for a server instance and chooses a supported OS/architecture
|
||||
- **THEN** platform MUST create or reuse the server's current encrypted run key, queue a real run-worker build job, return a building distribution with its job ID, compile the target executable, package it with the generated config, publish the completed binary archive and checksum through the artifact channel, record an audit event, and MUST NOT return the raw key in the API response
|
||||
|
||||
#### Scenario: Run generation has not completed
|
||||
- **WHEN** the run-worker build job is queued, running, failed, or cancelled
|
||||
- **THEN** platform MUST keep the distribution unavailable for download, expose the real job state and progress, and MUST NOT substitute generated configuration JSON or a synthetic build log as the downloadable run package
|
||||
|
||||
#### Scenario: Operator downloads generated run package
|
||||
- **WHEN** an authorized operator downloads a generated run artifact
|
||||
- **THEN** platform MUST authorize access by server scope and return the secret-bearing package through artifact/download APIs without exposing raw host paths, direct sockets, or database credentials in package metadata
|
||||
|
||||
### Requirement: Run and client-manager keys are isolated singletons
|
||||
Run executors and plugin-declared client managers SHALL use different authentication secrets, and each server/component SHALL have exactly one current active key stored encrypted in the platform database.
|
||||
|
||||
#### Scenario: Client manager is generated after run
|
||||
- **WHEN** a plugin-declared client-manager package is generated for a server that already has a run package
|
||||
- **THEN** platform MUST create or reuse the server's current encrypted client-manager key and MUST NOT reuse, reveal through API metadata, or derive it from the run key
|
||||
|
||||
#### Scenario: Component key reset is requested
|
||||
- **WHEN** an operator resets a server's run key or client-manager key
|
||||
- **THEN** platform MUST replace the encrypted database key for that component, increment the key generation, revoke all packages generated with prior generations, and record an audit event identifying the component kind without logging raw key material
|
||||
|
||||
#### Scenario: Old package authenticates after reset
|
||||
- **WHEN** a run or client-manager package generated before the latest key reset attempts to authenticate
|
||||
- **THEN** platform MUST reject the old key and require the operator to regenerate and redeploy the corresponding run or client-manager package
|
||||
|
||||
### Requirement: Plugins declare runtime profiles
|
||||
Game plugins SHALL declare runtime profiles that describe how run or external transports can discover, control, observe, and connect to the game server using logical keys instead of raw credentials or host paths.
|
||||
|
||||
#### Scenario: Plugin declares server discovery and transports
|
||||
- **WHEN** a plugin manifest declares runtime profiles with discovery probes, lifecycle actions, dependency probes, log sources, FTP/rsync, SQL, RCON, or client-manager bindings
|
||||
- **THEN** plugin validation MUST accept only known profile fields and platform MUST preserve the declarations for server setup and action gating
|
||||
|
||||
#### Scenario: Plugin manifest includes unsafe runtime details
|
||||
- **WHEN** a plugin manifest embeds raw run keys, client-manager keys, FTP passwords, database DSNs, RCON passwords, absolute host paths, direct sockets, or arbitrary shell scripts in runtime profiles
|
||||
- **THEN** plugin validation and platform registration MUST reject the manifest before it becomes installable
|
||||
|
||||
### Requirement: Server runtime bindings resolve plugin profiles
|
||||
Server instances SHALL bind plugin-declared logical runtime keys to operator-provided local or remote settings before run-dependent actions are enabled.
|
||||
|
||||
#### Scenario: Run discovers an existing server
|
||||
- **WHEN** run registers for a server instance with complete runtime bindings and the plugin declares discovery probes
|
||||
- **THEN** run MUST evaluate the probes locally, report logical discovery status, version, and health, and MUST NOT return raw host paths or secret values to platform_web or plugin pages
|
||||
|
||||
#### Scenario: Required binding is missing
|
||||
- **WHEN** an operator opens server actions for a runtime profile that requires unbound install root, service name, FTP profile, SQL profile, RCON profile, or client-manager profile
|
||||
- **THEN** platform MUST mark dependent actions unavailable and explain the missing logical binding without exposing internal storage details
|
||||
|
||||
### Requirement: Plugins control third-party startup behavior
|
||||
Third-party game program startup and shutdown SHALL be driven by plugin-declared lifecycle profiles and server runtime bindings, not hardcoded platform game logic.
|
||||
|
||||
#### Scenario: Local process server starts through run
|
||||
- **WHEN** a plugin declares a local process lifecycle profile and the server runtime binding is complete
|
||||
- **THEN** run MUST start or stop the third-party program through the declared bounded action template and stream stdout/stderr through the log channel
|
||||
|
||||
#### Scenario: Hosted server has no local lifecycle control
|
||||
- **WHEN** a plugin declares an FTP-only, FTP+RCON, or custom-client runtime profile without local process lifecycle
|
||||
- **THEN** platform MUST hide or deny local start/stop actions and expose only the declared remote or client-manager actions
|
||||
|
||||
### Requirement: Dependency checks and installs are typed
|
||||
Run SHALL check dependencies through plugin-declared probes and SHALL install missing dependencies only through approved, typed, reviewable install plans.
|
||||
|
||||
#### Scenario: Dependency check reports missing runtime
|
||||
- **WHEN** run evaluates plugin-declared dependency probes and a required runtime, service, package, toolchain, Steam app, Java runtime, Docker runtime, or OS package is missing
|
||||
- **THEN** platform MUST show dependency status and a reviewable install plan if the plugin declares one for the target platform
|
||||
|
||||
#### Scenario: Dependency install is approved
|
||||
- **WHEN** an authorized operator approves a dependency install plan
|
||||
- **THEN** platform MUST queue a bounded run job using typed package/download steps, checksum or source metadata where provided, and must reject arbitrary shell snippets
|
||||
|
||||
### Requirement: Client-manager packages are plugin-declared builds
|
||||
The platform SHALL support plugin-declared client-manager build profiles for companion executables that require source checkout, configuration injection, and compilation before download.
|
||||
|
||||
#### Scenario: SCUM-style client manager is generated
|
||||
- **WHEN** a plugin declares a client-manager build profile with repository, revision policy, supported target platform, build system, config template, and output artifact paths
|
||||
- **THEN** platform MUST create a run-worker build job that checks out the approved source and revision, injects configuration obtained through the authenticated job-input channel, compiles the target executable, uploads the downloadable artifact through the artifact channel, and redacts secrets and workspace paths from progress and build results
|
||||
|
||||
#### Scenario: Client-manager build is still running
|
||||
- **WHEN** the source checkout, environment check, dependency download, compile, or artifact upload stage is incomplete
|
||||
- **THEN** platform_web MUST display the corresponding real job progress and MUST NOT mark later stages complete on a local timer
|
||||
|
||||
#### Scenario: Unsupported client-manager target is requested
|
||||
- **WHEN** an operator requests a client-manager build for an OS/architecture not declared by the plugin profile
|
||||
- **THEN** platform MUST reject the request before cloning source or creating a credential
|
||||
|
||||
### Requirement: Online run endpoints self-update through platform jobs
|
||||
The platform SHALL update online run endpoints by queuing a bounded self-update job that references an approved artifact and checksum instead of sending raw shell commands.
|
||||
|
||||
#### Scenario: Online run accepts update
|
||||
- **WHEN** an assigned run endpoint is online and supports self-update
|
||||
- **THEN** platform MUST queue an update job, and run MUST download the artifact, verify checksum or signature metadata, stage the replacement, report progress, and restart or swap only after verification succeeds
|
||||
|
||||
#### Scenario: Update verification fails
|
||||
- **WHEN** run cannot verify or stage the update artifact
|
||||
- **THEN** run MUST keep the current executable, report a bounded failure result, and preserve heartbeat or last-known status without leaking local paths or credentials
|
||||
|
||||
### Requirement: Run exposes multi-channel transport capabilities
|
||||
Run SHALL provide declared server operations through separate control, job, log, artifact/file, FTP/rsync, SQL, and RCON channels or adapters while preserving priority and bounded payload rules.
|
||||
|
||||
#### Scenario: Long file transfer is active
|
||||
- **WHEN** run is transferring a large file, FTP payload, rsync payload, or artifact chunk
|
||||
- **THEN** heartbeat, job ack/result, cancellation polling, and log ingest MUST continue independently without waiting for transfer completion
|
||||
|
||||
#### Scenario: Undeclared transport operation is requested
|
||||
- **WHEN** a plugin page or platform caller requests FTP, SQL, RCON, file, or process work not declared by the plugin runtime profile and run capabilities
|
||||
- **THEN** platform MUST deny the request before creating a job and MUST return only a safe error
|
||||
|
||||
### Requirement: Live and historical logs are platform-mediated
|
||||
Platform_web SHALL show live and historical server logs through platform APIs backed by run log ingest, log checkpoints, and plugin-declared log sources.
|
||||
|
||||
#### Scenario: Live log tail is opened
|
||||
- **WHEN** an operator opens live logs for a server with an online run endpoint
|
||||
- **THEN** platform_web MUST read from platform log APIs and display sequenced log entries from run without direct run sockets or raw file paths
|
||||
|
||||
#### Scenario: Historical log backfill is requested
|
||||
- **WHEN** an operator requests older logs for a declared process, file, FTP, SQL, or plugin-specific log source
|
||||
- **THEN** platform MUST queue or serve a backfill using per-source checkpoints, cursors, or file fingerprints and MUST avoid embedding large log bodies in job result payloads
|
||||
|
||||
### Requirement: Server action menu reflects declared availability
|
||||
The server list and server detail action menu SHALL show generate run, download run, push run update, generate client manager, dependency check, install dependency, live logs, and historical logs only when the current user and plugin/runtime state permit them.
|
||||
|
||||
#### Scenario: Actions are available
|
||||
- **WHEN** a server has a plugin with runtime profiles, complete bindings, and the current user has the required permissions
|
||||
- **THEN** platform_web MUST render the applicable actions using the existing game-operations console style and call platform APIs rather than plugin-owned direct endpoints
|
||||
|
||||
#### Scenario: Actions are unavailable
|
||||
- **WHEN** a server lacks a required plugin declaration, binding, online run status, build profile, or user permission
|
||||
- **THEN** platform_web MUST hide or disable the action with a safe reason and MUST NOT render raw credentials, host paths, direct sockets, or secret refs beyond redacted identifiers
|
||||
|
||||
### Requirement: Distribution and control events are audited
|
||||
The platform SHALL audit run generation, run download, credential reset, run update, dependency install, client-manager build, client-manager download, and transport operation requests.
|
||||
|
||||
#### Scenario: Sensitive operation completes
|
||||
- **WHEN** a sensitive distribution or control operation succeeds, fails, or is denied
|
||||
- **THEN** platform MUST record actor, server instance, plugin ID, component kind, operation, result, artifact ID or job ID where applicable, and redacted reason without raw secret material
|
||||
@@ -1,92 +0,0 @@
|
||||
## 1. Plugin Contracts
|
||||
|
||||
- [x] 1.1 Extend the game plugin manifest schema with runtime profiles for server discovery, lifecycle profiles, dependency probes, install plans, log sources, transport profiles, and client-manager build profiles.
|
||||
- [x] 1.2 Update plugin SDK types and bridge docs for runtime bindings, run distribution actions, dependency actions, live/historical log actions, and client-manager generation.
|
||||
- [x] 1.3 Update SCUM and Minecraft example manifests to declare realistic runtime profiles, dependency probes, log sources, and transport bindings.
|
||||
- [x] 1.4 Add plugin validation tests that accept safe runtime/client-manager profiles and reject raw keys, database DSNs, RCON passwords, direct sockets, raw host paths, and arbitrary shell snippets.
|
||||
|
||||
## 2. Platform Secret and Distribution Model
|
||||
|
||||
- [x] 2.1 Add platform domain, DTO, model, repository, and validator types for run distributions, client-manager distributions, runtime bindings, encrypted database keys, key generations, dependency status, build jobs, and update jobs.
|
||||
- [x] 2.2 Implement encrypted-at-rest database key storage for exactly one active run key and one active client-manager key per server/component.
|
||||
- [x] 2.3 Add key reset services and tests proving reset replaces the active encrypted key, increments generation, revokes old packages, and requires regenerating the affected run or client-manager artifact.
|
||||
- [x] 2.4 Add services and tests for generating server-scoped run packages, creating artifact records, writing the current run key into package config, storing key generation metadata, and authorizing downloads.
|
||||
- [x] 2.5 Add services and tests for client-manager build records, distinct current client-manager keys, source revision metadata, target-platform validation, and downloadable artifact publication.
|
||||
- [x] 2.6 Add audit events for generation, download, key reset, update, dependency install, build, and denied sensitive operations.
|
||||
|
||||
## 3. Platform APIs and Job Orchestration
|
||||
|
||||
- [x] 3.1 Add API routes and handlers for server action availability, generate/download run, reset run key, push run update, generate/download client manager, reset client-manager key, check dependencies, install dependencies, live logs, and historical logs.
|
||||
- [x] 3.2 Gate all routes by user permissions, server ownership, plugin declarations, runtime bindings, and run endpoint capability availability.
|
||||
- [x] 3.3 Add self-update job creation with artifact refs, checksums, idempotency keys, and denied-path tests for offline or unsupported run endpoints.
|
||||
- [x] 3.4 Add dependency-check and dependency-install job creation with typed install plans and rejection of arbitrary shell commands.
|
||||
- [x] 3.5 Add historical log backfill job creation with source IDs, checkpoints, bounded results, and artifact/log channel separation.
|
||||
|
||||
## 4. Run Bootstrap and Runtime Behavior
|
||||
|
||||
- [x] 4.1 Implement generated package config loading, current key generation authentication, server-scoped identity, old-package rejection after reset, and redacted local diagnostics.
|
||||
- [x] 4.2 Implement runtime profile resolution for local process, hosted FTP/RCON, FTP-only, SQL, file, and custom-client modes using server bindings.
|
||||
- [x] 4.3 Implement dependency probes and typed install plan execution for supported OS targets with safe progress and failure results.
|
||||
- [x] 4.4 Implement self-update executor with artifact download, checksum/signature verification hooks, staging, rollback, restart/swap behavior, and tests.
|
||||
- [x] 4.5 Implement live log tailing from process stdout/stderr and declared file sources with durable sequence checkpoints.
|
||||
- [x] 4.6 Implement historical log backfill cursors for declared file, FTP, SQL, and plugin-specific log sources without embedding large log bodies in job results.
|
||||
- [x] 4.7 Implement bounded adapter envelopes for FTP/rsync, SQL read, RCON command, and file transfer so long transfers do not block heartbeat or job metadata.
|
||||
|
||||
## 5. Build Pipeline
|
||||
|
||||
- [x] 5.1 Implement platform-side or build-worker source checkout for plugin-declared client-manager repositories with pinned revision metadata.
|
||||
- [x] 5.2 Implement target-platform validation, build dependency checks, redacted config injection, bounded build logs, checksum calculation, and artifact publication.
|
||||
- [x] 5.3 Add SCUM-style client-manager build tests covering supported targets, unsupported target denial, separate credential injection, and redacted logs.
|
||||
|
||||
## 6. platform_web Workflows
|
||||
|
||||
- [x] 6.1 Add server list and server detail action menu entries for generate run, download run, push run update, generate client manager, dependency check/install, live logs, and historical logs.
|
||||
- [x] 6.2 Add API client types, schemas, and tests for run distribution, client-manager distribution, dependency status, update jobs, and historical log backfill.
|
||||
- [x] 6.3 Add UI states for unavailable actions with safe reasons, redacted secret refs, run online/offline status, build status, update progress, dependency status, and log backfill status.
|
||||
- [x] 6.4 Preserve the existing platform_web game-operations console style and verify no raw keys, host paths, sockets, DSNs, RCON passwords, or direct run endpoints render in the UI.
|
||||
|
||||
## 7. Documentation and Verification
|
||||
|
||||
- [x] 7.1 Update platform, run, plugin, and platform_web docs for run generation, client-manager builds, runtime bindings, dependency profiles, live logs, historical logs, and self-update behavior.
|
||||
- [x] 7.2 Run plugin manifest validation, plugin SDK tests, platform tests, run tests, frontend tests, and `scripts/check-structure.sh`.
|
||||
- [x] 7.3 Run `openspec validate add-run-distribution-and-client-managers --strict`.
|
||||
- [x] 7.4 Complete a browser walkthrough for touched server-list and server-detail workflows before marking UI acceptance complete.
|
||||
- [x] 7.5 Record verification evidence in this task file before completion.
|
||||
|
||||
## 8. Real Distribution Build Repair
|
||||
|
||||
- [x] 8.1 Replace synchronous synthetic run/client artifacts with queued `distribution.build` jobs, building distribution records, authenticated build-input retrieval, and terminal job projection.
|
||||
- [x] 8.2 Implement the independent run worker build adapter for trusted run source and approved HTTPS client-manager repositories, including fixed Go builds, isolated workspaces, config packaging, checksums, and chunked artifact upload.
|
||||
- [x] 8.3 Drive the platform_web generation dialog from real job progress and terminal state instead of timer-completed stages.
|
||||
- [x] 8.4 Add regression coverage proving generation queues a backend job, does not publish JSON plans as artifacts, publishes only uploaded build output, and reports actual progress/failure.
|
||||
- [x] 8.5 Run focused platform, run, frontend, OpenSpec, and structure verification and record the evidence below.
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- `cd plugins && npm run validate:manifest`: passed. First sandbox attempt failed with `listen EPERM` on the local `tsx` IPC pipe, then the same command passed with approved escalation.
|
||||
- `cd plugins && npm run typecheck`: passed.
|
||||
- `cd plugins && npm test`: passed, 1 file / 17 tests.
|
||||
- `cd run && go test ./...`: passed.
|
||||
- `cd platform && go test ./...`: passed.
|
||||
- `cd platform_web && npm run typecheck`: passed.
|
||||
- `cd platform_web && npm test`: passed, 13 files / 60 tests.
|
||||
- `cd platform_web && npm run build`: passed, Vite production build completed.
|
||||
- `scripts/check-structure.sh`: passed.
|
||||
- `openspec validate add-run-distribution-and-client-managers --strict`: passed. The CLI printed a PostHog network flush warning after validation, but exited successfully with `Change 'add-run-distribution-and-client-managers' is valid`.
|
||||
- `LOCAL_DEBUG_PLATFORM_PORT=18189 LOCAL_DEBUG_WEB_PORT=5183 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-acceptance scripts/browser-acceptance.sh`: passed.
|
||||
- Browser evidence file: `/private/tmp/browser-local-debug-acceptance/browser-acceptance/browser-acceptance-evidence.json`.
|
||||
- Browser walkthrough evidence covered 首页、服务器管理、服务器管理 / 运行操作菜单、插件市场、用户管理、AI 提供商管理、服务器详情、服务器详情 / 插件控制, plus desktop/mobile checks for black mecha and magical-girl themes.
|
||||
|
||||
### Real Distribution Build Repair Evidence (2026-07-17)
|
||||
|
||||
- `cd platform && go test ./service ./validator ./api`: passed.
|
||||
- `cd run && go test ./runtime ./protocol ./api`: passed; the runtime suite compiled a real run executable from an isolated source copy and uploaded the archive through chunked artifact calls.
|
||||
- `cd platform_web && npm test -- --run components/RuntimeTaskProgress.test.ts pages/ConsolePages.test.tsx`: passed, 2 files / 13 tests.
|
||||
- `cd platform && go test ./...`: passed across all platform packages.
|
||||
- `cd run && go test ./...`: passed across all independent run packages.
|
||||
- `cd platform_web && npm test`: passed, 15 files / 76 tests.
|
||||
- `cd platform_web && npm run typecheck`: passed.
|
||||
- `cd platform_web && npm run build`: passed, Vite production build completed.
|
||||
- `openspec validate add-run-distribution-and-client-managers --strict`: passed.
|
||||
- `scripts/check-structure.sh`: passed.
|
||||
- Regression evidence covers queued `distribution.build` creation with no synthetic artifact, authenticated leased build-input retrieval, rejection of premature success before artifact upload, successful retry after real artifact publication, retained downloadable chunk payloads, isolated trusted run source copies, rejection of credential-bearing/unpinned client repositories, and frontend projection of real running/succeeded/failed job states.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-28
|
||||
@@ -1,48 +0,0 @@
|
||||
## Context
|
||||
|
||||
The SCUM plugin already declares runtime config mappings and log sources, while Platform exposes safe configuration read/diff/approval APIs and a scoped file-operation dispatcher. Its current plugin page is an operations overview with semantic logs; this does not match the operator's configuration-first workflow.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Make plugin-owned logical file declarations the single catalog for SCUM configuration and log file scopes.
|
||||
- Model safe configuration fields separately from the raw INI content, then compose changes into the existing Platform diff-preview and approval flow.
|
||||
- Present declared log files and their Platform log-stream contents in the same workbench.
|
||||
- Redirect historical SCUM page keys to the default `files-config` page without breaking shared plugin routing.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Arbitrary filesystem browsing, path entry, terminals, FTP/rsync controls, raw secrets, or host/socket exposure.
|
||||
- Raw text as the default configuration editor, direct write access for unknown fields, or a new run-side protocol.
|
||||
- Changing global server-list behavior or non-SCUM plugin pages.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. Add `fileWorkspace` to the plugin manifest/runtime projection. It contains safe logical directories/files and modeled fields, rather than host paths or unbounded schemas. This makes a page contract auditable and keeps ownership with the plugin.
|
||||
2. Give every modeled field an owning logical file key, Chinese operational metadata, and constrained control details. The frontend uses only these fields to compose proposed INI content; unmapped lines remain visible as read-only field records.
|
||||
3. Reuse declared file read/write dispatch for logical file keys. A completed `files.read` job may be projected through a Platform-owned declared-file snapshot endpoint, which accepts only a declared logical file key, returns no host path or job payload, and redacts secret-like assignment values before returning content. Modeled edits and optional raw config edits require a visible diff preview before the Platform queues a declared `files.write` job.
|
||||
4. Move SCUM from `operations` to `files-config`; the route resolver redirects old `overview`, `config`, `logs`, and `operations` keys only for `game.scum`. Other plugins keep their declared page keys unchanged.
|
||||
5. Build page content from existing shared console form/list/diff classes. No page-owned surface system or global decoration is added.
|
||||
6. Treat the SCUM workbench as one selected logical file at a time. The left pane contains only declared directories and files. The right pane presents either modeled fields or an optional raw mode for an editable configuration file, and a read-only log view for a log file. Selection changes must not trigger unbounded polling or path-based requests.
|
||||
7. Render the plugin bundle in embedded mode when it is mounted under a server-detail section. The generic plugin page frame and host-context diagnostics remain available for direct plugin routes, but must not be nested inside the file-management tab.
|
||||
8. Keep Companion player, reward, state, vehicle, and trajectory controls out of this page. Those remain available through their separately scoped plugin-control experiences and must not obscure the file workflow.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [A config document may contain extra keys] → preserve them in the proposed content and show them as read-only, unmodeled rows.
|
||||
- [Existing installations still link old route keys] → normalize those keys in the common resolver before page lookup.
|
||||
- [A declared log stream is absent] → show an explicit unavailable state and never fall back to a filesystem path.
|
||||
- [INI parsing has formatting limits] → patch only declared simple key/value fields and rely on Platform preview before approval.
|
||||
- [A raw file has not completed an authorized read] → show an explicit pending or empty state rather than an invented template or stale file content.
|
||||
- [A declared file contains a secret-like assignment] → redact its value in the snapshot while retaining the surrounding file structure for operational review.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Ship manifest and Platform declaration validation/projection with the SCUM `files-config` page.
|
||||
2. Deploy the frontend route normalization and workbench; old SCUM links resolve to `files-config`.
|
||||
3. Rollback by restoring the previous manifest page declaration; no persisted migration or write protocol needs reversal.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None. The first field catalog uses existing SCUM deployment mappings and can be expanded through manifest declarations later.
|
||||
@@ -1,27 +0,0 @@
|
||||
## Why
|
||||
|
||||
SCUM operators currently reach separate overview, configuration, and semantic-log surfaces, even though their routine operational work begins with declared files and safe, modeled settings. The default SCUM work surface needs to make configuration actionable without revealing host paths or turning raw text editing into the normal workflow.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Replace the SCUM overview-first experience with a unified `文件与配置` workbench whose default scope is the plugin-declared configuration directory.
|
||||
- Add plugin-declared logical file directories/files and a modeled configuration-field catalog, including Chinese labels, help, control metadata, constraints, defaults, restart impact, and owning file.
|
||||
- Reuse Platform-mediated file requests and the existing configuration diff-preview/approval/write flow so modeled changes are previewed before dispatch; expose completed declared-file reads through a bounded, redacted Platform snapshot rather than through host paths or general job payloads.
|
||||
- Expose logs as declared log files inside the same workbench, with separate safe log-file scope; retain unknown configuration fields as read-only information.
|
||||
- Replace the static, stacked SCUM panels with a single selection-based file workbench: directory/file navigation on one side and the selected file's modeled configuration, optional raw config mode, or read-only log content on the other.
|
||||
- Embed the workbench inside the server detail section without a second plugin-page header or unrelated Companion feature panels.
|
||||
- Safely migrate legacy SCUM overview/config/log routes to the new workbench.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `scum-file-config-workbench`: Declared SCUM file scopes, modeled configuration editing, log-file viewing, and safe route migration.
|
||||
|
||||
### Modified Capabilities
|
||||
- `config-write-and-file-dispatch`: File dispatch and config approval now consume declared logical directories/files and field ownership metadata.
|
||||
- `scum-operations`: SCUM's primary operator surface changes from an overview to the file-and-configuration workbench.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects the SCUM plugin manifest/declarations, Platform plugin validation and safe file/config DTO handling, and SCUM frontend contracts/routes/components.
|
||||
- Reuses `files.request`, existing server configuration diff/approval/write APIs, and the SCUM runtime profile; adds a Platform-owned read-result projection without expanding filesystem or remote-access authority.
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Declared field ownership constrains config editing
|
||||
Platform-projected plugin declarations SHALL associate each modeled configuration field with a declared logical file key so the frontend can invoke existing diff and approval APIs without accepting arbitrary file targets.
|
||||
|
||||
#### Scenario: Preview uses an owning declared config file
|
||||
- **WHEN** a modeled field change is previewed
|
||||
- **THEN** the frontend MUST use the field's declared logical file key and MUST NOT accept a host path or user-supplied target key
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: SCUM declares safe file workspace catalog
|
||||
The SCUM plugin SHALL declare logical configuration and log directories/files and a bounded modeled configuration-field catalog without raw host paths, secrets, credentials, sockets, or arbitrary schemas.
|
||||
|
||||
#### Scenario: Default configuration scope is declared
|
||||
- **WHEN** an authorized operator opens the SCUM file-and-configuration page
|
||||
- **THEN** the page MUST select the plugin-declared configuration directory and list only its declared logical files
|
||||
|
||||
#### Scenario: Unsafe declaration is rejected
|
||||
- **WHEN** a plugin manifest includes an absolute path, traversal key, secret-like value, or unsupported field control
|
||||
- **THEN** Platform MUST reject the manifest before it is registered
|
||||
|
||||
### Requirement: Modeled SCUM fields are configuration-first
|
||||
The SCUM workbench SHALL render modeled fields with Chinese label, explanation, input type, constraint, default, restart impact, and owning file, and SHALL keep unmodeled fields read-only.
|
||||
|
||||
#### Scenario: Operator changes a modeled field
|
||||
- **WHEN** an operator changes a declared editable field
|
||||
- **THEN** the workbench MUST compose only that field into the owning configuration file and require a diff preview before approval
|
||||
|
||||
#### Scenario: Unknown configuration is encountered
|
||||
- **WHEN** the loaded configuration includes a key outside the declared field catalog
|
||||
- **THEN** the workbench MUST show it as read-only and MUST NOT present it as a safe editable control
|
||||
|
||||
### Requirement: Logs are file scope in the same workbench
|
||||
The SCUM workbench SHALL present plugin-declared log files as a log-file scope and display their Platform-mediated stream content.
|
||||
|
||||
#### Scenario: Operator opens a declared log file
|
||||
- **WHEN** an operator selects a declared SCUM log file
|
||||
- **THEN** the page MUST query only its declared Platform log stream and show readable file content without host-path disclosure
|
||||
|
||||
### Requirement: Raw file content is a bounded declared-file snapshot
|
||||
Platform SHALL expose raw configuration or log text only from the latest completed `files.read` result for the same server and a plugin-declared logical file key.
|
||||
|
||||
#### Scenario: Declared file result is ready
|
||||
- **WHEN** an authorized operator requests the raw view of a declared file after its read job completes
|
||||
- **THEN** Platform MUST return only that file's bounded content, logical key, version, checksum, and read state
|
||||
- **AND THEN** the response MUST NOT contain a host path, a generic job execution payload, or another file's content
|
||||
|
||||
#### Scenario: Declared file is not read yet
|
||||
- **WHEN** no successful declared-file read is available for the selected file
|
||||
- **THEN** Platform MUST return an explicit pending or not-read state without inventing file contents
|
||||
|
||||
#### Scenario: Raw file contains a secret-like assignment
|
||||
- **WHEN** a completed declared-file result includes a secret-like `key=value` assignment
|
||||
- **THEN** Platform MUST redact the assignment value before returning the raw snapshot
|
||||
|
||||
### Requirement: SCUM workbench has one active file surface
|
||||
The SCUM workbench SHALL keep declared directory/file navigation separate from the selected file content, rather than stacking every declared file and every unrelated SCUM feature on one page.
|
||||
|
||||
#### Scenario: Operator selects a declared configuration file
|
||||
- **WHEN** an operator selects `ServerSettings.ini` or another declared configuration file
|
||||
- **THEN** the workbench MUST show only that file's metadata and supported modes in the content pane
|
||||
- **AND THEN** modeled fields MUST be limited to fields owned by that selected file
|
||||
|
||||
#### Scenario: Operator switches a selected configuration file to raw mode
|
||||
- **WHEN** an operator activates the raw configuration mode for a selected declared configuration file
|
||||
- **THEN** the workbench MUST show only the most recent Platform-mediated file result or an explicit not-yet-read state
|
||||
- **AND THEN** an editable declared configuration file MAY expose a raw editor only after a completed read snapshot is available
|
||||
- **AND THEN** raw-mode changes MUST require a visible diff preview before dispatching a declared logical `files.write` request
|
||||
- **AND THEN** it MUST NOT expose a host path, arbitrary file selector, or unrestricted text editor
|
||||
|
||||
#### Scenario: Operator selects a declared log file
|
||||
- **WHEN** an operator selects a declared log file
|
||||
- **THEN** the workbench MUST replace the configuration controls with that log file's declared read surface
|
||||
- **AND THEN** the log raw view MUST stay read-only and support switching between UTF-8 and UTF-16 LE display
|
||||
|
||||
### Requirement: Embedded SCUM file management avoids duplicate page chrome
|
||||
When the SCUM workbench is rendered inside a server detail section, the frontend SHALL render it without a second plugin page frame, host-context panel, or unrelated Companion feature panels.
|
||||
|
||||
#### Scenario: Server detail opens SCUM file management
|
||||
- **WHEN** an operator opens the SCUM `文件管理` section in server detail
|
||||
- **THEN** the first workbench surface MUST be the declared directory/file navigation and selected file content
|
||||
- **AND THEN** the page MUST NOT render a nested `PLUGIN PAGE` title or `平台托管上下文` panel
|
||||
|
||||
### Requirement: Legacy SCUM pages migrate safely
|
||||
The frontend SHALL migrate legacy SCUM overview, config, logs, and operations page keys to the `files-config` page while leaving non-SCUM routing unchanged.
|
||||
|
||||
#### Scenario: Legacy SCUM operations link is opened
|
||||
- **WHEN** a user opens a SCUM plugin URL with the legacy `operations` key
|
||||
- **THEN** the frontend MUST resolve it to the declared `files-config` workbench for the same server context
|
||||
@@ -1,8 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: SCUM primary surface is file and configuration workbench
|
||||
The SCUM plugin SHALL expose `files-config` as its primary operator page rather than an overview-first or semantic-log-dashboard page.
|
||||
|
||||
#### Scenario: SCUM plugin page opens
|
||||
- **WHEN** a user opens the declared primary SCUM page for a server instance
|
||||
- **THEN** the page MUST prioritize declared configuration files and modeled configuration controls before log-file browsing
|
||||
@@ -1,18 +0,0 @@
|
||||
## 1. Plugin and Platform declaration contract
|
||||
|
||||
- [x] 1.1 Add safe logical file-directory/file and modeled-field contracts to plugin manifests, Platform domain/DTO projections, copying, and validation.
|
||||
- [x] 1.2 Declare SCUM configuration/log files and bounded Chinese configuration field metadata, then remove legacy SCUM overview page declarations.
|
||||
- [x] 1.3 Add focused Platform validation/projection tests for safe declaration and field ownership behavior.
|
||||
- [x] 1.4 Add a bounded redacted Platform projection for completed declared-file read results.
|
||||
|
||||
## 2. SCUM file and configuration workbench
|
||||
|
||||
- [x] 2.1 Add frontend declaration contracts and resolver for the SCUM `files-config` default workbench and legacy route migration.
|
||||
- [x] 2.2 Build the shared-theme selection-based file list, selected-file modeled configuration form, raw config mode, unknown-field list, preview diff, and declared write dispatch experience.
|
||||
- [x] 2.3 Add declared log-file scope and Platform log stream content reading without path exposure.
|
||||
- [x] 2.4 Render the SCUM workbench embedded in server detail and keep unrelated Companion feature panels out of the file-management tab.
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Add/update focused backend, plugin, route, contract, and component tests for selection state, raw mode, and embedded rendering.
|
||||
- [x] 3.2 Run strict OpenSpec validation, relevant backend/plugin/frontend checks, browser verification, and scripts/check-structure.sh.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-28
|
||||
@@ -1,57 +0,0 @@
|
||||
## Context
|
||||
|
||||
Platform already receives sequenced, durable runtime log batches and has a `game.scum` manifest that declares `scum.login` and `scum.logout` schemas. Those entries are queryable as logs but are not durable player-domain records. The new projection must remain local to a server instance, be safe to invoke as part of log ingestion, and not make raw network data browser-visible or persistent.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Persist independent game-player records keyed by server instance and SCUM player ID, with aliases, bounded sessions, access attempts, and review-only security signals.
|
||||
- Project success login/logout semantics atomically and idempotently from accepted log entries, with sequence/event keys for duplicates and timestamp ordering for stale updates.
|
||||
- Derive server-isolated correlation identifiers using an HMAC secret and a normalized source value, while retaining only the derived value.
|
||||
- Offer permission-scoped, server-authorized management APIs and console records that never return IP values, raw source identifiers, secrets, raw log lines, or automatic enforcement controls.
|
||||
- Retain access attempts and signals for a configurable bounded period and preserve player identity/session summaries after evidence expiry.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Platform-user accounts, credentials, game database reads/writes, skill/attribute editing, gifts, map trails, or any automatic ban/kick/punishment.
|
||||
- Changes to Run channels, direct host/socket/database access, or browser access to raw semantic log bodies.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Use server-local game identity.** `game_player` is unique on `(server_instance_id, game_player_id)`; it has no foreign key to `user`. This prevents platform-console authentication from being mistaken for SCUM identity. An alias table records renamed display names with first/last-seen times.
|
||||
|
||||
Alternative considered: use display name as the identifier. It cannot safely handle player renames or duplicate names.
|
||||
|
||||
2. **Project only accepted SCUM semantic events in the ingestion transaction.** The log sequence (`log_stream_id`, `seq`) is the projection idempotency key. Login/open-session changes only apply when their event time is not older than the player's latest projected event; a logout closes the latest matching open session no later than its event time. Duplicate batches perform no second projection.
|
||||
|
||||
Alternative considered: asynchronous parsing of raw log lines. It would duplicate declared parsing rules, complicate order guarantees, and retain unnecessary sensitive content.
|
||||
|
||||
3. **Store only an HMAC-derived, server-scoped network correlation key.** A server-specific HMAC domain separator plus a process secret produces the correlation key. The source is never saved in models, logs, DTOs, or signal evidence. A digest is useful only within the same server and cannot be compared across servers.
|
||||
|
||||
Alternative considered: hash the raw IP directly. Unsalted hashes are reversible for common address spaces and correlatable across servers.
|
||||
|
||||
4. **Treat failures and anomalies as review evidence.** Failed login/connection event payloads create bounded `game_access_attempt` records. A threshold (five failures for the same fingerprint within fifteen minutes) creates or refreshes an `excessive-failed-access` signal; multiple player IDs sharing one server-local fingerprint create a `possible-alt-account` signal. Signals include text status and evidence counts, and have no action API.
|
||||
|
||||
Alternative considered: automatic moderation. It is excluded because heuristic evidence requires an operator review.
|
||||
|
||||
5. **Use existing session authorization and console primitives.** New endpoints use existing server read authorization. The frontend fetches named API contracts and renders an ordinary full-width shared table/record list with explicit status labels, never raw logs or a new page-local visual system.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [A plugin payload omits a usable player ID] → Ignore the event for projection and retain normal log ingestion; validate only bounded known fields.
|
||||
- [Late logout arrives after another login] → Close only a compatible open session whose start is no later than logout; never regress `lastSeenAt`.
|
||||
- [Projection failure follows log body append] → Return the ingest error and retry the acknowledged range safely; event identity prevents duplicate records.
|
||||
- [HMAC secret rotates] → Derived keys intentionally cease correlating across rotations; raw data is never recoverable. Deployment config keeps the secret stable during its intended retention window.
|
||||
- [Evidence tables grow] → Perform retention pruning during projection/query and cap query limits.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add model-first tables and repositories; existing installations begin with no projected players.
|
||||
2. Deploy manifest schemas and Platform projection; only newly ingested declared events create records. Historical log backfill remains an explicit later operation.
|
||||
3. Deploy APIs and console page after backend authorization is available.
|
||||
4. Rollback by disabling the page and projection. Existing records contain no raw network data and can expire through normal retention cleanup.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None. Initial thresholds and retention are conservative constants covered by tests and can become declared policy in a later change.
|
||||
@@ -1,23 +0,0 @@
|
||||
## Why
|
||||
|
||||
SCUM login semantics are currently retained only as operational logs, so operators cannot safely review a local player's identity history, sessions, or suspicious access behavior. A server-scoped game-player projection turns declared SCUM login/logout events into reviewable evidence without conflating game identities with platform users or exposing network data.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a server-scoped local game-player domain with aliases, sessions, access attempts, and review-only security signals.
|
||||
- Project declared `scum.login` and `scum.logout` semantic log events idempotently, including duplicate, renamed-player, out-of-order, and session-boundary handling.
|
||||
- Derive a server-isolated irreversible network correlation fingerprint; do not persist raw IP addresses or raw fingerprints.
|
||||
- Add authenticated player-profile, aliases, access-trajectory, and security-signal APIs plus SCUM console contracts and records.
|
||||
- Define bounded retention and manual-review semantics for access evidence and risk signals.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `scum-game-player-intelligence`: Server-local SCUM player identities, event projection, privacy-preserving access evidence, and review-only risk signals.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects Platform domain/model/repository/service/API/validation layers and durable metadata storage.
|
||||
- Affects the SCUM plugin semantic-event schemas and page declaration, plus Platform Web API contracts, routing, and shared-console records.
|
||||
- Adds no Platform account authentication, direct game-database access, raw network data, automatic moderation, Run protocol, or host/executor data exposure.
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Server-local game-player identity
|
||||
The system SHALL maintain a game-player identity independently of platform users, uniquely scoped by `serverInstanceId` and immutable game-player ID, with bounded display-name alias history.
|
||||
|
||||
#### Scenario: A known game player logs in under a new name
|
||||
- **WHEN** a successful declared SCUM login contains an existing player ID and a different valid display name
|
||||
- **THEN** the system SHALL update the player's current display name and retain the previous and new names as server-local aliases
|
||||
|
||||
### Requirement: Idempotent semantic login/logout projection
|
||||
The system SHALL project accepted `scum.login` and `scum.logout` semantic events using a durable event identity and SHALL tolerate duplicate and out-of-order delivery without creating duplicate access evidence or regressing player state.
|
||||
|
||||
#### Scenario: A duplicate login event is received
|
||||
- **WHEN** the same accepted log stream sequence is ingested again
|
||||
- **THEN** the system SHALL return the normal duplicate acknowledgement and SHALL not create an additional session or alias record
|
||||
|
||||
#### Scenario: A stale logout arrives after a later login
|
||||
- **WHEN** a logout event is older than the player's latest successful login
|
||||
- **THEN** the system SHALL only close an eligible earlier open session and SHALL not overwrite the newer player last-seen state
|
||||
|
||||
### Requirement: Privacy-preserving access evidence
|
||||
The system SHALL persist no raw IP address, raw network fingerprint, host path, credential, or raw sensitive log content in game-player access records or browser-visible responses. Network correlation SHALL be derived as an irreversible value scoped to one server instance.
|
||||
|
||||
#### Scenario: An access event carries a source address
|
||||
- **WHEN** a SCUM event contains a source address or network identifier
|
||||
- **THEN** the system SHALL use it only to derive a server-isolated correlation value and SHALL omit the source value from stored models and API responses
|
||||
|
||||
### Requirement: Review-only risk signals
|
||||
The system SHALL create bounded security signals for thresholded failed access and possible shared-fingerprint identities, and SHALL expose them as manual-review evidence only.
|
||||
|
||||
#### Scenario: Repeated failed access crosses the threshold
|
||||
- **WHEN** five failed attempts with one server-local correlation value occur within fifteen minutes
|
||||
- **THEN** the system SHALL create or refresh an excessive-failed-access signal with an explicit textual review status and evidence count
|
||||
|
||||
#### Scenario: An operator reviews a signal
|
||||
- **WHEN** an authorized operator reads a player security signal
|
||||
- **THEN** the response SHALL contain no automated enforcement command, raw network identifier, or raw log line
|
||||
|
||||
### Requirement: Authorized player intelligence console
|
||||
The system SHALL provide server-authorized player profile, aliases, sessions, access-attempt, and security-signal responses through named contracts, and the SCUM console SHALL render labels and status text rather than relying only on color.
|
||||
|
||||
#### Scenario: An unauthorized user requests server player data
|
||||
- **WHEN** a platform session lacks read access to the requested server instance
|
||||
- **THEN** the player intelligence API SHALL deny access without revealing whether a game-player record exists
|
||||
|
||||
### Requirement: Bounded evidence retention
|
||||
The system SHALL retain access attempts and active security evidence for a bounded period, prune expired evidence during normal service operations, and keep independent player identity history intact.
|
||||
|
||||
#### Scenario: Evidence is older than the retention limit
|
||||
- **WHEN** a query or projection runs after an access attempt exceeds the retention period
|
||||
- **THEN** the system SHALL remove the expired attempt and any expired non-active signal evidence without deleting the game-player identity
|
||||
@@ -1,21 +0,0 @@
|
||||
## 1. Domain and persistence
|
||||
|
||||
- [x] 1.1 Add server-local game-player, alias, session, access-attempt, and security-signal domain/models, repositories, MySQL migration, memory/file stores, validation, and retention helpers.
|
||||
- [x] 1.2 Add idempotent SCUM login/logout and failed-access projection from accepted semantic log entries, including rename, duplicate, stale event, session boundary, isolated HMAC correlation, and review-only signal thresholds.
|
||||
- [x] 1.3 Add focused domain/service/repository tests for privacy, ordering, idempotency, access control, retention, aliases, sessions, and risk signals.
|
||||
|
||||
## 2. APIs and plugin contract
|
||||
|
||||
- [x] 2.1 Add named request/response DTOs, authorized handlers/routes, safe projections, and API tests for player profiles, lists, aliases, sessions, attempts, and signals.
|
||||
- [x] 2.2 Extend the SCUM manifest semantic schemas/page contract for bounded player intelligence and add plugin validation fixtures/tests.
|
||||
|
||||
## 3. SCUM console
|
||||
|
||||
- [x] 3.1 Add Platform Web API/client contracts and route resolution for the SCUM player intelligence work surface.
|
||||
- [x] 3.2 Render full-width shared-console player records, access trajectories, and manual-review signals with explicit text status and no raw network/log exposure.
|
||||
- [x] 3.3 Add frontend contract/component tests for safe rendering and status readability.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run strict OpenSpec validation and focused backend, plugin, and frontend test suites.
|
||||
- [x] 4.2 Run `scripts/check-structure.sh`, stage only task files, commit on `main`, and push the configured remote.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-28
|
||||
@@ -1,3 +0,0 @@
|
||||
# add-scum-map-trajectories
|
||||
|
||||
SCUM player and vehicle map trajectory projection
|
||||
@@ -1,45 +0,0 @@
|
||||
## Context
|
||||
|
||||
The existing SCUM player intelligence projection owns server-local identities and sessions, while the game-client bridge owns declared Companion snapshots and commands. Neither layer presents movement. The map must remain an explainable, bounded operational view and may not turn the browser into a route to raw logs, Run, game databases, or Companion sockets.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Collect only declared semantic position/vehicle transition events from a platform-managed Companion or accepted log projection.
|
||||
- Convert plugin-declared world coordinates into safe normalized map coordinates and retain only a sampled, bounded trail per server/entity.
|
||||
- Return a fixed bounded window with player/vehicle filters, vehicle-riding segments, data source, collection time, map version, and precision.
|
||||
- Enforce existing server authorization before resolving map status or trajectory data; preserve server isolation.
|
||||
- Render readable point and line trails with explicit empty and missing-map states and detail navigation contracts.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- OCR, screenshot parsing, mouse/keyboard injection, desktop automation, direct game-window access, direct sockets, direct database access, raw coordinate/database querying, indefinite retention, real-time all-server heatmaps, or raw log/browser delivery.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **A small typed event catalog is the only collector contract.** The SCUM manifest declares four semantic events: `player.position`, `vehicle.position`, `player.vehicle.enter`, and `player.vehicle.leave`. Every event includes a bounded entity ID, occurred time, collection time, source (`companion` or `log-projection`), and a plugin map ID/version. Position events carry only finite world X/Y values. They enter through the existing durable log/Companion snapshot channel, never browser-to-game traffic.
|
||||
|
||||
2. **Plugin map declaration defines the safe projection.** `mapTrajectories` in the manifest declares map ID/version, world bounds, image dimensions, axis orientation, sampling distance/time, and retention seconds. Platform validates it once, converts world coordinates to normalized 0–1000 map units, rounds to declared precision, and rejects mismatched map metadata or points outside declared bounds. The frontend receives no host path, original world coordinate, Companion endpoint, or raw record body.
|
||||
|
||||
3. **Project by server/entity/time with event identity and compression.** `GameMapTrackPoint` is unique by accepted event ID and is scoped by server plus entity kind/ID. Projection sorts logically by event time; duplicates are ignored, late points remain ordered in query results, and a point is retained only when it advances the declared sampling interval or distance (transitions are always retained). The repository filters time on server/entity indexes and prunes expired points and ride segments during projection and query.
|
||||
|
||||
4. **Derive riding intervals from enter/leave events.** A player enter opens one vehicle segment; entering a different vehicle closes the prior segment at the new event time. A leave closes only the matching active vehicle. Out-of-order and duplicate transitions cannot produce overlapping active segments. The map response projects these segments as player-associated vehicle trail intervals, not inferred ownership.
|
||||
|
||||
5. **Use a bounded read model instead of arbitrary map queries.** The API accepts a maximum 24-hour time window and at most 20 known player IDs plus 20 known vehicle IDs. It authorizes server access before lookup, verifies player IDs belong to that server, limits output points per entity, and returns map metadata plus empty/missing-map statuses. Vehicle IDs are only accepted if observed in the same server's declared vehicle snapshots or trajectory records.
|
||||
|
||||
6. **Keep detail linking as explicit identifiers.** Player trail summaries provide the existing `gamePlayerRecordId`; vehicles provide their safe vehicle ID and link intent. The frontend may navigate to the existing player selection/detail endpoint or invoke the pre-existing vehicle lookup context. It does not receive a route to Run, a raw query template, or vehicle storage details.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Companion cannot provide typed position events] → the map shows a clear collection-unavailable/empty state; no substitute screen or input automation is attempted.
|
||||
- [Map version changes] → points are queried only for the declared map version; mismatched events are rejected and the response explains the missing compatible map.
|
||||
- [High event volume] → server-side sampling, per-entity output caps, and retention pruning bound storage and response size.
|
||||
- [Late events] → query sorting and identity deduplication keep trails deterministic; transition rules avoid reopened or cross-vehicle overlap.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add model-first track/segment records, memory/file/MySQL persistence, projection, retention, and test coverage.
|
||||
2. Register the plugin map declaration and typed schemas; unsupported deployments remain visibly empty.
|
||||
3. Deploy the authorized API and console map. Existing player and vehicle views remain unchanged.
|
||||
4. Roll back by removing the map panel/declaration; expired projected records are pruned normally and no raw data needs migration.
|
||||
@@ -1,23 +0,0 @@
|
||||
## Why
|
||||
|
||||
SCUM operations currently show player identity and vehicle snapshots, but operators cannot explain where a selected player or vehicle has been over a bounded period. A server-scoped, permission-checked map projection is needed without exposing raw logs, Companion connectivity, host data, or arbitrary coordinate queries.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Define controlled SCUM Companion/log-projection events for `player.position`, `vehicle.position`, `player.vehicle.enter`, and `player.vehicle.leave`.
|
||||
- Require the plugin to declare map version, coordinate conversion, sampling precision, and retention policy; project accepted events into server-isolated trajectory records.
|
||||
- Add a bounded, authorized map API with time windows, player/vehicle filters, vehicle-riding segments, source/collection timestamps, and explicit missing-map/empty states.
|
||||
- Add a Chinese SCUM console map view with point-and-line trajectories and links to the existing player detail and vehicle context.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `scum-map-trajectories`: Controlled collection, projection, retention, authorization, and map rendering of SCUM player and vehicle trajectories.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects platform domain/model/repository/service/validation/API DTOs and durable metadata snapshots.
|
||||
- Extends the SCUM plugin manifest and schemas with bounded map metadata and semantic trajectory events.
|
||||
- Adds platform-web API contracts and a shared-console map surface; it receives only safe projected coordinates and metadata.
|
||||
- Does not add OCR, screen/input automation, direct game/window access, raw logs, unbounded location retention, or live heatmaps.
|
||||
@@ -1,59 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Controlled SCUM trajectory event contracts
|
||||
The system SHALL accept SCUM location information only as platform-managed Companion or accepted log-projection semantic events named `player.position`, `vehicle.position`, `player.vehicle.enter`, and `player.vehicle.leave`, each carrying bounded IDs, occurrence and collection timestamps, declared source, and matching map metadata.
|
||||
|
||||
#### Scenario: An undeclared or malformed location event arrives
|
||||
- **WHEN** an event has an unknown type, malformed bounded ID, non-finite coordinate, invalid source, or mismatched map declaration
|
||||
- **THEN** the system SHALL reject it from trajectory projection and SHALL not expose raw event material to the browser
|
||||
|
||||
### Requirement: Plugin-declared safe map conversion
|
||||
The SCUM plugin SHALL declare a map ID/version, coordinate transform/world bounds, sampling precision, and finite retention period. The platform SHALL convert accepted world points into a rounded safe map projection before persistence or API delivery.
|
||||
|
||||
#### Scenario: A point is outside declared map bounds
|
||||
- **WHEN** a valid position event has world coordinates outside the declared transform bounds
|
||||
- **THEN** the platform SHALL not persist or return a map point for that event
|
||||
|
||||
#### Scenario: Map metadata is absent
|
||||
- **WHEN** a server plugin has no compatible map declaration
|
||||
- **THEN** the map API and console SHALL return a readable missing-map state without attempting alternative collection
|
||||
|
||||
### Requirement: Ordered, sampled, and retained server-isolated trajectories
|
||||
The system SHALL index points by server, entity, and occurrence time; tolerate duplicate and out-of-order events; apply declared sampling compression; and remove points and closed ride segments after the declared retention period.
|
||||
|
||||
#### Scenario: Duplicate or delayed position event
|
||||
- **WHEN** the same accepted event is delivered twice or an older point arrives after a newer point
|
||||
- **THEN** the system SHALL retain no duplicate and SHALL return all accepted points ordered by occurrence time without regressing current sampling state
|
||||
|
||||
#### Scenario: A point is below the sampling threshold
|
||||
- **WHEN** a same-entity point occurs inside the declared minimum time and distance thresholds
|
||||
- **THEN** the system SHALL compress it rather than persist another display point
|
||||
|
||||
#### Scenario: Retention expires
|
||||
- **WHEN** normal projection or map retrieval occurs after a point or closed riding segment passes its retention deadline
|
||||
- **THEN** the system SHALL remove the expired record while preserving unrelated player identity and vehicle snapshot data
|
||||
|
||||
### Requirement: Vehicle ride association
|
||||
The system SHALL derive player vehicle segments from typed enter/leave events and SHALL close a prior active segment before opening a segment for a different vehicle.
|
||||
|
||||
#### Scenario: A player changes vehicles without a leave event
|
||||
- **WHEN** a player enters a second vehicle while a first vehicle segment remains active
|
||||
- **THEN** the system SHALL close the first segment at the second enter time and open one segment for the second vehicle
|
||||
|
||||
### Requirement: Authorized bounded map read model
|
||||
The system SHALL authorize server access before returning a maximum 24-hour trajectory window and SHALL expose only safe projected points, declared map metadata, collection/source labels, entity summaries, and detail-link identifiers. It SHALL not expose raw coordinates, raw logs, IPs, paths, credentials, host information, or Run/Companion connectivity.
|
||||
|
||||
#### Scenario: Unauthorized map request
|
||||
- **WHEN** a session lacks access to the requested server instance
|
||||
- **THEN** the API SHALL deny the request without revealing map availability, entity existence, or trajectory data
|
||||
|
||||
#### Scenario: Cross-server entity selector
|
||||
- **WHEN** a requested player or vehicle ID belongs only to another server
|
||||
- **THEN** the response SHALL not include its points or reveal the other server association
|
||||
|
||||
### Requirement: Explainable SCUM map console
|
||||
The SCUM console SHALL render declared map metadata, collection source/times, selected player and vehicle points/lines, ride segments, time and entity filters, and textual empty or missing-map states. Map entity interactions SHALL use the returned safe detail-link identifiers.
|
||||
|
||||
#### Scenario: An operator selects a trail entity
|
||||
- **WHEN** an operator selects a player or vehicle map item
|
||||
- **THEN** the console SHALL navigate or invoke the matching player/vehicle detail context using the returned identifier without constructing arbitrary coordinate or data queries
|
||||
@@ -1,19 +0,0 @@
|
||||
## 1. Specification and contracts
|
||||
|
||||
- [x] 1.1 Define the platform domain/model/repository contracts for declared map metadata, safe points, ride segments, bounded filters, and map read response.
|
||||
- [x] 1.2 Add SCUM manifest map declaration and typed semantic event schemas for position and vehicle transitions.
|
||||
|
||||
## 2. Platform projection and API
|
||||
|
||||
- [x] 2.1 Implement map declaration validation, safe coordinate conversion, sampling compression, event deduplication/order handling, ride-segment projection, and expiry pruning.
|
||||
- [x] 2.2 Add authorized server map route, named DTOs, and safe response mapping with time/entity bounds and missing-map state.
|
||||
- [x] 2.3 Add backend tests for conversion, duplicate/out-of-order events, cross-vehicle segments, filters, authorization, sampling, retention, and cross-server isolation.
|
||||
|
||||
## 3. Console
|
||||
|
||||
- [x] 3.1 Add frontend API/types/contracts and a shared-theme SCUM map component with time/player/vehicle filters, point/line trails, source/timestamp labels, and empty/missing-map states.
|
||||
- [x] 3.2 Wire safe player/vehicle detail interactions and add focused component/schema tests.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run relevant Go, plugin, and frontend tests/build; run `openspec validate add-scum-map-trajectories --strict` and `scripts/check-structure.sh`.
|
||||
@@ -1,4 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-28
|
||||
goal: Provide safe authorized SCUM player attribute updates through the declared
|
||||
game-client bridge.
|
||||
@@ -1,3 +0,0 @@
|
||||
# add-scum-player-state-patch
|
||||
|
||||
SCUM player detail and approved version-scoped attribute patching
|
||||
@@ -1,42 +0,0 @@
|
||||
## Context
|
||||
|
||||
The prior `scum-game-player-intelligence` change owns server-local player identity, sessions, risk signals, and access control. The existing game-client bridge supplies declared commands, approval states, leases, audit references, and result fencing, but it does not itself constrain individual game-state fields or maintain a readable player-change history.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Permit only catalogued SCUM skills and character attributes for an explicitly declared server game version.
|
||||
- Verify player/server ownership, current state version, companion availability, declared maintenance/online safety state, and platform-admin approval before dispatch.
|
||||
- Record before/after value, reason, requester, approver, bridge command result, and read-after-write confirmation as an immutable patch audit.
|
||||
- Prevent unknown versions, fields, out-of-range values, stale versions, unsafe execution windows, and unknown/failed execution from being represented as applied.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- SQL or database access, raw JSON/INI write APIs, host paths, direct Run/game connections, OCR/input automation, player identity/risk-signal edits, bans, gifts, or map trails.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Catalog at the platform boundary.** `SCUMPlayerStateCatalog` maps a declared server game version to a small list of field keys and numeric ranges. No caller or plugin payload can introduce fields dynamically. The initial exact version is `0.9.700.90357` and supports `skills.running` and `attributes.strength` in range 0–10.
|
||||
|
||||
2. **Use a dedicated typed bridge operation.** The manifest declares only `game-state.patch`, with a schema requiring target player ID, game version, expected state version, safety-window token, reason, and a list of catalogued changes. The result carries a bounded per-field outcome and an immediate confirmed state version; it contains no raw storage/database material.
|
||||
|
||||
3. **Two-stage platform-admin approval.** A server-authorized requester creates a durable patch record in `pending-approval`. A platform admin approves it after revalidating authorization, catalog, snapshot version, and safety window. Approval queues the bridge command and remains auditable; a requester who is also platform admin still creates then approves the explicit record.
|
||||
|
||||
4. **Snapshot/state fencing and confirmation.** A current `player.state` snapshot is the source of before values and its `stateVersion` is copied into the requested patch. The companion must reject mismatches, apply only declared fields in a verified maintenance/offline safety window, then read state back before returning success. Platform marks a record `confirmed` only when each returned value exactly equals its requested value and the returned state version advances. Failed and unknown results stay readable terminal audit states.
|
||||
|
||||
5. **Ownership is revalidated at every transition.** Player record lookup checks server ownership before viewing, creating, approving, or reading a patch. The bridge command is scoped to the same server plugin and profile; the generic queue cannot be used as an alternate raw patch entry point because the dedicated service owns field/snapshot validation and records the audit before dispatch.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Companion has no exact version/state snapshot] → Disable the form and return a readable unsupported/unknown-version result.
|
||||
- [State changes between snapshot and execution] → The expected state version causes the companion to reject; record the conflict without claiming application.
|
||||
- [Companion times out or result is missing] → Keep the record `execution-unknown`; do not infer a write, and require a later confirmation read.
|
||||
- [Maintenance state becomes unsafe] → Approval and companion both reject dispatch; no write is attempted.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add model-first patch records, memory/file/MySQL repositories, and immutable transition helpers.
|
||||
2. Deploy the manifest schemas and companion version declaration; no version is implicitly supported.
|
||||
3. Deploy the API and console. Existing player profiles retain all read-only intelligence behavior.
|
||||
4. Roll back by disabling the command declaration and form; historical audit records remain readable.
|
||||
@@ -1,22 +0,0 @@
|
||||
## Why
|
||||
|
||||
SCUM player intelligence currently presents useful local identity and risk context, but administrators cannot safely correct the limited in-game state that the installed server version explicitly supports. A controlled patch workflow is required so changes remain reviewable, version-fenced, approved, and executed only through the companion command channel.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a SCUM version-scoped player-state field catalog for supported skills and character attributes only.
|
||||
- Add player-state read snapshots and an approved `game-state.patch` bridge operation with optimistic state-version checks, safe execution-window checks, and confirmation reads.
|
||||
- Persist an immutable patch audit record containing requested old/new values, reason, requester/approver, command result, and confirmation status.
|
||||
- Add authorized API contracts and Chinese console controls that show the editable diff, approval state, readable outcome, and player context.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `scum-player-state-patch`: Version-fenced, approved SCUM player skill and character-attribute changes via the game-client bridge.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects Platform player domain/models/repositories/services/validation/API and durable metadata storage.
|
||||
- Extends the SCUM manifest with a bounded patch command and typed schemas, plus Platform Web contracts and console records.
|
||||
- Does not permit SQL, raw configuration/JSON/INI writing, direct game database access, unbounded state editing, automatic moderation, gifts, or map trails.
|
||||
@@ -1,48 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Version-scoped player state catalog
|
||||
The system SHALL allow SCUM player state patches only for a declared exact game version and an explicit catalog of skill/attribute fields with numeric ranges.
|
||||
|
||||
#### Scenario: Unknown server version
|
||||
- **WHEN** an administrator requests a patch and the current server state reports an unknown game version
|
||||
- **THEN** the system SHALL disable the patch request and SHALL not queue a bridge command
|
||||
|
||||
#### Scenario: Out-of-range or unknown field
|
||||
- **WHEN** a request contains a field absent from the version catalog or a value outside its range
|
||||
- **THEN** the system SHALL reject the request before an audit approval or game-side command is created
|
||||
|
||||
### Requirement: Authorized and safe patch request
|
||||
The system SHALL ensure that the game player belongs to the target server, the requester has server access, the expected player-state version matches the current snapshot, and the snapshot declares a verified maintenance/offline safety window before creating a patch record.
|
||||
|
||||
#### Scenario: Stale player state
|
||||
- **WHEN** a patch carries an expected state version different from the current player-state snapshot
|
||||
- **THEN** the system SHALL reject it as a conflict and SHALL not dispatch a patch command
|
||||
|
||||
#### Scenario: Online server without a safe window
|
||||
- **WHEN** a state snapshot indicates the target player is online or maintenance is not verified
|
||||
- **THEN** the system SHALL reject the request with a readable safety status
|
||||
|
||||
### Requirement: Explicit administrator approval and immutable audit
|
||||
The system SHALL persist each accepted request with field-level before/after values, reason, requester, approval state, approver, and execution status. Only a platform administrator with server access MAY approve dispatch.
|
||||
|
||||
#### Scenario: Non-admin approval
|
||||
- **WHEN** a server-authorized non-platform-admin attempts to approve a pending patch
|
||||
- **THEN** the system SHALL deny approval and SHALL leave the patch pending
|
||||
|
||||
### Requirement: Typed game-state patch execution and confirmation
|
||||
The system SHALL dispatch only the declared `game-state.patch` command through the game-client bridge. A successful record SHALL require a typed per-field result and a read-after-write confirmation whose values equal the requested values and whose state version advances.
|
||||
|
||||
#### Scenario: Companion reports a failure
|
||||
- **WHEN** the companion returns a failed patch command result
|
||||
- **THEN** the patch record SHALL be terminal `execution-failed`, preserve the readable result summary, and SHALL not be reported as applied
|
||||
|
||||
#### Scenario: Result is missing or unconfirmable
|
||||
- **WHEN** the command expires, is cancelled, returns malformed state, or cannot confirm the requested values
|
||||
- **THEN** the record SHALL retain an explicit `execution-unknown` or `confirmation-failed` status and SHALL not be reported as applied
|
||||
|
||||
### Requirement: Readable SCUM console workflow
|
||||
The SCUM player console SHALL show player detail context and provide a Chinese patch form only for supported safe states. It SHALL show a textual field diff, reason, approval status, executor result, and confirmation status without relying only on color.
|
||||
|
||||
#### Scenario: Pending approval
|
||||
- **WHEN** a patch is awaiting approval
|
||||
- **THEN** the console SHALL label it as awaiting platform-administrator approval and display the old/new values and requester reason
|
||||
@@ -1,21 +0,0 @@
|
||||
## 1. Contracts, models, and persistence
|
||||
|
||||
- [x] 1.1 Add version-scoped SCUM state catalog, player-state snapshot/patch domain types, audit model/repositories/migration/store implementations, and field/safety validation.
|
||||
- [x] 1.2 Add service state machine for request, platform-admin approval, bridge-result reconciliation, and confirmation-read semantics with immutable audit evidence.
|
||||
- [x] 1.3 Add focused backend tests for unknown version, invalid field/range, server ownership, stale version, unsafe window, approval permission, execution failure/unknown, audit, and confirmation.
|
||||
|
||||
## 2. API and SCUM bridge contract
|
||||
|
||||
- [x] 2.1 Add named DTOs and authorized player-state/patch API routes and tests.
|
||||
- [x] 2.2 Declare `game-state.patch` and player-state schemas in the SCUM manifest, extend companion bridge validation fixtures/tests, and preserve the typed bounded command channel.
|
||||
|
||||
## 3. SCUM console
|
||||
|
||||
- [x] 3.1 Add frontend API/types and Chinese player-detail patch controls using shared console/theme primitives.
|
||||
- [x] 3.2 Render readable diff, reason, approval, execution, and confirmation histories; disable unsupported or unsafe writes.
|
||||
- [x] 3.3 Add frontend tests for field labels, diff/audit readability, and disabled safety states.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run strict OpenSpec validation, focused backend/plugin/frontend tests, and `scripts/check-structure.sh`.
|
||||
- [x] 4.2 Stage only this task's files, commit on `main`, and push the configured remote.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-23
|
||||
@@ -1,77 +0,0 @@
|
||||
## Context
|
||||
|
||||
The prior UE4SS DLL change provisions `ue4ss/Mods/scum_simple_rcon/config.ini` before a normal SCUM start, but the declared Run `rcon` adapter is only an envelope placeholder. The shipped DLL is a Source RCON server that is intentionally loopback-only and accepts raw SCUM commands on its game-thread queue; `SendChat <type> "message" [SteamID64]` is its supported chat form.
|
||||
|
||||
Platform and Run already use leased jobs, signed Run-only input routes, scoped workspaces, and durable job state. Sending a raw admin command through the generic remote-adapter `inputs` map would persist it in the Platform job and Run journal, conflicting with the requested no-history/no-audit behavior.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Let an authorized server operator send a typed chat message or raw SCUM command through the existing job channel without a second confirmation or command audit record.
|
||||
- Transfer a command exactly once to the active leased Run worker without storing the raw text or RCON password in Platform persistence, job assignments, Run journals, browser DTOs, logs, or result messages.
|
||||
- Bind every dispatch to a ready, selected Windows amd64 UE4SS DLL declaration and a fixed Source RCON loopback plan.
|
||||
- Have Run authenticate to `127.0.0.1` using the protected generated config and implement the Source RCON wire protocol with bounded I/O.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Do not modify, build, or redeploy the UE4SS DLL source as part of command transport.
|
||||
- Do not create a generic remote TCP/RCON gateway, expose an RCON host or password, or allow browser-to-Run sockets.
|
||||
- Do not persist raw command text, chat text, source responses, a command history, or per-command audit events.
|
||||
- Do not retry a mutating command automatically, provide a Linux `.dll` fallback, or implement a separate Linux UE4SS `.so` runtime.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision: Use a dedicated typed SCUM RCON request instead of generic remote-adapter inputs
|
||||
|
||||
Platform will expose a typed server-scoped request that accepts either a chat payload (`type`, message, optional SteamID64) or a bounded raw command. It validates the source DLL grammar and formats chat as `SendChat` internally. It validates ownership, the declared RCON capability, selected runtime binding, ready extension release, Windows amd64 endpoint, and the selected profile's RCON transport before it creates a job.
|
||||
|
||||
The job contains only an opaque input reference and a frozen `source-rcon` connection plan: extension key/mod key, logical config reference, and port. It contains no host, command, response, or secret. The existing generic remote-adapter endpoint remains suitable for declared non-secret inputs but is not used for raw SCUM commands.
|
||||
|
||||
Alternative considered: put `command` in `ExecutionInput.Inputs`. Rejected because Platform persistence, job claims, and Run's durable journal would retain the command.
|
||||
|
||||
### Decision: Use a one-time in-memory input broker fenced by the active Run lease
|
||||
|
||||
Platform stores each validated command in a mutex-protected, TTL-bounded in-memory broker before the corresponding job becomes claimable. The broker key is the job ID and cannot overwrite an outstanding submission with the same idempotency key. The signed Run-only RCON-input route first verifies endpoint, session, job, lease, attempt, capability, and frozen plan, then consumes and removes the payload.
|
||||
|
||||
The RCON job has exactly one attempt. A Platform restart, expired broker entry, worker crash after consume, or repeat input read fails closed rather than replaying a possibly mutating game command. Job/audit/result summaries use only generic delivery state.
|
||||
|
||||
Alternative considered: encrypting a durable broker row. Rejected because the explicit product boundary is no raw command persistence; encryption would still create history and recovery/replay semantics.
|
||||
|
||||
### Decision: Freeze a source-RCON loopback plan from the selected ready UE4SS extension
|
||||
|
||||
Platform derives the config reference from the extension's declared DLL layout (`ue4ss/Mods/<modKey>/config.ini`) and freezes the published port plus mod/extension identity. Because the actual SCUM executable may be below the workspace root, Run also owns a verified deployment-state marker that records the scoped logical config location written during DLL activation. The frozen plan carries only that safe marker reference; Run validates its extension/mod/port and expected config suffix before it reads the protected file. Run accepts only the `source-rcon` kind, Windows amd64, safe logical references, and an unprivileged declared port. There is no configurable host; Run always dials `127.0.0.1:<port>` in the server's scoped workspace.
|
||||
|
||||
The generator is corrected to write the DLL's actual `bind_address=127.0.0.1` setting. Run rejects a managed config whose port or bind address no longer matches the frozen plan.
|
||||
|
||||
Alternative considered: resolve paths or credentials in Platform. Rejected because Platform must not receive host paths or the generated RCON password.
|
||||
|
||||
### Decision: Treat Source RCON result bodies as sensitive transient data
|
||||
|
||||
Run authenticates, executes one command, and reads bounded response packets until the DLL's empty response sentinel. It classifies an `error:` response as a failed job but returns only a safe status/error code; it never includes raw command text, password, or response body in logs, artifacts, result messages, or Platform-facing payloads.
|
||||
|
||||
Alternative considered: stream full RCON output to the browser. Rejected because source responses may echo command text or game/player data and would reintroduce command history through job results/logs.
|
||||
|
||||
### Decision: Give the management console two direct entry points
|
||||
|
||||
The existing server detail surface gets a compact chat form and a raw-command form. Both submit immediately using typed API contracts and display only the current safe queue/result status. They intentionally do not add a confirmation modal, saved form history, command list, secret field, host field, or response transcript.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Platform or worker restarts during a command] → the broker payload is gone or consumed; the job fails closed and an operator can explicitly submit a new command.
|
||||
- [SCUM/UE4SS is not loaded or the port is unavailable] → Run returns a safe connection/auth/protocol failure without falling back to a remote address.
|
||||
- [An RCON response echoes sensitive input] → Run only classifies it and does not surface the body.
|
||||
- [A user submits an unsupported chat target or malformed text] → Platform rejects it before a job/broker entry is created.
|
||||
- [A DLL declaration is still unpublished] → the feature stays unavailable until real immutable release pins are published and selected.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Deploy Platform, Run, plugin manifest, and management-console changes together.
|
||||
2. Publish a real ready DLL declaration, ensure the Windows UE4SS bootstrap is present, and restart SCUM so Run writes the managed loopback config.
|
||||
3. Verify `rcon.status` or a harmless `rcon.chat` through the console on a non-production server, then send a broadcast and an allowed admin command.
|
||||
4. Roll back by removing the new Run capability/using the previous Platform and Run releases; no persistent commands or secrets require migration or cleanup.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- The current SCUM manifest is intentionally unpublished; end-to-end production dispatch remains gated until the publisher supplies the real DLL URL, checksum, size, executable checksum, and UE4SS ABI.
|
||||
- Future command-output streaming would need a separate transient, authorization-reviewed design rather than reusing durable job results.
|
||||
@@ -1,30 +0,0 @@
|
||||
## Why
|
||||
|
||||
The SCUM UE4SS lifecycle now provisions a protected, loopback-only Source RCON listener, but Run's declared `rcon` adapter is still a placeholder that reports success without connecting to the listener. Operators therefore cannot actually send chat text or SCUM admin commands through the platform, and raw commands must not become a durable command-history or audit feature.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a typed SCUM RCON dispatch path for direct chat delivery and raw SCUM admin commands, with no secondary confirmation step and no persisted command/audit payload.
|
||||
- Freeze a ready Windows UE4SS extension's safe loopback Source RCON connection metadata into a single-attempt Run job; reject unpublished, incompatible, or non-SCUM extension states before dispatch.
|
||||
- Keep the raw command only in a bounded, one-time, in-memory Platform input broker. The signed active Run lease retrieves it once; database jobs, Run journals, browser responses, audit events, logs, and result messages contain no command text or RCON password.
|
||||
- Replace Run's placeholder RCON adapter with a bounded Source RCON client that reads the generated protected config inside its scoped workspace, authenticates only to `127.0.0.1`, and sends the command using standard framed packets.
|
||||
- Add a server-management-console RCON panel for chat broadcasts/targeted chat and raw commands. It reports safe queued/succeeded/failed state without building a command history.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `scum-source-rcon-command-dispatch`: Platform authorization, one-time command delivery, safe browser contracts, and SCUM-specific dispatch constraints.
|
||||
- `run-source-rcon-execution`: Run-side loopback Source RCON authentication, packet exchange, response classification, and failure handling.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- `platform/`: domain/DTO/API contracts, command validation, transient input broker, fenced Run-only input endpoint, lifecycle/extension resolution, and focused tests.
|
||||
- `platform_web/`: typed API client, schemas, and the existing server-detail management surface.
|
||||
- `plugins/`: SCUM lifecycle capability declaration and manifest tests.
|
||||
- Independent `run/`: protocol copy, Platform client, Worker dispatch, Source RCON adapter, and unit/integration tests.
|
||||
- The UE4SS DLL source remains unchanged. No user-side compiler, generic remote socket, direct browser-to-RCON connection, Linux DLL substitute, raw command persistence, or command audit trail is introduced.
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Run executes a frozen Source RCON plan over loopback
|
||||
Run SHALL execute a `source-rcon` plan only for Windows amd64 and only by dialing `127.0.0.1` at the frozen declared port. It SHALL resolve the plan's generated config through the scoped workspace, read the protected password locally, and use Source RCON authentication and framed command/response packets. It SHALL not accept a browser-provided host, socket, path, or password.
|
||||
|
||||
#### Scenario: Valid loopback Source RCON command completes
|
||||
- **WHEN** Run receives a valid frozen plan and one-time command for a running compatible SCUM server
|
||||
- **THEN** it authenticates to the local DLL listener, sends the command, consumes the terminal response sentinel, and completes the job with a safe success status.
|
||||
|
||||
#### Scenario: Unsafe plan or local configuration is rejected
|
||||
- **WHEN** a plan is not `source-rcon`, is non-Windows, has an unsafe config key/port, or the local config is missing, non-loopback, or inconsistent with the frozen port
|
||||
- **THEN** Run fails before opening a socket or sending a command.
|
||||
|
||||
### Requirement: Run bounds and redacts Source RCON I/O
|
||||
Run SHALL bound command bytes, packet sizes, response bytes, response packet count, dialing, authentication, and command execution by the job context. It SHALL classify an RCON error response as a failed job but SHALL NOT persist or return the raw command, password, response body, config contents, or local path in logs, artifacts, progress, or result messages.
|
||||
|
||||
#### Scenario: Source RCON error response remains private
|
||||
- **WHEN** the DLL returns an `error:` response or malformed response framing
|
||||
- **THEN** Run returns a safe error code/message without exposing the returned body or submitted command.
|
||||
|
||||
### Requirement: Source RCON transport is at-most-once
|
||||
Run SHALL retrieve the command from the active Platform input route once per job and SHALL not retry a command after input, authentication, dial, or response failure. It SHALL not fall back to the placeholder remote adapter, a generic TCP address, `rundll32`, process injection, or a Linux loader.
|
||||
|
||||
#### Scenario: Lost one-time input does not replay a command
|
||||
- **WHEN** Run cannot retrieve a fresh one-time command or loses execution after it was consumed
|
||||
- **THEN** it fails the job safely and does not send a duplicate command.
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Platform dispatches a typed SCUM Source RCON command
|
||||
Platform SHALL accept a server-authorized typed request for either a SCUM chat message or a bounded raw SCUM command only when the installed plugin declares `remote.run.rcon.command`, the selected runtime profile declares the RCON transport, the endpoint reports the capability, and a selected ready Windows amd64 UE4SS DLL extension provides the Source RCON plan. Chat requests SHALL validate a type from 0 through 7, 1–1024 UTF-8 message bytes, and an optional 17-digit SteamID64 before Platform formats the DLL-supported `SendChat` command. Raw commands SHALL be non-empty UTF-8, contain no NUL/newline control framing, and fit within the declared Source RCON packet bound.
|
||||
|
||||
#### Scenario: Authorized chat dispatch is queued
|
||||
- **WHEN** an authorized operator submits a valid broadcast or targeted chat request for a compatible ready SCUM server
|
||||
- **THEN** Platform creates one scoped `remote.run.rcon.command` job with a frozen Source RCON plan and returns only safe queued state.
|
||||
|
||||
#### Scenario: Unsupported command request is rejected before dispatch
|
||||
- **WHEN** a request has malformed chat data, an unsafe raw command, an undeclared RCON capability, an unpublished extension, or a non-Windows endpoint
|
||||
- **THEN** Platform rejects it without creating a job or retaining command text.
|
||||
|
||||
### Requirement: Raw RCON input is transient and one-time
|
||||
Platform SHALL hold raw RCON command text only in a bounded in-memory one-time broker keyed by the dispatch job. The persisted job, job assignment, browser DTOs, audit events, and result messages SHALL omit command text, chat text, source responses, host paths, and RCON credentials. RCON command jobs SHALL have one attempt and SHALL not automatically retry.
|
||||
|
||||
#### Scenario: Active Run lease consumes a command once
|
||||
- **WHEN** the active leased Run attempt requests its RCON input
|
||||
- **THEN** Platform returns the command once and removes it from the broker.
|
||||
|
||||
#### Scenario: Repeated, expired, or restarted delivery fails closed
|
||||
- **WHEN** a broker payload was already consumed, expired, or lost after a Platform restart
|
||||
- **THEN** a later Run input request fails safely and does not replay the command.
|
||||
|
||||
### Requirement: Only the active signed Run attempt receives RCON input
|
||||
Platform SHALL expose RCON command input only through a signed Run-only route after validating the endpoint, session, job ID, lease token, attempt, scoped server, RCON capability, and frozen Source RCON plan. Browser and plugin APIs SHALL never receive the RCON input, password, host address, or generated local config path.
|
||||
|
||||
#### Scenario: Stale or foreign lease cannot read a command
|
||||
- **WHEN** a Run input request has a wrong endpoint, session, lease token, attempt, or job capability
|
||||
- **THEN** Platform denies it and leaves a valid unconsumed broker payload intact.
|
||||
|
||||
### Requirement: Management console provides direct chat and command controls
|
||||
The server management surface SHALL render direct chat and raw-command controls only through the typed Platform API. It SHALL not request a secondary confirmation, retain a command transcript, expose RCON connection material, or show raw Source RCON replies.
|
||||
|
||||
#### Scenario: Console sends a chat without creating history
|
||||
- **WHEN** an authorized operator submits a valid chat form
|
||||
- **THEN** the console displays the safe dispatch status and does not render the chat text as a durable command record.
|
||||
@@ -1,22 +0,0 @@
|
||||
## 1. Platform one-time command contracts
|
||||
|
||||
- [x] 1.1 Add typed Source RCON plan, chat/raw-command request, safe dispatch response, and bounded validators without exposing command or secret values in persisted job structures.
|
||||
- [x] 1.2 Resolve a selected ready SCUM UE4SS extension into a Windows-only frozen plan; queue one-attempt RCON jobs through a TTL-bounded in-memory broker with no per-command audit record.
|
||||
- [x] 1.3 Add the signed active-lease Run input contract, API route, DTOs, safe error behavior, and focused Platform tests for authorization, one-time consume, rejection, and redaction.
|
||||
|
||||
## 2. Independent Run Source RCON execution
|
||||
|
||||
- [x] 2.1 Mirror the frozen plan and one-time input protocol; add Platform client and Worker plumbing that keeps raw command text out of job journals.
|
||||
- [x] 2.2 Implement scoped managed-config parsing, Windows loopback validation, bounded Source RCON authentication/packet exchange, response redaction, and safe failure codes; correct generated UE4SS config to use `bind_address`.
|
||||
- [x] 2.3 Add Run tests for successful auth/command, source error, malformed/unsafe config or packets, at-most-once input, and non-Windows rejection.
|
||||
|
||||
## 3. Plugin and management console
|
||||
|
||||
- [x] 3.1 Declare the SCUM local lifecycle RCON capability and add manifest coverage without activating the unpublished DLL release.
|
||||
- [x] 3.2 Add typed frontend client/schema contracts and a direct chat/raw-command server-detail panel with no confirmation, transcript, secret, or source-response display.
|
||||
- [x] 3.3 Add focused frontend rendering/submission tests and confirm safe projections exclude RCON material.
|
||||
|
||||
## 4. Verification and delivery
|
||||
|
||||
- [x] 4.1 Run Platform, plugin, frontend, and Run tests; run `openspec validate add-scum-source-rcon-transport --strict` and `scripts/check-structure.sh`.
|
||||
- [x] 4.2 Review scoped diffs, stage only task files in the browser and independent Run repositories, commit, and push both configured branches.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-22
|
||||
@@ -1,87 +0,0 @@
|
||||
## Context
|
||||
|
||||
`game.scum` currently declares a Windows client-manager package that is built from a Git repository. The replacement is not a user-built executable: it is a publisher-built UE4SS `main.dll` that UE4SS loads into SCUM during the normal server process startup. The supplied RCON project requires UE4SS EngineTick and therefore cannot be loaded by an external EXE or attached safely to an already running SCUM process.
|
||||
|
||||
The Platform already owns plugin manifest validation, runtime binding selection, lifecycle job dispatch, and safe browser DTOs. Run already owns bounded HTTPS dependency downloads, scoped workspaces, direct executable vectors, and lifecycle process supervision. Neither currently has a typed server DLL extension plan or a real RCON adapter.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Let a plugin declare a prebuilt Windows UE4SS DLL release and update policy without exposing user-side compilation, arbitrary commands, host paths, or secrets.
|
||||
- Have Run synchronize the declared release automatically before each SCUM `process.start`, only after Platform has frozen the declaration into the leased job input.
|
||||
- Stage the DLL atomically below a logical server workspace, preserve the previous managed DLL for rollback, generate a local-only RCON configuration, and load through the normal UE4SS startup chain.
|
||||
- Expose safe declaration and synchronization state to the existing plugin/server management views.
|
||||
- Reject Linux for this Windows DLL extension explicitly.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Do not run a compiler, CMake, UE4SS source checkout, or arbitrary executable on an operator machine.
|
||||
- Do not inject a live process, use `rundll32`, `LD_PRELOAD`, remote threads, manual mapping, or a generic DLL loader.
|
||||
- Do not claim a Linux `.dll` equivalent. A future Linux `.so` loader is a separate, game-specific change.
|
||||
- Do not delete or migrate existing client-manager installations automatically.
|
||||
- Do not add per-command confirmation or persisted raw-command history for the future RCON console.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision: Model the payload as a Windows UE4SS DLL extension, not a client manager or executable
|
||||
|
||||
The manifest adds `runtimeProfiles.dllExtensions`. A ready profile has a fixed release URL/checksum/size/version, Windows amd64 target, compatible SCUM executable checksum, UE4SS ABI marker, logical target key, update policy, and loopback health contract. `kind` is fixed to `ue4ss-dll`, `activation` is fixed to `server-start`, and `supportedTargets` is fixed to Windows amd64. An explicit `unpublished` declaration may document an intended release URL but cannot be selected by a lifecycle profile or frozen into a job; this prevents placeholder hashes from reaching an operator machine.
|
||||
|
||||
The SCUM manifest declares the extension while retaining legacy client-manager metadata for existing installations. New server starts use the extension profile rather than building a companion executable.
|
||||
|
||||
Alternative considered: reuse `clientManagers`. Rejected because a UE4SS DLL is loaded by SCUM rather than supervised as an independent component process.
|
||||
|
||||
### Decision: Synchronize within the existing `process.start` lifecycle job
|
||||
|
||||
Platform copies the selected DLL extension plan into the fenced start-job execution input. Run performs sync before it launches the server executable. The job is the automatic update check: every start compares the installed managed release checksum/version with the declaration and updates only when necessary.
|
||||
|
||||
This avoids a new always-on download poller, preserves control/job/log/artifact channel isolation, and means Run never obtains unleased plugin configuration. A version change takes effect at the next normal server start. Future scheduled maintenance can queue an ordinary restart/start lifecycle job.
|
||||
|
||||
Alternative considered: let Run periodically poll plugin URLs directly. Rejected because it makes Run independently trust mutable plugin configuration and consumes network/resources outside Platform job fencing.
|
||||
|
||||
### Decision: Use release-pinned, scoped, atomic deployment
|
||||
|
||||
Run accepts only HTTPS URLs with a declared `sha256:` checksum and a bounded size. It downloads to a per-server extension staging root, verifies bytes before activation, and replaces only the managed DLL path atomically. It records a small local managed-release marker and retains one previous DLL copy for rollback. It never extracts archives, follows unsafe redirects, or accepts arbitrary target paths.
|
||||
|
||||
The generated `config.ini` contains a locally supplied RCON password reference/value only in the protected server workspace; it is not returned to Platform, plugins, browser DTOs, artifacts, or logs. `mods.txt` is updated idempotently using the exact declared extension key. UE4SS bootstrap files are not silently installed by this first change; the extension reports a blocked health result when the expected UE4SS layout is absent.
|
||||
|
||||
Alternative considered: download a whole UE4SS/bootstrap package on every server. Rejected for the first release because shared loader ownership and rollback across other mods requires a separate extension-runtime manager.
|
||||
|
||||
### Decision: Windows-only activation and explicit Linux rejection
|
||||
|
||||
The supplied module links Windows APIs and produces a `.dll`. Windows activation is the standard UE4SS startup path: the already-installed UE4SS loader reads `mods.txt` and loads the DLL after SCUM starts. Run does not mount or execute the DLL itself.
|
||||
|
||||
Linux would require a separately built `.so`, an independently verified UE4SS/Linux loader path, and game-specific compatibility. Run returns `unsupported_extension_platform` for this profile on Linux and does not try `LD_PRELOAD`.
|
||||
|
||||
### Decision: Address compatibility is owned by the DLL release
|
||||
|
||||
Native SCUM executor addresses are not configured in Platform or Run. The publisher-built DLL holds the vetted resolver table keyed by SCUM executable compatibility data and fails closed when its native probe cannot resolve exactly once. Platform/Run only select the right declared DLL release by compatible SCUM executable checksum.
|
||||
|
||||
Alternative considered: Run-side signature scanning or automatic generation. Rejected because it would make the executor a reverse-engineering authority and could execute an incorrect native address.
|
||||
|
||||
### Decision: Safe UI projections and no raw command history
|
||||
|
||||
Plugin detail and server detail show release version, checksum prefix, loading mode, supported target, update-on-start policy, last safe sync state, and Linux incompatibility. They do not show raw paths, URLs with credentials, RCON passwords, Run sessions, or native signatures. A future RCON console is direct operator input with transient delivery; it is not a confirmation dialog or a persisted command-history feature.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [A SCUM update changes native code] → DLL fails its internal probe; Run leaves the previous managed release in place and reports extension health unavailable rather than guessing an address.
|
||||
- [A malicious/changed CDN response] → checksum, HTTPS validation, bounded size, and staged verification block activation.
|
||||
- [UE4SS is not installed or incompatible] → sync completes the managed DLL only when safe, then reports a clear blocked health state; it does not copy proxy DLLs or alter shared loader files.
|
||||
- [A server host has multiple instances] → extension target and port are scoped by the existing server workspace/runtime binding; no global path is projected.
|
||||
- [Start job fails after update] → previous managed DLL is retained and a retry sees a coherent marker; full SCUM process rollback remains the existing lifecycle responsibility.
|
||||
- [Linux host selected] → the job is rejected before download and UI projects the unsupported platform state.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Register a new `game.scum` manifest version with a Windows UE4SS extension profile and preserve legacy client-manager declarations.
|
||||
2. On the next Windows start, Platform freezes the extension plan into the lifecycle job and Run syncs it before process launch.
|
||||
3. Operators ensure the approved UE4SS runtime is already present once; the DLL and generated configuration are then managed automatically.
|
||||
4. Roll back by publishing/reselecting the previous pinned DLL declaration and restarting the server; Run restores the previous managed DLL if activation fails.
|
||||
5. Existing client-manager installations are not stopped, deleted, or migrated automatically.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- A future change may manage the shared UE4SS bootstrap/runtime as a separately owned, reference-counted extension dependency.
|
||||
- A future Linux SCUM/UE4SS `.so` implementation requires its own compatibility and loader design.
|
||||
@@ -1,33 +0,0 @@
|
||||
## Why
|
||||
|
||||
The current SCUM plugin declares a separately built companion client, but the new SCUM RCON integration is a prebuilt UE4SS DLL that must load with the SCUM server process. Operators must not compile it, Run must not execute arbitrary binaries or inject a running process, and the platform currently has no declared, version-pinned DLL extension lifecycle.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a plugin-declared Windows-only UE4SS DLL extension profile with a fixed HTTPS release URL, SHA-256 checksum, file size, compatible SCUM executable checksum, UE4SS ABI marker, logical deployment target, and loopback RCON health probe.
|
||||
- Freeze the declared extension plan into the existing fenced `process.start` job. Run stages the approved DLL, generated configuration, and deterministic `mods.txt` entry before the normal SCUM process starts; there is no independent sync job or background poller.
|
||||
- Add Run-side verified DLL synchronization with bounded HTTPS download, scoped file ownership, atomic replacement, rollback, no runtime process injection, and an explicit Linux rejection for the Windows DLL extension.
|
||||
- Surface declared extension metadata and safe per-server state in plugin and server management views. The UI shows the release/version/checksum/loading mode and that Linux is unsupported, without exposing host paths, RCON passwords, or Run credentials.
|
||||
- Replace the SCUM example's new-server dependency on the `scum-client-manager` path with the UE4SS RCON extension declaration. Existing client-manager records remain compatible and are not deleted by this change.
|
||||
- Provision the extension's loopback-only Source RCON configuration for the existing declared remote-access boundary. This change does not create a second command console, per-command confirmation, or raw-command history.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `plugin-runtime-dll-extensions`: Plugin manifest, Platform validation, safe projections, and server-start ordering for versioned Windows UE4SS DLL extensions.
|
||||
- `run-ue4ss-dll-synchronization`: Independent Run download, staging, activation, UE4SS configuration, health preconditions, and rollback behavior for an approved UE4SS DLL extension.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- `plugins/`: manifest schema, validator, SCUM example declaration, and fixtures.
|
||||
- `platform/`: domain/DTO/validation/job contracts, server start dispatch, fenced extension-sync input, safe state projection, and API handlers.
|
||||
- `platform_web/`: API types and existing plugin/server detail surfaces for declared extension state.
|
||||
- Independent `run/`: protocol copies, extension-sync executor, generated local-only RCON configuration, tests, and documentation. It remains an independent Git repository and is not added to this repository.
|
||||
- No user-side compiler, arbitrary executable launch, runtime remote-process injection, Linux DLL support, raw host-path exposure, raw RCON-password exposure, or unrelated product areas are introduced.
|
||||
|
||||
The supplied CDN URL currently has no downloadable DLL. The SCUM example therefore carries an explicit unpublished declaration rather than an invented checksum, and it is not bound to `process.start` until the publisher supplies the real release pins. Ready declarations remain fully immutable and are the only declarations that can be frozen into a start job.
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Plugin declares a bounded Windows UE4SS DLL extension
|
||||
The plugin manifest SHALL support `runtimeProfiles.dllExtensions` entries only for a fixed `ue4ss-dll` kind, Windows amd64 target, `server-start` activation, logical target key, declared DLL relative path, and update-on-start policy. A `ready` release SHALL additionally have an HTTPS release URL, SHA-256 checksum, bounded byte size, SCUM executable checksum, and UE4SS ABI marker. An `unpublished` declaration MAY document an intended release URL but SHALL not be frozen into a start job. The manifest validator SHALL reject executable references, shell arguments, Linux targets, unsafe URLs, non-DLL paths, missing ready-release integrity metadata, and unsafe logical keys.
|
||||
|
||||
#### Scenario: Valid SCUM DLL declaration registers
|
||||
- **WHEN** `game.scum` registers a Windows UE4SS DLL extension with all required immutable release and compatibility fields
|
||||
- **THEN** Platform persists a typed declaration and exposes only a safe projection to browser clients.
|
||||
|
||||
#### Scenario: Unsafe DLL declaration is rejected
|
||||
- **WHEN** a manifest declares a non-HTTPS URL, missing checksum, Linux target, executable command, unsafe path, or missing compatibility checksum
|
||||
- **THEN** manifest validation rejects the registration before it is persisted.
|
||||
|
||||
#### Scenario: Unpublished SCUM release stays inactive
|
||||
- **WHEN** a plugin documents an unpublished UE4SS DLL release before the publisher has supplied its immutable release pins
|
||||
- **THEN** the declaration is safe to display but cannot be referenced by a server-start lifecycle profile or dispatched to Run.
|
||||
|
||||
### Requirement: Server start freezes the declared extension plan
|
||||
Platform SHALL add the selected compatible DLL extension plan to the fenced `process.start` Run job input. The frozen plan SHALL contain only logical target identifiers and release integrity/compatibility metadata, and SHALL reject a start when the selected runtime profile or endpoint platform does not support the extension.
|
||||
|
||||
#### Scenario: Compatible Windows server start includes extension plan
|
||||
- **WHEN** a Windows amd64 SCUM server with a selected compatible runtime profile is started
|
||||
- **THEN** its Run start job includes the current immutable DLL extension plan before process execution.
|
||||
|
||||
#### Scenario: Linux server is rejected without a download
|
||||
- **WHEN** a Linux endpoint is selected for a UE4SS DLL extension profile
|
||||
- **THEN** Platform rejects the extension path with an explicit unsupported-platform result and does not dispatch a DLL download.
|
||||
|
||||
### Requirement: Browser receives a safe extension projection
|
||||
Platform SHALL project extension key, display name, release version, checksum prefix, supported OS/architecture, loading mode, update-on-start policy, compatibility marker, and safe synchronization state to plugin and server management views. It SHALL NOT project RCON passwords, raw host paths, signed Run job data, native signatures, or raw local file metadata.
|
||||
|
||||
#### Scenario: Server detail renders declaration without secrets
|
||||
- **WHEN** an authorized operator views a SCUM plugin or server detail
|
||||
- **THEN** the UI displays safe DLL extension metadata and does not contain credentials, host paths, or native resolver data.
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Run synchronizes a frozen DLL plan before server start
|
||||
Run SHALL synchronize a declared UE4SS DLL extension before executing the associated `process.start` command. It SHALL compare the local managed-release marker against the frozen version/checksum, skip unchanged releases, and otherwise download, checksum-verify, stage, and atomically activate the declared DLL path within the scoped server workspace.
|
||||
|
||||
#### Scenario: Changed approved DLL updates before launch
|
||||
- **WHEN** a start job carries a valid extension plan whose release differs from the managed marker
|
||||
- **THEN** Run verifies and activates the new DLL before launching the server process.
|
||||
|
||||
#### Scenario: Unchanged approved DLL is reused
|
||||
- **WHEN** a start job carries the same version and checksum as the managed marker
|
||||
- **THEN** Run does not download the DLL again and proceeds to server launch.
|
||||
|
||||
### Requirement: Run preserves DLL deployment safety boundaries
|
||||
Run SHALL require HTTPS, a SHA-256 checksum, bounded content length, a safe logical target, and a declared `.dll` path. It SHALL write only managed extension files, retain one previous DLL for rollback, redact sensitive generated configuration, and never execute the DLL, inject a running process, load arbitrary libraries, or expose raw local paths/credentials through Platform-facing results.
|
||||
|
||||
#### Scenario: Invalid or mismatched payload does not activate
|
||||
- **WHEN** download fails, exceeds its byte limit, has a checksum mismatch, or the declared DLL path is unsafe
|
||||
- **THEN** Run keeps the prior managed DLL intact and returns a safe failed start result.
|
||||
|
||||
### Requirement: Run explicitly rejects Linux UE4SS DLL activation
|
||||
Run SHALL reject a `ue4ss-dll` extension plan when its local platform is not Windows amd64. It SHALL not attempt to map the DLL, invoke a shell loader, or substitute `LD_PRELOAD`.
|
||||
|
||||
#### Scenario: Linux extension start fails closed
|
||||
- **WHEN** a Linux Run receives a UE4SS DLL extension plan
|
||||
- **THEN** it returns `unsupported_extension_platform` before any download or process launch.
|
||||
|
||||
### Requirement: Extension synchronization does not block independent channels
|
||||
DLL download and verification SHALL run inside the claimed lifecycle job with bounded context while Run control heartbeat, job acknowledgement/result, cancellation polling, log spool upload, and artifact transfer remain independently scheduled.
|
||||
|
||||
#### Scenario: Slow DLL download preserves control and log traffic
|
||||
- **WHEN** a DLL download is blocked or slow during a start job
|
||||
- **THEN** Run continues its control heartbeat and durable log upload within their configured deadlines.
|
||||
@@ -1,24 +0,0 @@
|
||||
## 1. Plugin and Platform contracts
|
||||
|
||||
- [x] 1.1 Add the typed UE4SS DLL extension declaration to plugin schema, validator, fixtures, and the SCUM manifest with Windows-only compatibility metadata and an inactive unpublished-release guard.
|
||||
- [x] 1.2 Add domain, DTO, validator, and safe API projection types for declared DLL extensions and frozen start-job extension plans.
|
||||
- [x] 1.3 Freeze compatible extension plans into SCUM `process.start` jobs and reject incompatible Linux endpoint plans before Run dispatch.
|
||||
- [x] 1.4 Add focused Platform tests for registration, safe projection, start-job fencing, and unsupported-platform behavior.
|
||||
|
||||
## 2. Management console
|
||||
|
||||
- [x] 2.1 Extend typed frontend API/schema contracts for safe DLL extension declarations.
|
||||
- [x] 2.2 Render the declared Windows-only UE4SS extension and update-on-start policy in existing plugin/server detail surfaces without paths or secrets.
|
||||
- [x] 2.3 Add focused frontend tests for declaration rendering and Linux unsupported state.
|
||||
|
||||
## 3. Independent Run extension synchronization
|
||||
|
||||
- [x] 3.1 Mirror the frozen extension plan in the independent Run protocol and validate bounded, Windows-only DLL fields.
|
||||
- [x] 3.2 Implement scoped staged DLL download, checksum verification, managed-release marker, atomic activation, previous-DLL rollback, generated UE4SS mod configuration, and deterministic mods index update.
|
||||
- [x] 3.3 Gate `process.start` on extension synchronization and fail closed on non-Windows targets, unsafe payloads, or missing UE4SS layout without executing/loading the DLL directly.
|
||||
- [x] 3.4 Add Run unit tests for update/no-op/rollback/Linux rejection and channel independence.
|
||||
|
||||
## 4. Verification and delivery
|
||||
|
||||
- [x] 4.1 Run manifest, Platform, frontend, and Run focused tests; run `openspec validate add-scum-ue4ss-dll-runtime-extension --strict` and `scripts/check-structure.sh`.
|
||||
- [x] 4.2 Review scoped diffs, stage only task files in browser and independent Run repositories, commit, and push both configured branches.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-28
|
||||
@@ -1,3 +0,0 @@
|
||||
# add-scum-versioned-gift-catalog
|
||||
|
||||
SCUM versioned gift catalog and directed delivery
|
||||
@@ -1,47 +0,0 @@
|
||||
## Context
|
||||
|
||||
The SCUM plugin already declares `reward.deliver`, and the prior game-player and player-state work owns server-local identity plus a durable approval/audit pattern. Neither establishes a platform-owned item catalog, immutable gift definition, or a reliable distinction between game delivery and player notification. This change adds those controls without extending browser access to raw game commands or connection material.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Persist server-version-fenced gift catalogs, revisions, and grants in model-first storage with memory/file/MySQL implementations.
|
||||
- Permit only validated item catalog references in a gift revision; freeze the revision contents and game-player identity at grant creation.
|
||||
- Require a platform administrator to approve delivery, dispatch only typed `reward.deliver`, and record delivery and notification outcomes separately.
|
||||
- Give the Chinese SCUM console shared-theme workflows for draft editing, preview, player selection, confirmation, approval, and readable histories.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Commerce, shops, payment, offline inventory/database editing, raw item codes or generator syntax in browser requests, arbitrary RCON text, bulk grants, map trails, auto-retry of unknown delivery, or auto-redelivery after notification failure.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Catalog ownership and version fencing.** Platform defines a small verified SCUM item catalog keyed by exact game version. A revision stores item-catalog keys, labels, quantities, and an item-catalog version; service validation rejects unknown versions, absent items, duplicate lines, and quantities beyond catalog bounds. This is safer than exposing game item IDs in page forms or accepting a client-provided command payload.
|
||||
|
||||
2. **Draft then immutable revision.** A `gift_catalog` carries editable metadata and a draft revision; publishing creates an immutable `gift_revision` with a monotonic revision number. A `gift_grant` copies the selected revision ID plus a deep-frozen item snapshot and game-player record/ID/display-name snapshot. Editing or publishing later revisions therefore cannot change a queued grant.
|
||||
|
||||
3. **Explicit approval and idempotency.** Any server-authorized operator creates a `pending-approval` grant with a required idempotency key. A platform administrator with the same server access revalidates target, revision, version catalog, and online eligibility before dispatch. The grant ID is the bridge idempotency key, and a duplicate create request returns the original grant rather than producing another command.
|
||||
|
||||
4. **Delivery and notification are separate terminal facts.** `reward.deliver` success becomes `delivered`; command failure becomes `failed`; expiry/cancellation/missing result becomes `unknown`. Only after a confirmed delivery does Platform queue the declared targeted notification command. A notification error produces `notification_failed` while preserving the delivery result. No terminal grant, especially `unknown` or `notification_failed`, is automatically retried or redelivered.
|
||||
|
||||
5. **No raw command or secret boundary crossing.** The frontend posts catalog keys, revision IDs, player record IDs, a bounded notice template, and idempotency key only. Platform composes typed bridge payloads from durable records, and browser/API projections omit run credentials, RCON strings, item codes, raw bridge payloads, and host paths.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [A server version has no verified item catalog] → Editing, publication, and grant approval are rejected with an explicit unsupported-version result.
|
||||
- [A selected player is offline] → Grant approval is denied before delivery; the pending record remains auditable and does not dispatch.
|
||||
- [The bridge reports delivery success but notification fails] → Preserve `notification_failed` and do not attempt another item delivery.
|
||||
- [The bridge result is lost] → Persist terminal `unknown`, do not infer success, and require a deliberate later operator workflow rather than automatic retry.
|
||||
- [Two callers repeat a request] → Enforce a server/requester/idempotency-key uniqueness check and reuse the prior grant.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add model-first records and repositories, then wire file/MySQL snapshots with no existing data migration required.
|
||||
2. Deploy typed plugin catalog/delivery/notification schemas and Platform service/API support together; versions without a verified item catalog stay unsupported.
|
||||
3. Deploy the console after APIs are available; hide all raw command details behind the API contracts.
|
||||
4. Roll back by disabling the console/command declarations; immutable revision and grant history remains readable and no automatic replay is performed.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None. The initial SCUM version and item list are deliberately small and can be extended through a future reviewed catalog revision.
|
||||
@@ -1,26 +0,0 @@
|
||||
## Why
|
||||
|
||||
SCUM operators can invoke a one-off reward bridge command but cannot safely curate reusable gifts, freeze what was approved, or establish whether a targeted player received an item and its notification exactly once. A version-fenced gift workflow turns that raw capability into an auditable, least-privilege server-management operation.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add editable SCUM gift catalogs with immutable published revisions and items sourced only from the currently verified server-version item catalog.
|
||||
- Add durable, approval-gated targeted gift grants that freeze the selected revision and game-player identity before dispatching the declared `reward.deliver` command.
|
||||
- Track gift delivery and directed-notification results independently, including visible notification failures and terminal unknown delivery outcomes that are never retried automatically.
|
||||
- Add safe Platform APIs, SCUM plugin schemas, and Chinese console workflows for catalog editing, revision preview, player selection, confirmation, approvals, and grant history.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `scum-versioned-gift-catalog`: Version-scoped SCUM gift definition, immutable revisions, approval-gated directed delivery, and safe operational history.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects Platform domain/model/repository/service/validation/API layers and durable metadata persistence.
|
||||
- Extends the SCUM plugin's typed client-bridge declarations and schemas, plus Platform Web API contracts and SCUM player console.
|
||||
- Does not introduce commerce, direct RCON/game connections, arbitrary item/generator commands, raw game credentials, or raw database writes.
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Version-fenced gift catalog and revisions
|
||||
The system SHALL let authorized SCUM server operators create and edit gift catalog drafts whose items reference only the Platform-verified item catalog for the server's exact game version. Publishing SHALL create an immutable, monotonically versioned revision, and the system MUST reject unknown versions, stale or invalid items, duplicate items, and out-of-range quantities.
|
||||
|
||||
#### Scenario: Publish validated draft
|
||||
- **WHEN** an authorized operator publishes a draft containing only verified items for the current SCUM version
|
||||
- **THEN** the system creates an immutable revision with its frozen item list and exposes it for preview and granting
|
||||
|
||||
#### Scenario: Reject invalid item
|
||||
- **WHEN** a draft references an item absent from the verified item catalog for the selected SCUM version
|
||||
- **THEN** the system rejects the change without creating a publishable revision
|
||||
|
||||
### Requirement: Frozen and idempotent targeted grant
|
||||
The system SHALL create a durable grant from a selected published revision and local game-player record, freezing the revision contents and target identity before approval. A repeated request with the same scoped idempotency key MUST return the original grant and MUST NOT create another delivery command.
|
||||
|
||||
#### Scenario: Later catalog edit does not alter a grant
|
||||
- **WHEN** an operator creates a grant and subsequently edits or publishes the gift catalog
|
||||
- **THEN** the existing grant retains its original revision, item snapshot, and target identity snapshot
|
||||
|
||||
#### Scenario: Duplicate grant request
|
||||
- **WHEN** a requester submits the same target/revision grant request again with the same idempotency key
|
||||
- **THEN** the system returns the original grant and queues no duplicate delivery
|
||||
|
||||
### Requirement: Approved bounded game delivery
|
||||
The system SHALL require a platform administrator with target-server access to approve a pending grant and SHALL dispatch only the declared typed `reward.deliver` bridge command assembled from the frozen grant. Approval MUST reject offline targets, invalidated catalog/revision data, and unauthorized callers.
|
||||
|
||||
#### Scenario: Offline player is not dispatched
|
||||
- **WHEN** a platform administrator attempts to approve a grant for a player not present in the current online-player snapshot
|
||||
- **THEN** approval is rejected and no delivery command is queued
|
||||
|
||||
#### Scenario: Authorized approval queues delivery
|
||||
- **WHEN** a platform administrator approves a valid grant for an online local game player
|
||||
- **THEN** the system records the approver and queues one typed delivery command using the grant identity as its idempotency key
|
||||
|
||||
### Requirement: Delivery and notification lifecycle safety
|
||||
The system SHALL expose queued, delivered, notification_failed, failed, and unknown grant outcomes with readable audit evidence. A succeeded delivery followed by notification failure MUST remain visible as `notification_failed`; unknown delivery outcomes and notification failures MUST NOT automatically retry or redeliver items.
|
||||
|
||||
#### Scenario: Notification failure after delivered item
|
||||
- **WHEN** the delivery command succeeds and the targeted-notification command fails
|
||||
- **THEN** the grant is retained as `notification_failed` with the successful delivery evidence and failed notification evidence
|
||||
|
||||
#### Scenario: Unknown delivery is terminal
|
||||
- **WHEN** a queued delivery command expires, is cancelled, or has no conclusive result
|
||||
- **THEN** the grant becomes `unknown` and the system queues neither a retry nor another item delivery
|
||||
|
||||
### Requirement: Safe console and API projections
|
||||
The system SHALL provide Chinese shared-console workflows for draft/version editing, item preview, local player selection, grant confirmation, approval, and history. Browser requests and responses MUST NOT contain raw game item codes, generator commands, arbitrary RCON text, run credentials, host paths, or direct game connection data.
|
||||
|
||||
#### Scenario: Safe grant submission
|
||||
- **WHEN** an operator confirms a gift grant in the console
|
||||
- **THEN** the browser submits only bounded catalog/revision, player-record, notice, and idempotency references and renders the returned readable lifecycle record
|
||||
@@ -1,21 +0,0 @@
|
||||
## 1. Versioned catalog and grant lifecycle
|
||||
|
||||
- [x] 1.1 Add verified SCUM item catalog, gift catalog/revision/grant domain and model types, repositories, migrations, and memory/file/MySQL persistence.
|
||||
- [x] 1.2 Implement validation and service transitions for editable drafts, immutable revisions, frozen/idempotent grants, server/player ownership, online eligibility, and platform-admin approval/audit.
|
||||
- [x] 1.3 Reconcile typed delivery and targeted notification results without automatic replay; retain queued, delivered, notification_failed, failed, and unknown outcomes.
|
||||
- [x] 1.4 Add backend tests for frozen revisions, item/version validation, duplicate idempotency, offline targets, authorization/approval, notification failure, unknown results, and safe projections.
|
||||
|
||||
## 2. API and plugin contract
|
||||
|
||||
- [x] 2.1 Add named safe DTOs, authorized handlers/routes, and API tests for catalogs, revisions, grants, approval, and histories.
|
||||
- [x] 2.2 Add SCUM item-catalog, reward-delivery, and targeted-notification typed bridge schemas/declarations and plugin validation tests.
|
||||
|
||||
## 3. SCUM console
|
||||
|
||||
- [x] 3.1 Add typed frontend API/contracts and shared-console Chinese catalog, revision preview, player selection, confirmation, approval, and history workflows.
|
||||
- [x] 3.2 Add frontend tests for readable status/result rendering and absence of raw command/item/credential leakage.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run strict OpenSpec validation, focused backend, plugin, and frontend test suites, plus `scripts/check-structure.sh`.
|
||||
- [x] 4.2 Stage only this task's files, commit on `main`, and push the configured remote.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-08-04
|
||||
@@ -1,33 +0,0 @@
|
||||
## Context
|
||||
|
||||
Server deletion is currently a password-confirmed soft delete, but active states (`running` and `installing`) are always rejected. That protects against orphaning live runtime work, but it also traps operators when the platform state is stale, the run endpoint is gone, or a lifecycle job cannot complete.
|
||||
|
||||
The platform/run boundary matters here: platform can mark metadata deleted, but it must not invent game-specific stop behavior or directly manage host processes outside plugin-owned lifecycle jobs.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Let an owner or platform administrator force-delete a running or installing instance when they explicitly accept the operational risk.
|
||||
- Keep password confirmation mandatory for normal and forced deletion.
|
||||
- Preserve soft-delete history and current list filtering behavior.
|
||||
- Make forced deletion visible and deliberate in the UI.
|
||||
|
||||
**Non-Goals:**
|
||||
- Hard-deleting server metadata or historical records.
|
||||
- Killing, stopping, or cleaning up a remote process as part of delete.
|
||||
- Adding run-side force-kill behavior, game-specific cleanup, or deployment target changes.
|
||||
- Allowing non-owners or non-admins to delete servers.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Extend the existing `DELETE /api/v1/server-instances/{id}` JSON body with `force` and `confirmation` fields. The existing route keeps one destructive API surface, while older clients still get the default safe rejection for running/installing instances.
|
||||
- Require `force: true` plus a fixed confirmation phrase for running or installing instances. This separates accidental password-only deletion from intentional cleanup of stuck active instances.
|
||||
- Keep backend enforcement in `DeleteServerInstanceForSession`. The frontend can guide the operator, but the service must remain the source of truth.
|
||||
- Treat forced deletion as metadata-only. The server state becomes `deleted`; run jobs, logs, artifacts, and audit history remain visible through existing historical paths where supported.
|
||||
- Show force confirmation only when the selected instance is running or installing, and keep the delete entry in the existing compact server-card action menu.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] A forced delete can hide a server whose process is still alive. -> Mitigation: confirmation copy states that delete is metadata-only and does not stop the process.
|
||||
- [Risk] Operators may use force instead of stopping cleanly. -> Mitigation: normal delete remains the default for stopped/ready/failed servers; active states require explicit force confirmation.
|
||||
- [Risk] Existing clients may omit the new fields. -> Mitigation: the backend keeps the current rejection unless force confirmation is present.
|
||||
@@ -1,24 +0,0 @@
|
||||
## Why
|
||||
|
||||
Operators need a way to remove server instances that are stuck in `running` or `installing` state when the runtime can no longer be stopped cleanly. The current delete safety rule blocks those instances forever, which leaves stale servers in the active management console.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add an explicit forced delete path to the existing server deletion flow.
|
||||
- Preserve owner/platform-admin authorization and current-password confirmation for all server deletion.
|
||||
- Require an additional force confirmation when deleting a running or installing instance.
|
||||
- Keep deletion as a soft delete that marks the server instance `deleted` and preserves history.
|
||||
- Make the UI expose forced deletion only through the existing destructive password confirmation dialog.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `server-deletion`: server instance soft deletion, including authorization, password confirmation, and explicit forced deletion of active/stuck instances.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
## Impact
|
||||
|
||||
- `platform/` delete DTO, API handler docs, service validation, and tests.
|
||||
- `platform_web/` delete request types, client-side delete dialog, error/confirmation copy, and tests.
|
||||
- No changes to run executor ownership, plugin lifecycle execution, or hard-delete persistence.
|
||||
@@ -1,49 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Authorized server deletion
|
||||
The system SHALL allow a server instance to be deleted only when the authenticated user is the instance owner or a platform administrator.
|
||||
|
||||
#### Scenario: Owner deletes a server
|
||||
- **WHEN** the instance owner submits a delete request for their server
|
||||
- **THEN** the system SHALL accept the request if all other delete checks pass
|
||||
|
||||
#### Scenario: Non-owner cannot delete
|
||||
- **WHEN** an authenticated user who is neither the owner nor a platform administrator submits a delete request
|
||||
- **THEN** the system SHALL reject the request with forbidden access
|
||||
|
||||
### Requirement: Password confirmation for deletion
|
||||
The system SHALL require the authenticated user to provide their current account password with every server delete request and SHALL reject the request if the password is missing or does not match the current session user.
|
||||
|
||||
#### Scenario: Password mismatch
|
||||
- **WHEN** the authenticated user submits the delete request with an incorrect password
|
||||
- **THEN** the system SHALL reject the request with forbidden access
|
||||
|
||||
#### Scenario: Password required
|
||||
- **WHEN** the authenticated user submits the delete request without a password
|
||||
- **THEN** the system SHALL reject the request as invalid input or forbidden access
|
||||
|
||||
### Requirement: Forced active server deletion
|
||||
The system SHALL reject deletion for a running or installing server instance by default, but SHALL allow the same soft deletion when the authenticated owner or platform administrator also submits an explicit forced-delete confirmation.
|
||||
|
||||
#### Scenario: Running server delete without force is rejected
|
||||
- **WHEN** a delete request targets a running server instance without forced-delete confirmation
|
||||
- **THEN** the system SHALL reject the request and keep the server instance intact
|
||||
|
||||
#### Scenario: Installing server delete without force is rejected
|
||||
- **WHEN** a delete request targets an installing server instance without forced-delete confirmation
|
||||
- **THEN** the system SHALL reject the request and keep the server instance intact
|
||||
|
||||
#### Scenario: Running server force delete marks deleted state
|
||||
- **WHEN** a valid delete request targets a running server instance with forced-delete confirmation
|
||||
- **THEN** the system SHALL mark the server instance as deleted while preserving historical records
|
||||
|
||||
#### Scenario: Installing server force delete marks deleted state
|
||||
- **WHEN** a valid delete request targets an installing server instance with forced-delete confirmation
|
||||
- **THEN** the system SHALL mark the server instance as deleted while preserving historical records
|
||||
|
||||
### Requirement: Soft server removal state
|
||||
The system SHALL mark deleted server instances with the deleted state and preserve historical records rather than hard-deleting metadata.
|
||||
|
||||
#### Scenario: Successful deletion marks deleted state
|
||||
- **WHEN** a valid delete request targets a stopped, ready, failed, or force-confirmed active server instance
|
||||
- **THEN** the system SHALL mark the server instance as deleted and preserve history
|
||||
@@ -1,15 +0,0 @@
|
||||
## 1. Backend Force Delete
|
||||
|
||||
- [x] 1.1 Add force-delete fields to server deletion DTO/domain request and route handling.
|
||||
- [x] 1.2 Update service deletion validation so running/installing servers require explicit force confirmation.
|
||||
- [x] 1.3 Add backend service/API tests for forced running and installing deletion plus default rejection.
|
||||
|
||||
## 2. Frontend Confirmation
|
||||
|
||||
- [x] 2.1 Extend the server deletion request type and API usage with force confirmation fields.
|
||||
- [x] 2.2 Update the server list delete dialog to show active-state force warning and confirmation input.
|
||||
- [x] 2.3 Update frontend tests for forced delete payloads and copy.
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Run OpenSpec strict validation, structure check, and focused backend/frontend tests.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -1,55 +0,0 @@
|
||||
# Next Architecture Stream Action
|
||||
|
||||
## Current Guard
|
||||
|
||||
- No active guard.
|
||||
- `fix-env-profile-settings` task `3.5` is complete.
|
||||
- `implement-browser-acceptance-suite` is complete.
|
||||
- `polish-platform-interaction-design` is complete with desktop/mobile browser walkthrough evidence, black mecha and magical-girl theme evidence, automated browser acceptance evidence, frontend verification, structure verification, and strict OpenSpec validation.
|
||||
|
||||
## Current Change To Implement
|
||||
|
||||
- None. The current delivery stream has no active implementation target.
|
||||
|
||||
## Latest Completed Change
|
||||
|
||||
- Change name: `polish-platform-interaction-design`
|
||||
- Status: complete.
|
||||
- Primary roots: `platform_web/`
|
||||
- Completion evidence:
|
||||
- `LOCAL_DEBUG_PLATFORM_PORT=18189 LOCAL_DEBUG_WEB_PORT=5183 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-acceptance scripts/browser-acceptance.sh`
|
||||
- Evidence file: `/private/tmp/browser-local-debug-acceptance/browser-acceptance/browser-acceptance-evidence.json`
|
||||
- `cd platform_web && npm run typecheck`
|
||||
- `cd platform_web && npm test`
|
||||
- `cd platform_web && npm run build`
|
||||
- `scripts/check-structure.sh`
|
||||
- `openspec validate polish-platform-interaction-design --strict`
|
||||
|
||||
## Recommended Next Action
|
||||
|
||||
No further concrete backlog item is defined in the current delivery stream. The next stream step should be one of:
|
||||
|
||||
1. Archive completed OpenSpec changes, starting with `polish-platform-interaction-design`, if the user wants to finalize the completed stream state.
|
||||
2. Create exactly one new OpenSpec change from fresh product/design feedback, if the user provides or approves a new concrete backlog item.
|
||||
|
||||
## Prompt For The Next Chat
|
||||
|
||||
```text
|
||||
Continue the architecture delivery stream in /Users/tasia/Desktop/code/browser.
|
||||
|
||||
Read first:
|
||||
- AGENTS.md
|
||||
- openspec/changes/architecture-delivery-stream/delivery-plan.md
|
||||
- openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md
|
||||
|
||||
Task:
|
||||
- Confirm there is no active guard and no active implementation target.
|
||||
- If asked to finalize completed work, archive completed OpenSpec changes according to the archive workflow.
|
||||
- If asked to continue product work, create exactly one new OpenSpec change from fresh approved feedback before implementing anything.
|
||||
- Run the required OpenSpec validation for any change you create or archive.
|
||||
- Update delivery-plan.md and NEXT_CHANGE.md after the stream action.
|
||||
```
|
||||
|
||||
## Stop Condition
|
||||
|
||||
Stop after archiving completed work or preparing exactly one new approved OpenSpec change, unless the user explicitly asks to keep going.
|
||||
@@ -1,123 +0,0 @@
|
||||
# Architecture Delivery Stream
|
||||
|
||||
This file is the working progress record for the architecture stream. It is intentionally stored with the OpenSpec change so a new chat can read the current queue before creating or implementing the next change.
|
||||
|
||||
## Status Legend
|
||||
|
||||
- `complete`: tasks and verification evidence exist.
|
||||
- `active`: current implementation target.
|
||||
- `guard`: current blocker that must be closed or explicitly reprioritized before generating the next concrete OpenSpec.
|
||||
- `pending`: planned but not active.
|
||||
- `paused`: intentionally deferred by the user.
|
||||
- `blocked`: cannot proceed without a user decision or external state change.
|
||||
|
||||
## Current Guard
|
||||
|
||||
No active guard. `fix-env-profile-settings` task `3.5` was completed on 2026-07-08 with an API-backed browser walkthrough for the personal settings page, and `scripts/check-structure.sh` plus `openspec validate fix-env-profile-settings --strict` passed.
|
||||
|
||||
## Queue
|
||||
|
||||
| Order | Status | Change | Primary Roots | Completion Gate |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 0 | complete | `bootstrap-game-server-platform-architecture` | all | `scripts/check-structure.sh`; `openspec validate bootstrap-game-server-platform-architecture --strict`. |
|
||||
| 1 | complete | `establish-development-runtime-baseline` | all | `scripts/check-all.sh`; `scripts/check-structure.sh`; `openspec validate establish-development-runtime-baseline --strict`; browser walkthrough. |
|
||||
| 2 | complete | `implement-platform-core-domain` | `platform/` | Platform domain unit tests and strict validation. |
|
||||
| 3 | complete | `implement-platform-api-surface` | `platform/` | API handler tests, validation tests, strict validation. |
|
||||
| 4 | complete | `implement-ai-provider-management` | `platform/`, `platform_web/` | Secret redaction tests, API tests, browser walkthrough, strict validation. |
|
||||
| 5 | complete | `implement-run-control-registration` | `run/`, `platform/` | Control protocol tests, registration integration test, strict validation. |
|
||||
| 6 | complete | `implement-run-job-channel` | `run/`, `platform/` | Job lifecycle tests, journal/idempotency tests, strict validation. |
|
||||
| 7 | complete | `implement-log-ingest-pipeline` | `run/`, `platform/` | Spool retry tests, batch ack tests, query tests, strict validation. |
|
||||
| 8 | complete | `implement-artifact-transfer-channel` | `run/`, `platform/` | Chunk/resume/checksum tests, priority isolation tests, strict validation. |
|
||||
| 9 | complete | `implement-plugin-registry-and-manifest-validation` | `plugins/`, `platform/` | Schema validation tests, registry API tests, strict validation. |
|
||||
| 10 | complete | `implement-plugin-bridge-and-sdk` | `plugins/`, `platform_web/`, `platform/` | Bridge permission tests, SDK type checks, strict validation. |
|
||||
| 11 | complete | `implement-platform-web-console-shell` | `platform_web/` | Frontend build, route/page tests, browser walkthrough, strict validation. |
|
||||
| 12 | complete | `implement-server-management-workflows` | all | Create/start/stop workflow tests, browser walkthrough, strict validation. |
|
||||
| 13 | complete | `redesign-platform-web-interactions` | `platform_web/` | Frontend tests/build, browser walkthrough, strict validation. |
|
||||
| 14 | complete | `fix-platform-auth-session-api` | `platform/`, `platform_web/` | Auth/session API tests, frontend auth flow tests, strict validation. |
|
||||
| 15 | complete | `implement-role-scoped-server-access` | `platform/`, `platform_web/` | Role access tests, UI visibility tests, strict validation. |
|
||||
| 16 | complete | `implement-platform-observability-and-config-read` | `platform/`, `run/`, `platform_web/` | Observability/config read tests, browser walkthrough, strict validation. |
|
||||
| 17 | complete | `implement-plugin-marketplace-api-driven-ui` | `platform/`, `platform_web/`, `plugins/` | Marketplace API tests, frontend tests/build, browser walkthrough, strict validation. |
|
||||
| 18 | complete | `implement-config-write-and-file-dispatch` | `platform/`, `run/`, `platform_web/`, `plugins/` | Config diff/write tests, file dispatch tests, browser walkthrough, strict validation. |
|
||||
| 19 | complete | `implement-run-worker-real-execution` | `run/`, `platform/` | Real worker lifecycle tests, job result tests, strict validation. |
|
||||
| 20 | complete | `implement-plugin-page-bridge-execution` | `platform_web/`, `plugins/`, `platform/` | Plugin page bridge tests, permission tests, strict validation. |
|
||||
| 21 | complete | `implement-platform-mediated-ai-invocation` | `platform/`, `platform_web/`, `plugins/` | AI invocation tests, key redaction tests, reviewable diff tests, strict validation. |
|
||||
| 22 | complete | `implement-artifact-download-and-browser-transfer` | `platform/`, `run/`, `platform_web/` | Artifact download/transfer tests, browser download walkthrough, strict validation. |
|
||||
| 23 | complete | `sync-implemented-docs-and-comments` | all | Documentation/comment sync checks and strict validation. |
|
||||
| 24 | complete | `implement-durable-platform-storage` | `platform/` | Durable repository tests and strict validation. |
|
||||
| 25 | complete | `add-local-docker-deployment` | all | Local docker smoke path and strict validation. |
|
||||
| 26 | complete | `add-mysql-platform-metadata-storage` | `platform/`, deployment | MySQL metadata tests and strict validation. |
|
||||
| 27 | complete | `fix-env-profile-settings` | `platform/`, `platform_web/` | Browser walkthrough task `3.5`; `scripts/check-structure.sh`; `openspec validate fix-env-profile-settings --strict`. |
|
||||
| 28 | complete | `verify-current-platform-e2e-baseline` | all | Browser walkthrough and API/run/plugin proof report that classifies every required first-party flow as real, partial, demo-only, or blocked. |
|
||||
| 29 | complete | `implement-real-game-plugin-lifecycle-proof` | `plugins/`, `platform/`, `platform_web/`, `run/` | Plugin/SDK tests, platform lifecycle tests, run lifecycle tests, platform_web tests/build, API-backed browser walkthrough, `scripts/check-structure.sh`, and `openspec validate implement-real-game-plugin-lifecycle-proof --strict`. |
|
||||
| 30 | complete | `harden-log-artifact-channel-isolation` | `run/`, `platform/` | Run/platform channel isolation tests, protocol docs, `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1`, `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1`, `scripts/check-structure.sh`, and `openspec validate harden-log-artifact-channel-isolation --strict`. |
|
||||
| 31 | complete | `implement-local-debug-workspace` | all | Local debug docs/scripts, self-start smoke, browser walkthrough, frontend/plugin/platform/run checks, `scripts/check-structure.sh`, and `openspec validate implement-local-debug-workspace --strict`. |
|
||||
| 32 | complete | `implement-browser-acceptance-suite` | `platform_web/`, all | Automated browser acceptance command, API-backed first-party route proof, plugin/server operation proof, frontend/plugin/platform/run checks, `scripts/check-structure.sh`, and `openspec validate implement-browser-acceptance-suite --strict`. |
|
||||
| 33 | complete | `polish-platform-interaction-design` | `platform_web/` | Interaction/design polish criteria, desktop/mobile browser walkthroughs, automated browser acceptance, platform_web tests/build, `scripts/check-structure.sh`, and `openspec validate polish-platform-interaction-design --strict`. |
|
||||
|
||||
## Next Pointer
|
||||
|
||||
Read `openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md` before starting a fresh architecture-stream chat. That file contains the exact next action and prompt.
|
||||
|
||||
## Generator Handoff Template
|
||||
|
||||
Use this template when starting a fresh chat whose job is to create the next OpenSpec only:
|
||||
|
||||
```text
|
||||
Continue the architecture delivery stream in /Users/tasia/Desktop/code/browser.
|
||||
|
||||
Read first:
|
||||
- AGENTS.md
|
||||
- openspec/changes/architecture-delivery-stream/delivery-plan.md
|
||||
- openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md
|
||||
|
||||
Task:
|
||||
- Follow NEXT_CHANGE.md exactly.
|
||||
- If the current guard is still open, close or explicitly record the blocker first.
|
||||
- Create exactly one new OpenSpec change.
|
||||
- Generate proposal.md, design.md, specs/**/*.md, and tasks.md for that one change.
|
||||
- Run openspec validate <new-change> --strict.
|
||||
- Update NEXT_CHANGE.md to point at implementing the new change.
|
||||
- Stop after the one new OpenSpec is ready; do not implement it in this chat unless explicitly asked.
|
||||
```
|
||||
|
||||
## Implementation Handoff Template
|
||||
|
||||
Use this template when starting a fresh implementation chat for a concrete change:
|
||||
|
||||
```text
|
||||
Implement OpenSpec change: <change-name>
|
||||
|
||||
Scope:
|
||||
- Implement only openspec/changes/<change-name>/.
|
||||
- Preserve root ownership boundaries in AGENTS.md.
|
||||
- Do not add billing, cloud host sales, agent-provider/cloud-provider workflows, or unrelated marketplace features.
|
||||
- Do not let browser or game management plugins access run directly; route plugin capabilities through platform-mediated contracts.
|
||||
- Keep log ingest durable and independent from control, job result, and artifact/file transfer channels.
|
||||
|
||||
Read first:
|
||||
- AGENTS.md
|
||||
- openspec/changes/architecture-delivery-stream/delivery-plan.md
|
||||
- openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md
|
||||
- openspec/changes/bootstrap-game-server-platform-architecture/proposal.md
|
||||
- openspec/changes/bootstrap-game-server-platform-architecture/design.md
|
||||
- openspec/changes/<change-name>/proposal.md
|
||||
- openspec/changes/<change-name>/design.md
|
||||
- openspec/changes/<change-name>/tasks.md
|
||||
|
||||
Required closure:
|
||||
- Complete the tasks in openspec/changes/<change-name>/tasks.md only after evidence exists.
|
||||
- Run scripts/check-structure.sh.
|
||||
- Run openspec validate <change-name> --strict.
|
||||
- Run all change-specific test/build/walkthrough commands listed in the task file.
|
||||
- If frontend pages are touched, complete a browser walkthrough before claiming acceptance.
|
||||
- Update delivery-plan.md and NEXT_CHANGE.md before closing.
|
||||
- Stop after this change is closed; do not start the next backlog item in the same chat unless explicitly asked.
|
||||
```
|
||||
|
||||
## Progress Rules
|
||||
|
||||
1. Resolve the current guard before generating a new concrete product OpenSpec unless the user explicitly reprioritizes.
|
||||
2. Create or implement only one concrete OpenSpec by default.
|
||||
3. If implementation reveals that a pending item is too large, split it before writing product code.
|
||||
4. Update this progress file and `NEXT_CHANGE.md` through an OpenSpec change when the queue order, active item, or completion gates materially change.
|
||||
5. Keep final answers from implementation chats focused on changed files, verification evidence, and the next suggested backlog item.
|
||||
@@ -1,94 +0,0 @@
|
||||
## Context
|
||||
|
||||
`bootstrap-game-server-platform-architecture` established the repository roots, ownership boundaries, and architecture contracts, but it intentionally did not build the full platform. The remaining work touches all four roots and needs to be delivered as a sequence of small OpenSpec changes so each implementation chat has a narrow scope, concrete verification commands, and clear handoff to the next change.
|
||||
|
||||
The delivery stream is a process and governance layer. It does not replace the bootstrap specs. Each follow-up change must treat the bootstrap change and any archived specs as the baseline.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Define one ordered backlog for the architecture implementation.
|
||||
- Keep each OpenSpec change small enough for one focused implementation chat.
|
||||
- Require a standard handoff block for every concrete change so the user can open a new chat and paste a precise implementation prompt.
|
||||
- Require closing evidence before the next OpenSpec is created or implemented.
|
||||
- Cover `platform/`, `run/`, `platform_web/`, and `plugins/` without mixing ownership boundaries.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Do not add billing, cloud host sales, provider marketplace, or agent-provider workflows.
|
||||
- Do not implement product code inside this stream change.
|
||||
- Do not require automated creation or closing of chats; chat boundaries are user-operated.
|
||||
- Do not redefine product scope already covered by the bootstrap architecture.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Use a serial backlog, not parallel feature branches
|
||||
|
||||
Only one concrete implementation OpenSpec should be active at a time unless the user explicitly pauses or reprioritizes the stream. This keeps validation evidence simple and prevents later changes from depending on unverified assumptions.
|
||||
|
||||
Alternative considered: create all detailed OpenSpecs at once. Rejected because later specs would likely become stale after the first implementation changes discover concrete package, runtime, and data model constraints.
|
||||
|
||||
### Decision 2: Start with development runtime baseline
|
||||
|
||||
The first concrete implementation change is `establish-development-runtime-baseline`. It defines the executable skeleton, package managers, local commands, and test/verification entry points before any business capability is implemented.
|
||||
|
||||
Alternative considered: start with platform domain APIs. Rejected because there is not yet a runnable backend or frontend baseline to attach tests and browser walkthroughs to.
|
||||
|
||||
### Decision 3: Split the stream by dependency, not by team label
|
||||
|
||||
Backlog items may touch multiple roots when the contract is cross-cutting, but each item must name its primary root ownership and forbid casual cross-root imports. Shared contracts must be generated, copied through explicit contract packages, or duplicated as documented API contracts until generation exists.
|
||||
|
||||
Alternative considered: one backlog per root. Rejected because platform-run protocols, plugin bridge contracts, and frontend API clients require coordinated changes.
|
||||
|
||||
### Decision 4: Every concrete change gets a handoff prompt
|
||||
|
||||
Each concrete OpenSpec must end with a short implementation handoff containing the change name, exact target, required reads, verification commands, and stopping conditions. The prompt is the practical bridge between chats.
|
||||
|
||||
Alternative considered: rely on OpenSpec files alone. Rejected because a new chat needs a compact instruction that prevents it from reopening already-settled scope.
|
||||
|
||||
### Decision 5: Closing evidence gates progression
|
||||
|
||||
A change is not considered closed until its tasks are checked with evidence. The minimum evidence is `scripts/check-structure.sh` plus `openspec validate <change> --strict`; frontend page changes also require a browser walkthrough, and executable code changes require the relevant tests/builds documented by that change.
|
||||
|
||||
Alternative considered: create the next change after implementation edits are made. Rejected because unverified work compounds defects into downstream specs.
|
||||
|
||||
## Initial Delivery Queue
|
||||
|
||||
| Order | Change | Primary Roots | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| 0 | `bootstrap-game-server-platform-architecture` | all | Completed architecture baseline and repository skeleton. |
|
||||
| 1 | `establish-development-runtime-baseline` | all | Add runnable project/tooling baselines and common verification commands. |
|
||||
| 2 | `implement-platform-core-domain` | `platform/` | Add core domain, DTO, model, repository, service, validator, and route contracts for users, plugins, server instances, AI providers, jobs, artifacts, logs, and audit. |
|
||||
| 3 | `implement-platform-api-surface` | `platform/` | Add HTTP API handlers, validation, error envelopes, and initial persistence wiring for the core resources. |
|
||||
| 4 | `implement-ai-provider-management` | `platform/`, `platform_web/` | Store AI provider metadata safely, redact secrets, and expose first-party management APIs and UI. |
|
||||
| 5 | `implement-run-control-registration` | `run/`, `platform/` | Add run hello, heartbeat, capability, version, and capacity registration. |
|
||||
| 6 | `implement-run-job-channel` | `run/`, `platform/` | Add job claim, ack, progress, result, cancel, reconcile, and idempotent local journal behavior. |
|
||||
| 7 | `implement-log-ingest-pipeline` | `run/`, `platform/` | Add local spool, compressed batch upload, sequence ack, retry, and platform log query metadata. |
|
||||
| 8 | `implement-artifact-transfer-channel` | `run/`, `platform/` | Add chunked, resumable, checksummed, throttled artifact upload/download. |
|
||||
| 9 | `implement-plugin-registry-and-manifest-validation` | `plugins/`, `platform/` | Validate plugin manifests, register installed game management plugins, and expose marketplace metadata. |
|
||||
| 10 | `implement-plugin-bridge-and-sdk` | `plugins/`, `platform_web/`, `platform/` | Add safe plugin page bridge, SDK types, scoped platform abilities, and no raw key/run/path exposure. |
|
||||
| 11 | `implement-platform-web-console-shell` | `platform_web/` | Add frontend app shell, routes, API client structure, theme tokens, and required first-party pages. |
|
||||
| 12 | `implement-server-management-workflows` | all | Create server instances from plugins, dispatch lifecycle jobs to run, and show job/log/artifact state. |
|
||||
| 13 | `implement-dev-game-plugin-proof` | `plugins/`, all | Add one development game management plugin proving multi-instance creation, logs, files, jobs, and AI assistance. |
|
||||
| 14 | `implement-end-to-end-acceptance-suite` | all | Add cross-root acceptance checks and browser walkthrough coverage for the first complete workflow. |
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] The backlog may need to change after tooling decisions are implemented. Mitigation: update this stream through a new OpenSpec change if ordering or scope materially changes.
|
||||
- [Risk] A change may grow too large for one chat. Mitigation: split it before implementation and keep the original change as a coordination parent only if needed.
|
||||
- [Risk] Generated contracts may not exist early. Mitigation: use explicit copied contract files with documented ownership until generation is introduced by its own OpenSpec.
|
||||
- [Risk] Chat handoff can omit important context. Mitigation: require each handoff to name exact files to read and exact commands to run.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Validate this stream change and use it as the current implementation queue.
|
||||
2. Create `establish-development-runtime-baseline` as the first concrete OpenSpec.
|
||||
3. In a new chat, implement only that change, run its verification, and check its tasks with evidence.
|
||||
4. After closure, create or refine the next concrete OpenSpec from the queue.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Whether the initial persistence backend should be SQLite-first for local development or Postgres-first for production parity remains for the platform API changes.
|
||||
- Whether log body storage starts as local compressed segments or a query engine adapter remains for the log ingest change.
|
||||
- Whether run job transport starts as long polling or streaming remains for the run job channel change.
|
||||
@@ -1,26 +0,0 @@
|
||||
## Why
|
||||
|
||||
The bootstrap architecture is broad enough that implementing it as one large change would make review, verification, and rollback hard. The project needs an explicit OpenSpec delivery stream that breaks the platform, run executor, frontend console, and plugin system into ordered, single-session changes that can be implemented one at a time.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a delivery workflow for creating and implementing architecture OpenSpec changes in dependency order.
|
||||
- Define a per-change handoff format so each new chat can implement exactly one OpenSpec change without guessing scope.
|
||||
- Define closing criteria for each implementation chat before the next OpenSpec change is started.
|
||||
- Define the initial architecture backlog across `platform/`, `run/`, `platform_web/`, and `plugins/`.
|
||||
- Keep the bootstrap architecture as the baseline and require every follow-up change to reference it instead of redefining product scope.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `architecture-delivery-workflow`: Ordered OpenSpec backlog, per-change handoff rules, implementation-chat closure criteria, and progress tracking for the full architecture delivery stream.
|
||||
|
||||
### Modified Capabilities
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Adds planning artifacts under `openspec/changes/architecture-delivery-stream/`.
|
||||
- Affects how future OpenSpec changes are created, implemented, validated, and handed off between chats.
|
||||
- Does not implement backend, run, frontend, or plugin runtime code directly.
|
||||
- Requires future implementation chats to run `scripts/check-structure.sh` and `openspec validate <change> --strict` before marking work complete.
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Ordered Architecture Backlog
|
||||
The repository SHALL maintain an ordered architecture delivery backlog that maps each future OpenSpec change to its primary roots, purpose, dependencies, and verification expectations.
|
||||
|
||||
#### Scenario: Backlog lists the next architecture change
|
||||
- **WHEN** a contributor needs the next implementation target
|
||||
- **THEN** the backlog identifies the next change name, affected roots, and why it follows the previous change
|
||||
|
||||
#### Scenario: Backlog preserves bootstrap as baseline
|
||||
- **WHEN** a follow-up change is planned
|
||||
- **THEN** it references `bootstrap-game-server-platform-architecture` or archived baseline specs instead of redefining the product scope
|
||||
|
||||
### Requirement: Single Active Implementation Change
|
||||
The delivery workflow SHALL keep only one concrete implementation OpenSpec active at a time unless the user explicitly requests a pause, reprioritization, or parallel track.
|
||||
|
||||
#### Scenario: Previous change is not closed
|
||||
- **WHEN** the current implementation change has unchecked tasks or missing verification evidence
|
||||
- **THEN** the next concrete implementation change is not started as active work
|
||||
|
||||
#### Scenario: User requests a reprioritization
|
||||
- **WHEN** the user explicitly changes the implementation order
|
||||
- **THEN** the backlog is updated or superseded before the new active change is implemented
|
||||
|
||||
### Requirement: Per-Change Handoff
|
||||
Each concrete implementation OpenSpec SHALL include a handoff block suitable for a fresh chat, containing the change name, implementation objective, required context files, expected verification commands, and stopping conditions.
|
||||
|
||||
#### Scenario: New chat starts implementation
|
||||
- **WHEN** the user opens a fresh chat for a concrete change
|
||||
- **THEN** the handoff block gives enough context to implement that change without expanding scope to unrelated backlog items
|
||||
|
||||
#### Scenario: Handoff references verification
|
||||
- **WHEN** the handoff is prepared
|
||||
- **THEN** it includes `scripts/check-structure.sh`, `openspec validate <change> --strict`, and any change-specific build, test, or browser walkthrough commands
|
||||
|
||||
### Requirement: Closure Evidence
|
||||
Implementation tasks SHALL remain unchecked until the implementing chat records verification evidence for the task or group of tasks.
|
||||
|
||||
#### Scenario: Task is completed
|
||||
- **WHEN** a task checkbox is marked complete
|
||||
- **THEN** the change records the command, walkthrough, file reference, or artifact that proves the task is complete
|
||||
|
||||
#### Scenario: Verification fails
|
||||
- **WHEN** a required verification command fails
|
||||
- **THEN** the implementation chat fixes the issue or records the blocker before the change is considered closed
|
||||
|
||||
### Requirement: Ownership Boundaries
|
||||
Each concrete change SHALL name its affected project roots and preserve root ownership boundaries from `AGENTS.md`.
|
||||
|
||||
#### Scenario: Change touches multiple roots
|
||||
- **WHEN** a change updates more than one of `platform/`, `run/`, `platform_web/`, and `plugins/`
|
||||
- **THEN** the OpenSpec design explains the contract boundary and avoids casual cross-root imports
|
||||
|
||||
#### Scenario: Shared contracts are needed
|
||||
- **WHEN** two roots need the same request, response, or protocol shape
|
||||
- **THEN** the change uses an explicit contract file, generated artifact, or documented copy boundary rather than importing implementation code across roots
|
||||
|
||||
### Requirement: Progress Tracking
|
||||
The delivery workflow SHALL maintain a progress record for the architecture stream that shows completed, active, pending, paused, and blocked changes.
|
||||
|
||||
#### Scenario: Active change completes
|
||||
- **WHEN** a concrete implementation change is closed
|
||||
- **THEN** the progress record marks it complete with verification evidence and identifies the next pending change
|
||||
|
||||
#### Scenario: Change is split
|
||||
- **WHEN** a backlog item is too large for one implementation chat
|
||||
- **THEN** the progress record replaces it with smaller ordered changes and records the reason for the split
|
||||
@@ -1,27 +0,0 @@
|
||||
## 1. Stream Artifacts
|
||||
|
||||
- [x] 1.1 Create the architecture delivery stream proposal.
|
||||
- [x] 1.2 Create the delivery stream design with ordered backlog decisions.
|
||||
- [x] 1.3 Create the delivery workflow spec with backlog, handoff, closure, ownership, and progress requirements.
|
||||
- [x] 1.4 Create the delivery progress record with queue status and handoff template.
|
||||
|
||||
## 2. First Concrete Change
|
||||
|
||||
- [x] 2.1 Create the `establish-development-runtime-baseline` OpenSpec change.
|
||||
- [x] 2.2 Add proposal, design, specs, and tasks for the runtime baseline change.
|
||||
- [x] 2.3 Add a fresh-chat handoff block to the runtime baseline tasks.
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Run `scripts/check-structure.sh`.
|
||||
- [x] 3.2 Run `openspec validate architecture-delivery-stream --strict`.
|
||||
- [x] 3.3 Run `openspec validate establish-development-runtime-baseline --strict`.
|
||||
- [x] 3.4 Confirm OpenSpec status shows both changes have required artifacts present.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `scripts/check-structure.sh`: passed.
|
||||
- `openspec validate architecture-delivery-stream --strict`: passed.
|
||||
- `openspec validate establish-development-runtime-baseline --strict`: passed.
|
||||
- `openspec status --change architecture-delivery-stream --json`: proposal, design, specs, and tasks present.
|
||||
- `openspec status --change establish-development-runtime-baseline --json`: proposal, design, specs, and tasks present.
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-30
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
## Context
|
||||
|
||||
Two independently reasonable decisions currently deadlock the build path.
|
||||
|
||||
`platform/service/job_channel.go` strips `distribution.build` from any component-authenticated session, so a generated run cannot claim build work. `platform/service/distributions.go` derives `generate-run` availability from `svc.endpointSupports(endpoint, domain.JobCapabilityDistributionBuild)`, falling back to `run endpoint cannot build distributions`. An instance bound to its own generated run therefore fails the availability check permanently.
|
||||
|
||||
`platform/service/distributions.go` picks the builder endpoint as `instance.DeploymentTargetID` when set, otherwise `instance.RunEndpointID`. Both resolve to machine-side endpoints, so building depends on a hand-maintained privileged worker being registered and online.
|
||||
|
||||
`platform/service/distribution_build_jobs.go` decrypts the component key and returns `AuthKey` in `DistributionBuildInput`. Any endpoint claiming a build job receives that plaintext credential.
|
||||
|
||||
`platform/validator/server_lifecycle.go` does not require a deployment target; it only requires `profileKey` when `runEndpointId` is supplied. The creation-time requirement is imposed by `platform_web/components/ServerDeploymentWorkflow.tsx`.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
Goals: make build execution a platform responsibility with no dependency on machine-side endpoint state; reduce server creation to plugin type and server name; keep the generated-run build restriction as a security boundary; stop shipping plaintext auth keys to machine-side endpoints for builds.
|
||||
|
||||
Non-goals: changing the channel model for control/jobs/logs/artifacts; changing how a registered run executes game lifecycle work; adding billing, cloud host sales, or provider workflows; removing deployment target selection from post-creation instance management.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Platform-owned Docker builder
|
||||
|
||||
The platform owns a builder that runs each distribution build in a container from a pinned image, with the run source snapshot mounted read-only and a per-job output directory mounted writable. Container-per-build keeps the existing plugin/job workspace isolation guarantee from `run-build-download-flow` and keeps the Go toolchain out of the platform runtime image.
|
||||
|
||||
Alternative considered: building in-process with the platform's own Go toolchain. Rejected because it makes the toolchain a hard platform deployment dependency and gives build code the platform process's filesystem and credential reach. The container boundary is what makes it safe to hold the auth key on the platform side.
|
||||
|
||||
Builder readiness is a platform-level probe, not a run endpoint capability. When the builder is unavailable, the unavailable reason names the builder so the operator is not sent looking at run endpoints.
|
||||
|
||||
### Availability derivation
|
||||
|
||||
`generate-run` and `generate-client-manager` availability becomes: plugin declares the capability, runtime bindings are complete, platform builder is ready. The `endpointSupports(..., JobCapabilityDistributionBuild)` term is removed from both actions. `bindingsComplete` and the plugin declaration checks stay as they are.
|
||||
|
||||
### Build job identity
|
||||
|
||||
Build jobs remain jobs with `distribution.build` capability so idempotency, artifact ownership (`ArtifactOwnerKindJob`), progress projection, and the `projectDistributionBuildResult` verification path are preserved unchanged. The change is who executes them: the platform builder claims and completes them internally instead of a machine-side endpoint claiming over the job channel. The existing artifact-scope assertions in `validateDistributionBuildResult` continue to guard the result.
|
||||
|
||||
The capability-stripping guard in `job_channel.go` stays. With platform-side execution it becomes redundant for correctness but remains as defense in depth: a machine-side endpoint must never be assignable build work even if a future dispatch path regresses.
|
||||
|
||||
### Secret handling
|
||||
|
||||
`GetDistributionBuildInput` remains for legacy machine-side flows already in the field, but platform-executed builds resolve the component key internally and never place it in a job-channel response. The key reaches the builder container through the per-job input file rather than an API response, so it is never transmitted to a machine-side endpoint.
|
||||
|
||||
### Creation form
|
||||
|
||||
The deployment target selector is removed from the create branch of `ServerDeploymentWorkflow.tsx` rather than made optional. Leaving an optional selector preserves the original defect: the listed endpoints are still wrong choices at creation time. The run endpoint selector on the non-create branch is unaffected. The `saveAsDraft` special case for the create branch loses its reason to exist for target selection and is simplified accordingly.
|
||||
|
||||
Backend validation already permits this, so no relaxation is needed there. `deploymentTargetId` remains accepted by the create DTO for post-creation and programmatic flows.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
Docker becomes a platform deployment dependency for building. Mitigation: builder readiness is probed and surfaced as an explicit unavailable reason, so a platform without Docker degrades to "cannot build" with a clear cause rather than a misleading endpoint capability message.
|
||||
|
||||
Existing instances carry `DeploymentTargetID` values pointing at privileged workers. Those bindings stay valid for non-build work; only build routing stops consulting them.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Availability derivation and platform-side execution land together, since changing availability alone would surface an action that cannot execute. The creation-form change is independent and can land in the same change without ordering constraints.
|
||||
|
||||
## Open Questions
|
||||
|
||||
Whether the builder image is built from this repository or pinned from a registry is left to implementation, provided the image reference is pinned rather than floating.
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
## Why
|
||||
|
||||
Creating a server instance currently forces the owner to pick a deployment target before any run executor exists. The target dropdown lists already-registered run endpoints, but the intended flow is create server → platform builds run → operator executes run on the machine → run registers back. At creation time there is nothing correct to select, so the field can only be filled with an unrelated endpoint or bypassed with the draft checkbox.
|
||||
|
||||
Distribution building is also routed through machine-side run endpoints, while a generated run is intentionally stripped of `distribution.build` authority. Both restrictions are individually sound, but together they mean an instance bound to its own generated run can never build again: `generate-run` reports `run endpoint cannot build distributions`. Building only works when a separately maintained privileged worker endpoint happens to be registered and online, which makes the platform's core build path depend on hand-maintained machine state.
|
||||
|
||||
The current build dispatch additionally hands the plaintext component `authKey` to whichever endpoint claims the build job, so a privileged worker accumulates credentials for every server it has ever built. Moving builds into a platform-owned Docker builder removes that credential egress path instead of widening it.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Remove deployment target selection from the server creation form. Creation requires only game plugin type and server name; the run endpoint binding is established when the generated run registers itself.
|
||||
- Keep deployment target and runtime profile selection available as optional actions on an already-created instance, never as creation prerequisites.
|
||||
- Move `distribution.build` execution into a platform-owned Docker builder. The platform builds run and client-manager packages itself and no longer dispatches build jobs to machine-side run endpoints.
|
||||
- Keep the generated-run build restriction intact as a security boundary; `generate-run` availability must no longer depend on any run endpoint advertising `distribution.build`.
|
||||
- Stop exposing plaintext component auth keys over the job channel for builds executed by the platform builder.
|
||||
- Add tests proving an instance bound only to its own generated run can still generate a new run distribution.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `platform-side-distribution-builds`: Covers platform-owned Docker build execution, creation-time field requirements, and run-endpoint-independent build availability.
|
||||
|
||||
### Modified Capabilities
|
||||
- `run-distribution-and-client-managers`: Build execution moves from machine-side run endpoints to the platform Docker builder; generated-run build restriction is preserved.
|
||||
- `run-build-download-flow`: Build source snapshotting and artifact download must work without a privileged worker endpoint.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected roots: `platform/`, `platform_web/`, `scripts/`.
|
||||
- Affected behavior: server creation validation, `generate-run` and `generate-client-manager` availability, job channel build dispatch, build input secret exposure.
|
||||
- Verification requires `scripts/check-structure.sh`, platform tests, frontend tests, OpenSpec strict validation, and a local proof that run generation succeeds on an instance whose only endpoint is its own generated run.
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Server creation requires only plugin type and server name
|
||||
The system SHALL require only the game plugin type and the server name to create a server instance, and SHALL NOT require a deployment target, run endpoint, or runtime profile at creation time.
|
||||
|
||||
#### Scenario: Creation form field set
|
||||
- **WHEN** an owner opens the server creation workflow
|
||||
- **THEN** the form requires plugin type and server name only, and presents no deployment target or run endpoint selector as a creation prerequisite
|
||||
|
||||
#### Scenario: Creation without any registered endpoint
|
||||
- **WHEN** an owner creates a server instance while no run endpoint is registered for that instance
|
||||
- **THEN** creation succeeds and the instance is created without a deployment target binding
|
||||
|
||||
#### Scenario: Binding established by run registration
|
||||
- **WHEN** a generated run for that instance registers itself with the platform
|
||||
- **THEN** the platform binds the instance to that run endpoint without the owner having pre-selected it
|
||||
|
||||
#### Scenario: Target selection remains available after creation
|
||||
- **WHEN** an owner opens an already-created instance
|
||||
- **THEN** deployment target and runtime profile selection remain available as optional actions on that instance
|
||||
|
||||
### Requirement: Distribution builds execute in a platform-owned Docker builder
|
||||
The platform SHALL execute `distribution.build` work in a platform-owned Docker builder and SHALL NOT dispatch distribution build jobs to machine-side run endpoints.
|
||||
|
||||
#### Scenario: Run distribution build execution
|
||||
- **WHEN** an owner requests run generation for a server instance
|
||||
- **THEN** the platform builds the package in its own Docker builder and records the resulting artifact against the build job
|
||||
|
||||
#### Scenario: Client-manager distribution build execution
|
||||
- **WHEN** an owner requests client-manager generation for a server instance
|
||||
- **THEN** the platform builds the package in its own Docker builder and records the resulting artifact against the build job
|
||||
|
||||
#### Scenario: Build failure reporting
|
||||
- **WHEN** a platform Docker build fails
|
||||
- **THEN** the distribution status becomes failed, the build job reports a failure, and the failure reason excludes host paths and secret values
|
||||
|
||||
### Requirement: Build availability is independent of run endpoint capabilities
|
||||
The system SHALL determine `generate-run` and `generate-client-manager` availability from plugin declarations, runtime bindings, and platform builder readiness, and SHALL NOT require any run endpoint to advertise `distribution.build`.
|
||||
|
||||
#### Scenario: Instance bound only to its own generated run
|
||||
- **WHEN** a server instance's only run endpoint is its own generated run, which holds no distribution-build authority
|
||||
- **THEN** `generate-run` remains available and a new run distribution can be generated
|
||||
|
||||
#### Scenario: No privileged worker endpoint registered
|
||||
- **WHEN** no run endpoint advertising `distribution.build` is registered or online
|
||||
- **THEN** run generation still succeeds through the platform Docker builder
|
||||
|
||||
#### Scenario: Builder unavailable
|
||||
- **WHEN** the platform Docker builder is unavailable
|
||||
- **THEN** the unavailable reason names the platform builder rather than a run endpoint capability
|
||||
|
||||
### Requirement: Generated runs hold no distribution-build authority
|
||||
The system SHALL continue to deny distribution-build work to component-authenticated generated runs. This restriction is a security boundary and SHALL NOT be relaxed to unblock building.
|
||||
|
||||
#### Scenario: Generated run claims a build
|
||||
- **WHEN** a component-authenticated generated run claims work advertising `distribution.build`
|
||||
- **THEN** the platform does not assign distribution build work to that run
|
||||
|
||||
### Requirement: Platform builds do not expose plaintext component auth keys over the job channel
|
||||
The system SHALL keep component auth keys inside the platform when builds are executed by the platform Docker builder, and SHALL NOT return plaintext auth keys to machine-side run endpoints for distribution builds.
|
||||
|
||||
#### Scenario: Build input secret handling
|
||||
- **WHEN** the platform builder assembles a package requiring a component auth key
|
||||
- **THEN** the key is resolved inside the platform and is not transmitted to any machine-side run endpoint
|
||||
|
||||
#### Scenario: Generated package still authenticates
|
||||
- **WHEN** a package built by the platform builder registers with the platform
|
||||
- **THEN** its embedded credential and key generation are accepted as before
|
||||
@@ -1,40 +0,0 @@
|
||||
## 1. Server creation form
|
||||
|
||||
- [x] 1.1 Remove the deployment target selector from the create branch of `platform_web/components/ServerDeploymentWorkflow.tsx`, keeping the run endpoint selector on the non-create branch unchanged.
|
||||
- [x] 1.2 Simplify the create-branch step gating so it no longer depends on `deploymentTargetId` or on `saveAsDraft` for target selection.
|
||||
- [x] 1.3 Keep `deploymentTargetId` accepted in `platform_web/schemas/serverManagement.ts` and the create DTO for post-creation and programmatic flows.
|
||||
- [x] 1.4 Update or add frontend tests proving creation submits with plugin type and server name only.
|
||||
|
||||
## 2. Platform Docker builder
|
||||
|
||||
- [x] 2.1 Add a platform-owned builder that executes a distribution build in a container from a pinned image, with run source mounted read-only and a per-job output directory mounted writable.
|
||||
- [x] 2.2 Add a builder readiness probe and expose its unavailable reason as a platform-builder reason, not a run endpoint capability reason.
|
||||
- [x] 2.3 Route `distribution.build` job execution to the platform builder so the job is claimed and completed internally instead of over the job channel.
|
||||
- [x] 2.4 Preserve job idempotency, `ArtifactOwnerKindJob` artifact ownership, progress projection, and the existing `validateDistributionBuildResult` artifact-scope assertions.
|
||||
- [x] 2.5 Keep build workspaces isolated per plugin and per job as required by `run-build-download-flow`.
|
||||
|
||||
## 3. Build availability derivation
|
||||
|
||||
- [x] 3.1 Remove the `endpointSupports(..., JobCapabilityDistributionBuild)` term from `generate-run` and `generate-client-manager` availability in `platform/service/distributions.go`.
|
||||
- [x] 3.2 Derive availability from plugin declaration, complete runtime bindings, and builder readiness, keeping existing binding reasons intact.
|
||||
- [x] 3.3 Stop resolving a machine-side builder endpoint for build dispatch in `GenerateRunDistribution` and the client-manager build path.
|
||||
|
||||
## 4. Secret handling
|
||||
|
||||
- [x] 4.1 Resolve component auth keys inside the platform for builder-executed builds and pass them to the container through the per-job input rather than a job-channel response.
|
||||
- [x] 4.2 Keep the `distribution.build` capability-stripping guard in `platform/service/job_channel.go` as defense in depth.
|
||||
- [x] 4.3 Add a test proving builder-executed builds do not return a plaintext auth key to a machine-side endpoint.
|
||||
|
||||
## 5. Tests and verification
|
||||
|
||||
- [x] 5.1 Add a platform test proving an instance whose only endpoint is its own generated run can generate a new run distribution.
|
||||
- [x] 5.2 Add a platform test proving run generation succeeds with no endpoint advertising `distribution.build` registered or online.
|
||||
- [x] 5.3 Keep `TestCoreServiceComponentRunCannotClaimDistributionBuild` passing.
|
||||
- [x] 5.4 Add a builder-unavailable test proving the reason names the platform builder.
|
||||
- [x] 5.5 Run `scripts/check-structure.sh`, platform tests, frontend tests, and `openspec validate platform-side-docker-distribution-builds --strict`.
|
||||
- [x] 5.6 Prove the flow end to end in local debug: create a server with plugin type and name only, generate a run, download and execute it, confirm registration and heartbeat.
|
||||
|
||||
## 6. Documentation
|
||||
|
||||
- [x] 6.1 Add server creation field rules and platform-side build ownership rules to `AGENTS.md`.
|
||||
- [x] 6.2 Document builder configuration values operators must provide or may tune.
|
||||
@@ -1,4 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-28
|
||||
goal: Treat guided-install selection as authorization for secure automatic
|
||||
deployment and recovery.
|
||||
@@ -1,3 +0,0 @@
|
||||
# auto-managed-server-deployment
|
||||
|
||||
Automatically deploy guided server installations when their dedicated Run registers.
|
||||
@@ -1,20 +0,0 @@
|
||||
## Decision
|
||||
|
||||
The Platform owns the desired deployment definition. A successful, component-authenticated hello from the reserved dedicated Run endpoint is the trigger to enqueue the first guided installation. The enqueue uses a stable idempotency key derived from the server and deployment revision, so reconnects cannot duplicate work.
|
||||
|
||||
The automatic path is restricted to target-bound `guided-install` servers in `draft`. Existing-server and custom-command modes remain explicit because a missing directory can be intentional or user-owned. A future reconcile capability may safely repair guided deployments after an attested drift check; it must not be simulated by blindly reinstalling on every hello.
|
||||
|
||||
## Flow
|
||||
|
||||
1. Create stores a target-bound draft and protected guided definition.
|
||||
2. The user generates, downloads, and starts the dedicated Run.
|
||||
3. Platform validates and persists the component hello/session.
|
||||
4. Platform atomically advances the draft to installing and creates one `process.install` job.
|
||||
5. Run claims the job through the existing job channel.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- No host path, command, credential, or socket is returned to Platform Web or plugins.
|
||||
- A running server is never overwritten by this registration trigger.
|
||||
- Failed jobs use the existing bounded retry policy; reconnects do not create unbounded retries.
|
||||
- The former deploy endpoint may remain for compatibility, but is not part of the normal user journey.
|
||||
@@ -1,15 +0,0 @@
|
||||
## Why
|
||||
|
||||
Creating a guided server already captures the user's installation intent, directory, and game configuration. Requiring a second Deploy click after the dedicated Run registers exposes an internal bootstrap stage and leaves a healthy Run idle.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Treat `guided-install` as authorization to deploy automatically once the server-scoped Run successfully registers.
|
||||
- Keep existing-server and custom-command definitions non-destructive: registration never silently reinstalls them.
|
||||
- Remove Deploy/Retry deploy from the normal server-detail flow; registration and durable job state become the source of deployment progress.
|
||||
|
||||
## Impact
|
||||
|
||||
- `platform/` schedules the initial fenced install from successful dedicated Run registration.
|
||||
- `platform_web/` presents registration as an automatic deployment wait state rather than an operator action.
|
||||
- The independent Run contract remains channelized; its SCUM executor work is validated separately and is not exposed to the browser.
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Guided creation authorizes automatic initial deployment
|
||||
The Platform SHALL queue one fenced `process.install` job when the dedicated Run for a target-bound draft with a `guided-install` definition successfully registers.
|
||||
|
||||
#### Scenario: Dedicated Run registers for a guided draft
|
||||
- **WHEN** the Run presents the valid server-scoped component identity for a guided draft
|
||||
- **THEN** the Platform persists the session and queues the guided install using the stored deployment revision
|
||||
- **AND** the server transitions to `installing` without another browser action
|
||||
|
||||
#### Scenario: The dedicated Run reconnects
|
||||
- **WHEN** the Run registers again after the automatic installation has been queued
|
||||
- **THEN** the Platform does not create another installation job for the same deployment revision
|
||||
|
||||
### Requirement: Automatic registration dispatch is non-destructive outside guided installs
|
||||
The Platform SHALL NOT automatically reinstall existing-server or custom-command deployments solely because their Run registers.
|
||||
|
||||
#### Scenario: Existing server Run registers
|
||||
- **WHEN** a target-bound draft uses `existing-server` and its dedicated Run registers
|
||||
- **THEN** the Platform records the Run session without creating an installation job
|
||||
|
||||
### Requirement: Normal server management does not require a manual deployment click
|
||||
The management console SHALL present guided deployment as automatically pending after dedicated Run registration rather than as a Deploy or Retry deploy button.
|
||||
|
||||
#### Scenario: Guided draft awaits Run registration
|
||||
- **WHEN** an operator opens a newly created guided draft before its dedicated Run has registered
|
||||
- **THEN** the console directs the operator to generate and start the dedicated Run
|
||||
- **AND** it does not offer a separate Deploy or Retry deploy action
|
||||
@@ -1,13 +0,0 @@
|
||||
## 1. Platform automatic dispatch
|
||||
|
||||
- [x] 1.1 Queue a fenced guided install after an accepted dedicated Run hello, with stable revision idempotency and no duplicate reconnect dispatch.
|
||||
- [x] 1.2 Cover guided automatic dispatch and non-guided no-op behavior with service tests.
|
||||
|
||||
## 2. Management workflow
|
||||
|
||||
- [x] 2.1 Remove the normal manual Deploy/Retry deploy controls and describe automatic deployment after Run registration.
|
||||
- [x] 2.2 Update focused frontend tests for the automatic workflow.
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Run focused backend/frontend tests, type checking, structure validation, and strict OpenSpec validation.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-08-10
|
||||
@@ -1,37 +0,0 @@
|
||||
## Context
|
||||
|
||||
The Run process captures supervised stdout and stderr correctly, but `SpoolLogSink` persists one request per line. The durable uploader scans and uploads those files once per second within a five-second deadline. A startup burst therefore creates a durable backlog that reaches the platform long after the process emitted it.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Persist and upload contiguous same-stream entries in bounded multi-entry batches.
|
||||
- Drain pending log work promptly while retaining retryable, acknowledgement-driven durability.
|
||||
- Keep log upload independent from control, job, and artifact work.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Change platform log ingest routes or their contiguous-range contract.
|
||||
- Add game-specific log behavior, browser polling, or unbounded in-memory buffering.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Aggregate at the Run spool boundary. A short bounded in-memory builder groups entries only when their stream identity and sequence are contiguous, then writes one durable spool segment. This reduces both filesystem and HTTP work while preserving the existing spool retry model. Aggregating only in the uploader would retain thousands of per-line files and would not address disk pressure.
|
||||
- Bound each durable batch by entry count and serialized payload size. A full batch is committed before later entries are accepted, so a crash can lose at most uncommitted in-memory lines; process capture will surface errors rather than silently discarding a committed range. A timer flush bounds latency for low-volume output.
|
||||
- Flush pending batches repeatedly until no work remains or the channel work budget expires. The uploader remains in its own loop and uses a bounded context, so control and job loops remain independent.
|
||||
- Keep platform acknowledgements range-based. Batches remain immutable after persistence and are removed only when the existing accepted range covers them.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Crash before a partial batch is committed] → Keep the aggregation window small and flush on process completion and uploader shutdown.
|
||||
- [Large entry or encoded payload] → Commit that entry alone only when it satisfies the existing protocol bounds; reject unsafe oversized entries through the current validation path.
|
||||
- [Backlog monopolizes a tick] → Use a finite per-cycle deadline and yield to the next scheduler turn.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Existing one-entry spool files remain valid and flush through the unchanged acknowledgement logic. New Run binaries begin producing multi-entry segments; rollback remains safe because the old spool reader already accepts a batch with multiple entries.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None.
|
||||
@@ -1,24 +0,0 @@
|
||||
## Why
|
||||
|
||||
Run currently persists and uploads one HTTP log batch for every captured output line. High-volume startup output can create thousands of pending requests faster than the five-second uploader window can acknowledge them, leaving the management terminal far behind the supervised process.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Coalesce contiguous pending entries from the same Run log stream into bounded durable upload batches.
|
||||
- Drain available log backlog continuously within bounded upload work so current output reaches the platform promptly without blocking control, job, or artifact channels.
|
||||
- Preserve per-stream sequence continuity, checksums, retry retention, and acknowledgement semantics when a batch is rebuilt or retried.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `run-log-batch-upload`: Run-side durable aggregation and bounded delivery of supervised-process log streams.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `run/spool` pending-log representation and flush behavior, plus `run/runtime` process-log spooling and uploader scheduling.
|
||||
- Does not change platform API routes, browser contracts, game-specific lifecycle behavior, or artifact/control/job channels.
|
||||
@@ -1,30 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Run aggregates contiguous process log entries durably
|
||||
The Run log spool SHALL persist contiguous entries from one stream as bounded multi-entry batches before upload. Each persisted batch MUST retain one stream identity, an ordered contiguous sequence range, and a checksum covering its complete entries.
|
||||
|
||||
#### Scenario: High-volume process output is captured
|
||||
- **WHEN** a supervised process emits consecutive lines on the same declared stream
|
||||
- **THEN** Run MUST persist them in bounded multi-entry batches instead of one durable upload batch per line
|
||||
|
||||
#### Scenario: Stream changes or bounds are reached
|
||||
- **WHEN** a line belongs to another stream or adding it would exceed an aggregation bound
|
||||
- **THEN** Run MUST commit the current batch and begin a separate batch without creating a sequence gap
|
||||
|
||||
### Requirement: Run drains pending log backlog within bounded channel work
|
||||
The Run log uploader SHALL continue flushing acknowledged pending log batches while backlog exists, subject to its bounded log-channel work budget, without blocking control, job, or artifact channels.
|
||||
|
||||
#### Scenario: Backlog is present
|
||||
- **WHEN** the spool contains more than one pending log batch
|
||||
- **THEN** the uploader MUST attempt consecutive batches until the backlog is drained or its work budget expires
|
||||
|
||||
#### Scenario: Platform acknowledgement succeeds
|
||||
- **WHEN** the platform acknowledges a multi-entry batch range
|
||||
- **THEN** Run MUST remove that batch from the spool and advance the acknowledged watermark through the acknowledged sequence
|
||||
|
||||
### Requirement: Retry compatibility is preserved for old and new spool segments
|
||||
The Run spool SHALL retain unacknowledged aggregated batches for retry and SHALL continue to flush existing one-entry segments using the same range acknowledgement semantics.
|
||||
|
||||
#### Scenario: Run restarts with pending segments
|
||||
- **WHEN** Run restarts while old or aggregated log segments remain unacknowledged
|
||||
- **THEN** it MUST retry each persisted segment without duplicating or skipping acknowledged sequences
|
||||
@@ -1,21 +0,0 @@
|
||||
## 1. Durable Batch Aggregation
|
||||
|
||||
- [x] 1.1 Add bounded same-stream entry aggregation to the Run log spool while preserving contiguous sequence and checksum validation.
|
||||
- [x] 1.2 Flush partial aggregation state at lifecycle/process completion and durable-uploader shutdown.
|
||||
|
||||
## 2. Backlog Delivery
|
||||
|
||||
- [x] 2.1 Update the log uploader to keep draining pending batches within its bounded log-channel work budget.
|
||||
- [x] 2.2 Preserve retry, acknowledgement, and old one-entry spool segment compatibility.
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Add unit coverage for aggregation boundaries, restart/retry behavior, and multi-entry acknowledgement cleanup.
|
||||
- [x] 3.2 Add runtime coverage proving a high-volume stream catches up through bounded aggregated uploads.
|
||||
- [x] 3.3 Run `go test ./...` in `run/`, `scripts/check-structure.sh`, and `openspec validate batch-run-log-spool-upload --strict`.
|
||||
|
||||
## Evidence
|
||||
|
||||
- 2026-08-10: `go test ./...` from `run/` passed.
|
||||
- 2026-08-10: `scripts/check-structure.sh` passed.
|
||||
- 2026-08-10: `openspec validate batch-run-log-spool-upload --strict` passed.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -1,111 +0,0 @@
|
||||
## Context
|
||||
|
||||
The new project starts in `/Users/tasia/Desktop/code/browser` and intentionally splits the system into four subprojects:
|
||||
|
||||
- `platform/`: backend control plane for users, game management plugins, server instances, AI providers, jobs, artifacts, logs, and audit.
|
||||
- `run/`: machine-side executor that performs scoped process, file, log, artifact, and server lifecycle work.
|
||||
- `platform_web/`: management console frontend for 首页、服务器管理、插件市场、用户管理、AI 提供商管理.
|
||||
- `plugins/`: game management plugin workspace where each plugin defines how to create and manage one server type and can create many server instances.
|
||||
|
||||
The previous implementation mixed API DTOs, models, store code, business logic, frontend types, runtime protocols, plugin execution, and generated rules across many directories. This design treats directory ownership and validation as product requirements, not style preferences.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Make the platform a game server management platform, not a SCUM-only application.
|
||||
- Keep plugin semantics narrow: plugins define server types and server management workflows; they do not own platform transport, AI credentials, or run connections.
|
||||
- Give AI providers a clear role: model endpoint/key/model configuration used through platform-mediated plugin abilities.
|
||||
- Split run-platform communication into control, job, log ingest, artifact, and optional game client bridge channels.
|
||||
- Preserve log continuity when file transfer or plugin file operations are busy.
|
||||
- Create mandatory directories for DTOs, models, schemas, shared utilities, validators, and frontend types.
|
||||
- Add a repository structure checker that future changes must update when rules change.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No billing, cloud resource sales, or SaaS marketplace features.
|
||||
- No agent provider or cloud host provider system in this change.
|
||||
- No direct browser-to-run or plugin-to-run connection.
|
||||
- No raw UDP log transport for reliable historical logs.
|
||||
- No implementation of the full backend, frontend, or run binaries in this proposal.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Four subprojects are hard boundaries
|
||||
|
||||
The root project SHALL contain `run/`, `platform/`, `platform_web/`, and `plugins/` only as first-class implementation roots.
|
||||
|
||||
Alternative considered: one monorepo package tree with shared internal directories. Rejected because the old project already demonstrated that blurred roots let API structs, database models, protocol structs, and frontend types drift into business logic.
|
||||
|
||||
### Decision 2: Plugins are game management plugins
|
||||
|
||||
A plugin declares how to create and manage a class of game server. Installing `server.scum` or `server.minecraft` enables users to create multiple server instances from that plugin.
|
||||
|
||||
Alternative considered: treating every game-side mod or feature as a platform plugin. Rejected because it fragments one game into many pseudo-platform units and makes server creation unclear.
|
||||
|
||||
### Decision 3: AI provider management is a platform service
|
||||
|
||||
AI providers store base URL, API key reference, model list, routing mode, timeout, and policy. Plugins call a platform AI invocation API with scoped purpose and inputs; plugins never receive raw keys.
|
||||
|
||||
Alternative considered: plugin-owned AI provider configuration. Rejected because credentials would be duplicated, hard to audit, and unsafe for plugin frontends.
|
||||
|
||||
### Decision 4: Run communication is channelized by workload
|
||||
|
||||
The run executor SHALL use separate logical channels:
|
||||
|
||||
- control: hello, heartbeat, capability, capacity, version.
|
||||
- job: claim, ack, progress, result, cancel, reconcile.
|
||||
- log ingest: compressed batches, sequence acknowledgement, local spool, retry.
|
||||
- artifact: chunk upload/download, checksum, resumable transfer, throttling.
|
||||
- game client bridge: optional game-inside command polling and snapshots when a game needs it.
|
||||
|
||||
Alternative considered: one WebSocket with multiplexed message types. Rejected as the primary architecture because large files, long tasks, and high-volume logs can block each other and make backpressure hard to reason about.
|
||||
|
||||
### Decision 5: Logs are a data pipeline
|
||||
|
||||
Run SHALL collect process output and server log files into a local spool/WAL, upload compressed batches with monotonic sequence IDs, and delete local segments only after platform acknowledgement. Platform SHALL store log metadata separately from log bodies and support pluggable storage backends such as local compressed segments, Loki, ClickHouse, OpenSearch, or Elasticsearch.
|
||||
|
||||
Alternative considered: browser-oriented WebSocket logs from run to platform. Rejected because historical query, GPT analysis, retry, and thousands of server streams require durable ingestion semantics.
|
||||
|
||||
### Decision 6: File transfer is artifact-based
|
||||
|
||||
Plugins and frontend actions SHALL reference `artifactId` or `fileRef`, not host paths or raw run connections. Artifact transfer SHALL be chunked, resumable, checksummed, rate limited, and lower priority than control and log flush.
|
||||
|
||||
Alternative considered: synchronous file content inside job results. Accepted only for bounded small metadata or small text reads; rejected for general files because it can block logs and job status.
|
||||
|
||||
### Decision 7: Definitions live in fixed directories
|
||||
|
||||
Each backend subproject SHALL keep request/response DTOs, database models, domain types, protocol types, validation rules, shared helpers, and API route declarations in dedicated directories. Each frontend or plugin page SHALL keep API clients, page types, route definitions, schemas, bridge types, and shared utilities in dedicated directories.
|
||||
|
||||
Alternative considered: colocating structs and helper functions beside handlers for speed. Rejected because the user explicitly wants structure definitions, common functions, database definitions, and API definitions in predictable locations.
|
||||
|
||||
### Decision 8: Rules are validated by script
|
||||
|
||||
The root `scripts/check-structure.sh` SHALL verify required directories and governance files. Future implementation changes MUST extend the checker when adding new architectural rules.
|
||||
|
||||
Alternative considered: relying on AGENTS.md instructions only. Rejected because instructions alone do not prevent drift.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Directory rules may feel heavy before code exists -> Mitigation: start with lightweight presence checks and grow semantic checks with implementation.
|
||||
- [Risk] HTTP polling jobs can add latency -> Mitigation: begin with pull/long-poll for NAT reliability, then add HTTP/2 or gRPC streaming only where measured latency needs it.
|
||||
- [Risk] Log storage choice is premature -> Mitigation: define a storage adapter boundary and begin with local compressed segments plus metadata.
|
||||
- [Risk] Plugin flexibility is reduced -> Mitigation: expose platform abilities through a typed bridge and job/artifact APIs instead of direct run access.
|
||||
- [Risk] AI analysis may consume too much log context -> Mitigation: require log window extraction, redaction, summarization, and user confirmation before config writes.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Bootstrap the empty repository with four subproject roots, README files, AGENTS files, OpenSpec proposal artifacts, and the structure checker.
|
||||
2. Implement minimal platform models and route contracts for game management plugins, server instances, AI providers, run sessions, jobs, artifacts, and log streams.
|
||||
3. Implement run control, job claim/result, log spool/ingest, and artifact chunk APIs behind interfaces.
|
||||
4. Implement platform_web pages in the required navigation set and consume only platform APIs.
|
||||
5. Implement one dev game management plugin as the first proof that a plugin can create multiple server instances and use platform AI/file/log abilities.
|
||||
|
||||
Rollback is simple during bootstrap: remove the new change artifacts or directories before implementation starts. After implementation starts, rollback must follow OpenSpec task boundaries.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which backend database will be used first for platform metadata?
|
||||
- Should log body MVP use local compressed files, ClickHouse, Loki, or OpenSearch first?
|
||||
- Should the initial run job channel be short polling, long polling, or HTTP/2 streaming?
|
||||
- What language/runtime should game management plugin action scripts use first?
|
||||
@@ -1,34 +0,0 @@
|
||||
## Why
|
||||
|
||||
The previous SCUM-specific platform grew into a tightly coupled mix of frontend shell, backend services, run executors, client bridges, plugin runtime, file operations, log streaming, database access, and generated rules. The new project needs a clean game server management platform foundation where each subproject has explicit ownership, fixed definition directories, and verifiable change rules from the first commit.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Create a new four-part project layout: `run/`, `platform/`, `platform_web/`, and `plugins/`.
|
||||
- Define the platform as a game server management system with 首页、服务器管理、插件市场、用户管理、AI 提供商管理.
|
||||
- Treat plugins as game management plugins that define how to create and manage game servers; each installed plugin can create many server instances.
|
||||
- Define AI providers as GPT/OpenAI-compatible/model-provider configuration used by plugins for assisted config reading, config generation, log diagnosis, and server file suggestions.
|
||||
- Separate run-platform-plugin communication into dedicated channels for control, jobs, logs, artifacts/files, and optional game client bridge behavior.
|
||||
- Require logs to be a first-class ingestion pipeline with batching, compression, sequence acknowledgement, local spool, storage adapters, and browser tail as a derived view rather than the primary transport.
|
||||
- Require artifact/file transfer to be chunked, resumable, checksummed, throttled, and isolated from log ingestion and control heartbeats.
|
||||
- Require every subproject to keep API DTOs, database models, domain structs, shared helpers, validation rules, and frontend types in dedicated directories instead of scattering definitions through business logic.
|
||||
- Add repository governance files so future changes update rules and run automated structure checks before being considered complete.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `project-workspace-governance`: Project layout, AGENTS rules, README contracts, and automated structure validation requirements for the four subprojects.
|
||||
- `game-server-platform-core`: Core platform resources for users, game management plugins, server instances, AI providers, jobs, artifacts, logs, and audit.
|
||||
- `run-execution-channel`: The run-side control, job, log ingest, artifact transfer, and optional game client bridge contracts.
|
||||
- `game-plugin-system`: Game management plugin packaging, local development, manifest rules, platform bridge, plugin marketplace, and multi-instance server creation.
|
||||
- `platform-web-console`: The frontend console structure, plugin page bridge rules, page model, API client layout, and design constraints.
|
||||
|
||||
### Modified Capabilities
|
||||
- None. This is a new project with no existing specs.
|
||||
|
||||
## Impact
|
||||
|
||||
- Adds project-level rules and documentation under `/Users/tasia/Desktop/code/browser`.
|
||||
- Establishes OpenSpec artifacts for the initial architecture before implementation begins.
|
||||
- Affects all future implementation in `run`, `platform`, `platform_web`, and `plugins`.
|
||||
- Introduces an initial repository structure verifier that future changes must keep updated as rules evolve.
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Game management plugin manifest defines server creation
|
||||
A game management plugin SHALL provide a manifest that declares plugin identity, supported server type, create form schema, server lifecycle actions, required run capabilities, optional plugin pages, and AI/file/log permissions.
|
||||
|
||||
#### Scenario: Valid plugin installed
|
||||
- **WHEN** a plugin manifest declares a valid server type and required capabilities
|
||||
- **THEN** the platform MUST expose it in the plugin marketplace and allow creating server instances from it
|
||||
|
||||
#### Scenario: Plugin manifest requests unsafe access
|
||||
- **WHEN** a plugin manifest requests direct run credentials, raw host paths, or raw AI provider keys
|
||||
- **THEN** the platform MUST reject or disable that contribution
|
||||
|
||||
### Requirement: Plugins use platform bridge only
|
||||
Plugin page and plugin actions SHALL access platform abilities through a typed bridge or platform API and MUST NOT connect directly to run, log storage, artifact storage internals, or AI provider endpoints.
|
||||
|
||||
#### Scenario: Plugin reads logs
|
||||
- **WHEN** a plugin needs logs for a server instance
|
||||
- **THEN** it MUST query platform log APIs by server instance, stream, time range, cursor, or analysis window
|
||||
|
||||
#### Scenario: Plugin invokes AI
|
||||
- **WHEN** a plugin invokes AI for config or log assistance
|
||||
- **THEN** it MUST send a scoped platform AI request and receive a bounded response that excludes provider secrets
|
||||
|
||||
### Requirement: Local plugin development is first-class
|
||||
The project SHALL support local game management plugin development where a plugin can be registered as a dev plugin, provide UI from a dev server or static directory, and exercise real platform-run job, file, log, and AI flows against a selected test server instance.
|
||||
|
||||
#### Scenario: Developer runs local plugin
|
||||
- **WHEN** a developer starts a local plugin in dev mode
|
||||
- **THEN** platform_web MUST show the plugin as a dev game management plugin without requiring a marketplace publish
|
||||
|
||||
### Requirement: Plugin definitions are organized
|
||||
The `plugins/` workspace SHALL keep manifests, schemas, UI contracts, action definitions, test fixtures, and shared plugin SDK code in predictable directories.
|
||||
|
||||
#### Scenario: Plugin adds action input schema
|
||||
- **WHEN** a plugin adds or changes an action input
|
||||
- **THEN** the schema MUST live in a dedicated schema/contract location and tests MUST cover validation behavior
|
||||
|
||||
### Requirement: Plugin can create many server instances
|
||||
A game management plugin installation SHALL be reusable for multiple server instances with isolated configuration, artifacts, jobs, logs, and permissions per server instance.
|
||||
|
||||
#### Scenario: Two servers from one plugin
|
||||
- **WHEN** a user creates two server instances from the same plugin
|
||||
- **THEN** each instance MUST have separate configuration state, run binding, log streams, and artifact references
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Platform navigation scope
|
||||
The platform SHALL define the primary product surface as 首页、服务器管理、插件市场、用户管理、AI 提供商管理.
|
||||
|
||||
#### Scenario: Navigation is generated
|
||||
- **WHEN** platform_web renders authenticated navigation
|
||||
- **THEN** it MUST expose 首页、服务器管理、插件市场、用户管理、AI 提供商管理 as the primary areas
|
||||
|
||||
### Requirement: Game management plugins create server instances
|
||||
The platform SHALL model game management plugins as definitions for creating and managing game server types, and each installed game management plugin MUST be able to create multiple server instances.
|
||||
|
||||
#### Scenario: Create server from plugin
|
||||
- **WHEN** a user creates a server from an installed game management plugin
|
||||
- **THEN** the platform MUST create a server instance linked to that plugin and a selected run endpoint
|
||||
|
||||
#### Scenario: Multiple instances per plugin
|
||||
- **WHEN** a game management plugin is installed once
|
||||
- **THEN** users MUST be able to create more than one server instance from that plugin without reinstalling the plugin
|
||||
|
||||
### Requirement: AI providers are platform-managed
|
||||
The platform SHALL manage AI provider configuration for OpenAI-compatible, GPT, Claude, local, or relay endpoints, including base URL, key reference, model settings, timeout, and routing metadata.
|
||||
|
||||
#### Scenario: Plugin requests AI assistance
|
||||
- **WHEN** a plugin needs AI assistance for config reading, config generation, or log diagnosis
|
||||
- **THEN** it MUST call a platform AI capability and MUST NOT receive raw provider API keys
|
||||
|
||||
#### Scenario: AI suggests a config change
|
||||
- **WHEN** AI generates a server configuration change
|
||||
- **THEN** the platform MUST present a bounded diff or recommendation before any run-side file write job is dispatched
|
||||
|
||||
### Requirement: Platform data definitions are centralized
|
||||
The platform backend SHALL keep database models, DTOs, domain types, API route declarations, repository contracts, service interfaces, validators, and shared helpers in fixed directories.
|
||||
|
||||
#### Scenario: New API added
|
||||
- **WHEN** platform code adds a new HTTP/API endpoint
|
||||
- **THEN** its request and response DTOs MUST be defined in the platform contract/DTO area and route declarations MUST be discoverable in the API area
|
||||
|
||||
#### Scenario: New database table added
|
||||
- **WHEN** platform code adds a new database table
|
||||
- **THEN** its model MUST be defined in the database model area with field comments and tags before migrations or repositories reference it
|
||||
|
||||
### Requirement: Platform does not expose run internals to plugins
|
||||
The platform SHALL mediate all plugin access to files, jobs, logs, AI providers, and run endpoints.
|
||||
|
||||
#### Scenario: Plugin requests file operation
|
||||
- **WHEN** a plugin requests file access for a server instance
|
||||
- **THEN** the platform MUST authorize the request and dispatch a scoped job or artifact operation instead of exposing host paths or run credentials
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Console exposes required pages
|
||||
The platform web console SHALL provide 首页、服务器管理、插件市场、用户管理、AI 提供商管理 as first-party pages.
|
||||
|
||||
#### Scenario: Authenticated user opens console
|
||||
- **WHEN** an authenticated user opens platform_web
|
||||
- **THEN** the primary navigation MUST include 首页、服务器管理、插件市场、用户管理、AI 提供商管理
|
||||
|
||||
### Requirement: Server management uses routed or modal details
|
||||
Server management SHALL avoid fixed left-list/right-detail master-detail layouts and MUST use routed details, modal details, or drawers for server detail flows.
|
||||
|
||||
#### Scenario: User opens a server
|
||||
- **WHEN** a user selects a server from the server list
|
||||
- **THEN** platform_web MUST navigate to a detail route or open an overlay detail surface rather than permanently occupying a right-side detail pane
|
||||
|
||||
### Requirement: Plugin page is hosted through platform context
|
||||
Plugin page SHALL run inside a platform-controlled host that supplies theme tokens, server instance context, safe API access, AI invocation, log queries, artifact references, and job operations.
|
||||
|
||||
#### Scenario: Plugin page loads
|
||||
- **WHEN** a user opens an authorized plugin page for a server instance
|
||||
- **THEN** the host MUST pass only safe context and MUST not expose platform auth storage, AI keys, run credentials, or host paths
|
||||
|
||||
### Requirement: Frontend definitions are centralized
|
||||
platform_web SHALL keep API clients, route definitions, page contracts, bridge contracts, shared component types, schemas, and validation helpers in dedicated directories.
|
||||
|
||||
#### Scenario: New API call added
|
||||
- **WHEN** a frontend change adds a platform API call
|
||||
- **THEN** the call and related request/response types MUST live in the API/contract area rather than inside a view component
|
||||
|
||||
### Requirement: Logs and files are separate user flows
|
||||
The frontend SHALL treat log history/tail views and file/artifact operations as separate workflows so file operations do not imply log stream interruption.
|
||||
|
||||
#### Scenario: User uploads a file while viewing logs
|
||||
- **WHEN** a user uploads or downloads a server file from a plugin or file page
|
||||
- **THEN** active log history or tail views MUST continue to query or subscribe through the platform log APIs independently
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Four-root project layout
|
||||
The repository SHALL use `run/`, `platform/`, `platform_web/`, and `plugins/` as the only first-class implementation roots for executor, backend, frontend, and game management plugin work.
|
||||
|
||||
#### Scenario: Bootstrap layout exists
|
||||
- **WHEN** a contributor inspects the repository root
|
||||
- **THEN** the root MUST contain `run/`, `platform/`, `platform_web/`, and `plugins/`
|
||||
|
||||
#### Scenario: New implementation is placed under the correct root
|
||||
- **WHEN** a change adds executor, backend, frontend, or game management plugin implementation
|
||||
- **THEN** the files MUST be placed under the matching implementation root
|
||||
|
||||
### Requirement: Governance documentation is mandatory
|
||||
The repository and each first-class implementation root SHALL contain an `AGENTS.md` and `README.md` that describe scope, directory rules, and verification expectations.
|
||||
|
||||
#### Scenario: Root governance files exist
|
||||
- **WHEN** a contributor starts work from the repository root
|
||||
- **THEN** root `AGENTS.md` and `README.md` MUST explain cross-project rules and verification commands
|
||||
|
||||
#### Scenario: Subproject governance files exist
|
||||
- **WHEN** a contributor works inside `run/`, `platform/`, `platform_web/`, or `plugins/`
|
||||
- **THEN** that directory MUST contain local `AGENTS.md` and `README.md` with root-specific rules
|
||||
|
||||
### Requirement: Definition directories are fixed
|
||||
Backend subprojects SHALL keep DTOs, domain structs, database models, API route definitions, validation rules, protocols, and shared helpers in dedicated directories. Frontend and plugin page subprojects SHALL keep API clients, route definitions, page types, schemas, bridge types, and shared utilities in dedicated directories.
|
||||
|
||||
#### Scenario: Backend code adds a request DTO
|
||||
- **WHEN** backend code adds a request or response structure
|
||||
- **THEN** the structure MUST live in a dedicated DTO or contract directory rather than inside a handler function
|
||||
|
||||
#### Scenario: Frontend code adds a shared type
|
||||
- **WHEN** frontend code adds a shared API, route, bridge, or component type
|
||||
- **THEN** the type MUST live in a dedicated type, contract, schema, or API directory rather than inside a page component
|
||||
|
||||
### Requirement: Structure checks gate completion
|
||||
The repository SHALL provide a structure validation command that verifies mandatory roots and governance files, and future changes MUST update that validator when adding new structure rules.
|
||||
|
||||
#### Scenario: Required directory missing
|
||||
- **WHEN** `scripts/check-structure.sh` runs and a required root or governance file is missing
|
||||
- **THEN** the command MUST fail with a clear missing-path message
|
||||
|
||||
#### Scenario: Rule changes with no validator update
|
||||
- **WHEN** a change adds a new mandatory directory or governance rule
|
||||
- **THEN** the change MUST update the structure checker before the task can be marked complete
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Run control channel is lightweight
|
||||
The run executor SHALL use a lightweight control channel for hello, heartbeat, capability reporting, version reporting, and capacity reporting only.
|
||||
|
||||
#### Scenario: Run starts
|
||||
- **WHEN** run starts and reaches the platform
|
||||
- **THEN** it MUST register through hello and report capabilities before accepting jobs
|
||||
|
||||
#### Scenario: File transfer is active
|
||||
- **WHEN** run is uploading or downloading large artifacts
|
||||
- **THEN** control heartbeats MUST remain independent from artifact transfer progress
|
||||
|
||||
### Requirement: Job channel supports lifecycle semantics
|
||||
The run executor SHALL support job claim, ack, progress, result, cancel, and reconcile semantics for server lifecycle, config, database, backup, and plugin-triggered work.
|
||||
|
||||
#### Scenario: Job accepted
|
||||
- **WHEN** run accepts a job
|
||||
- **THEN** it MUST return a structured ack before execution and terminal result after execution
|
||||
|
||||
#### Scenario: Run restarts during job
|
||||
- **WHEN** run restarts or reconnects after accepting a job
|
||||
- **THEN** the platform MUST be able to request reconciliation using job identity or idempotency identity
|
||||
|
||||
### Requirement: Logs use durable ingest
|
||||
Run SHALL collect server logs into a local spool and upload compressed batches with stream identity, monotonic sequence range, checksum, and acknowledgement handling.
|
||||
|
||||
#### Scenario: Platform unavailable
|
||||
- **WHEN** platform log ingest is temporarily unavailable
|
||||
- **THEN** run MUST retain unacknowledged log batches locally and retry without losing sequence continuity
|
||||
|
||||
#### Scenario: User transfers files while logs are active
|
||||
- **WHEN** artifact transfer is consuming bandwidth
|
||||
- **THEN** log flush MUST keep priority over artifact chunks so historical logs continue to advance
|
||||
|
||||
### Requirement: Artifact transfer is isolated
|
||||
Run SHALL transfer files through an artifact channel with chunking, checksums, resume support, concurrency limits, and throttling separate from logs and control.
|
||||
|
||||
#### Scenario: Plugin writes a config file
|
||||
- **WHEN** a plugin asks the platform to write a config file
|
||||
- **THEN** run MUST receive a scoped job that references an artifact or bounded inline content and MUST write through a safe temp-and-replace flow
|
||||
|
||||
#### Scenario: Large file download active
|
||||
- **WHEN** a large file download is active
|
||||
- **THEN** job ack/result and log batch upload MUST NOT wait behind all artifact chunks
|
||||
|
||||
### Requirement: Game client bridge is optional and separate
|
||||
The system SHALL support an optional game client bridge channel for games that require in-game command execution or structured snapshots, but it MUST remain separate from run lifecycle and log ingestion channels.
|
||||
|
||||
#### Scenario: Game needs in-game command bridge
|
||||
- **WHEN** a game management plugin declares that a game needs an in-game client bridge
|
||||
- **THEN** the platform MUST route game command polling and snapshot reporting through the client bridge contract rather than the run artifact or log channels
|
||||
@@ -1,43 +0,0 @@
|
||||
## 1. Workspace Bootstrap
|
||||
|
||||
- [x] 1.1 Create the four first-class implementation roots: `run/`, `platform/`, `platform_web/`, and `plugins/`.
|
||||
- [x] 1.2 Add root `README.md` explaining the game server management platform scope and subproject boundaries.
|
||||
- [x] 1.3 Add root `AGENTS.md` with cross-project code organization, OpenSpec, verification, and no-scope-creep rules.
|
||||
- [x] 1.4 Add local `README.md` and `AGENTS.md` files in each implementation root.
|
||||
- [x] 1.5 Add `scripts/check-structure.sh` and wire it into documented verification commands.
|
||||
|
||||
## 2. Platform Foundation Contracts
|
||||
|
||||
- [x] 2.1 Define platform directories for API DTOs, database models, domain types, service contracts, repositories, validators, routes, config, and shared helpers.
|
||||
- [x] 2.2 Draft platform contracts for users, game management plugins, server instances, AI providers, run endpoints, jobs, artifacts, log streams, and audit events.
|
||||
- [x] 2.3 Define AI provider contract fields for provider kind, base URL, key reference, model list, relay mode, timeout, status, and redaction policy.
|
||||
- [x] 2.4 Define game management plugin and server instance lifecycle contracts proving one installed plugin can create many server instances.
|
||||
|
||||
## 3. Run Channel Contracts
|
||||
|
||||
- [x] 3.1 Define run control contract for hello, heartbeat, capabilities, version, and capacity.
|
||||
- [x] 3.2 Define run job contract for claim, ack, progress, result, cancel, reconcile, idempotency, and local journal behavior.
|
||||
- [x] 3.3 Define log ingest contract for local spool, batch compression, sequence acknowledgement, retry, and storage adapter boundaries.
|
||||
- [x] 3.4 Define artifact contract for chunk upload/download, checksum, resume, throttling, and priority separation from logs.
|
||||
- [x] 3.5 Define optional game client bridge contract for in-game commands and structured snapshots.
|
||||
|
||||
## 4. Plugin System Contracts
|
||||
|
||||
- [x] 4.1 Define game management plugin manifest schema with server type, create form, lifecycle actions, run capabilities, pages, and AI/file/log permissions.
|
||||
- [x] 4.2 Define local plugin development flow for dev registration, local UI hosting, action schema validation, and real platform-run flows.
|
||||
- [x] 4.3 Define plugin bridge contract that blocks direct run credentials, host paths, AI keys, and storage internals.
|
||||
- [x] 4.4 Add example plugin skeleton under `plugins/examples/` once implementation begins.
|
||||
|
||||
## 5. Frontend Console Contracts
|
||||
|
||||
- [x] 5.1 Define platform_web directories for API clients, route definitions, page contracts, schemas, bridge types, components, stores, and utilities.
|
||||
- [x] 5.2 Define first-party page skeletons for 首页、服务器管理、插件市场、用户管理、AI 提供商管理.
|
||||
- [x] 5.3 Define plugin page bridge UI contract for theme tokens, server instance context, safe API calls, job dispatch, log queries, artifacts, and AI invocation.
|
||||
- [x] 5.4 Add frontend verification rules that prevent API types and route definitions from living inside page components.
|
||||
|
||||
## 6. Verification
|
||||
|
||||
- [x] 6.1 Run `scripts/check-structure.sh` and fix missing required files or directories.
|
||||
- [x] 6.2 Run `openspec validate bootstrap-game-server-platform-architecture --strict` and fix proposal/spec/task issues.
|
||||
- [x] 6.3 Confirm OpenSpec status shows `tasks` done or ready for apply with all required artifacts present.
|
||||
- [x] 6.4 Update README verification instructions if any new required checker is added during implementation.
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-12
|
||||
@@ -1,102 +0,0 @@
|
||||
## Context
|
||||
|
||||
The platform web console already includes the required first-party routes for overview, server management, plugin marketplace, user management, and AI provider management. The current pages are uneven: some are data-backed, some fall back to local demonstration data, and several management surfaces expose create or status actions without complete edit, deletion, retirement, or operational error handling.
|
||||
|
||||
This change completes the management console without changing the product scope. Browser code continues to call platform APIs only. AI provider keys remain owned by `platform/`. Run internals, host paths, raw credentials, and direct sockets remain outside `platform_web/` and plugin pages.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Make visible management data come from platform APIs in normal operation, with explicit empty/error states when APIs are unavailable.
|
||||
- Complete user management for editing profile/contact fields, roles, status, and removal or deactivation.
|
||||
- Complete server management for metadata edits, safe delete/archive, administrator assignment, lifecycle feedback, and detail refresh.
|
||||
- Complete plugin marketplace behavior for real API data, state actions, detail refresh, and no production demo fallback masking failures.
|
||||
- Complete AI provider management for correct empty-list behavior, create/update/status/test/model refresh, and deletion or disable-only retirement semantics.
|
||||
- Keep frontend DTOs, validators, route contracts, and shared view contracts outside page components.
|
||||
- Preserve the platform_web theme and visual system while making controls dense enough for routine operations.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No billing, cloud host sales, provider marketplace, or agent-provider/cloud-provider workflow.
|
||||
- No direct plugin-to-run access and no browser access to run credentials, host paths, or raw sockets.
|
||||
- No raw AI key entry or display in `platform_web`; the UI continues to work with secret references only.
|
||||
- No replacement of the hash router, design system, or global theme architecture.
|
||||
- No real game process orchestration beyond existing platform-mediated workflows.
|
||||
|
||||
## Decisions
|
||||
|
||||
### API inventory and removal semantics
|
||||
|
||||
- Users: existing `GET/POST /api/v1/users` and `GET/PUT /api/v1/users/{id}` cover list, create, edit, role updates, status updates, and safe removal by deactivation. Hard delete is not exposed; the UI labels removal as `停用` and sends `status=disabled`.
|
||||
- Server instances: existing list/create/get/lifecycle/admin APIs are extended with `PUT /api/v1/server-instances/{id}` for metadata edits and `DELETE /api/v1/server-instances/{id}` for safe archive. Archive marks the server `deleted`, rejects running/installing states, hides deleted servers from normal lists, and returns them only with `state=deleted`.
|
||||
- Server administrators: `GET /administrators/candidates`, `POST /administrators`, and `DELETE /administrators/{userId}` remain membership APIs; they never delete user accounts.
|
||||
- Plugin marketplace: `GET /plugin-marketplace/plugins`, `GET /plugin-marketplace/plugins/{id}`, and `POST /plugin-marketplace/plugins/{id}/state` are the source of list/detail/action state. The page no longer maps `pluginCatalog` into runtime fallback data.
|
||||
- AI providers: `GET/POST /ai-providers`, `GET/PUT /ai-providers/{id}`, `POST /ai-providers/{id}/status`, `POST /test`, and `GET /models` cover empty lists, save, enable/disable, metadata test, model refresh, and retirement. Retirement is disable-only (`status=disabled`) and raw key material remains rejected by validators.
|
||||
- Config/logs/run/artifacts/audit: management pages continue using platform-mediated DTOs. Config API failure renders an explicit unavailable state instead of local sample config.
|
||||
|
||||
Missing backend support identified during implementation was limited to server instance metadata update and archive/list semantics; these were added with DTO, service, validator, repository, route, documentation, and API tests.
|
||||
|
||||
Request/response shapes remain bounded to IDs, logical refs, redacted secret refs, and platform-owned metadata. They do not include raw AI keys, raw host paths, run credentials, direct socket details, or unrestricted plugin execution fields.
|
||||
|
||||
### Decision 1: Treat demo data as development-only fixtures
|
||||
|
||||
Production pages will not silently replace failed API calls with `pluginCatalog`, `userAccess`, `seedProviders`, or `fallbackConfig`. Development fixtures may remain for isolated tests or explicit local-auth fallback paths, but page status must clearly show API unavailable or empty data.
|
||||
|
||||
Alternative considered: keep local fallback data for visual continuity. Rejected because it hides missing backend behavior and makes the console appear functional when data was not loaded.
|
||||
|
||||
### Decision 2: Add typed API contracts before page work
|
||||
|
||||
Any missing update, delete, retire, archive, or detail-refresh behavior will be represented first in `platform_web/api/types.ts`, `platform_web/api/client.ts`, shared contracts, and schemas. Page components will consume those typed contracts rather than defining request or response shapes inline.
|
||||
|
||||
Alternative considered: implement form submit handlers directly against ad hoc endpoints. Rejected because the repository requires API clients, DTOs, contracts, and schemas to stay outside page components.
|
||||
|
||||
### Decision 3: Use deactivation or archive when hard deletion is unsafe
|
||||
|
||||
Delete-like UI must respect domain safety. Users can be disabled or deleted according to platform rules. AI providers can be disabled or retired if deletion would break references. Server instances can be archived or soft-deleted if a running server or existing history prevents hard deletion. The UI must name the action accurately.
|
||||
|
||||
Alternative considered: add one generic delete button everywhere. Rejected because operational resources have different safety and audit requirements.
|
||||
|
||||
### Decision 4: Make fallback and failure states auditable
|
||||
|
||||
Pages that cannot load API data must show an error or empty state with retry and diagnostic context. Development-only fixtures must be visually isolated and must not enable state-changing actions that imply persistence.
|
||||
|
||||
Alternative considered: keep current optimistic local writes after failed API calls. Rejected because it can produce false success for management actions.
|
||||
|
||||
### Decision 5: Verify UI workflows in browser after implementation
|
||||
|
||||
Because this change touches frontend pages and interactions, completion requires automated tests plus a browser walkthrough. The walkthrough must include the edited pages at desktop and narrow widths and must confirm that no raw secrets, host paths, run credentials, or direct socket values are visible.
|
||||
|
||||
Alternative considered: rely only on unit tests. Rejected because these workflows depend on visible controls, responsive layout, and operational feedback states.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Backend APIs may not yet expose every edit/delete operation. Mitigation: implement missing platform DTO, service, repository, handler, and tests in the same change before wiring the UI.
|
||||
- [Risk] Removing silent fallbacks can make local development feel less populated. Mitigation: keep explicit local debug fixtures behind development-only paths and show clear labels when they are active.
|
||||
- [Risk] Delete semantics can vary by resource. Mitigation: define resource-specific action labels and confirmation copy, and prefer disable/archive where hard deletion is unsafe.
|
||||
- [Risk] This change spans several pages. Mitigation: implement one resource workflow at a time with focused tests, then finish with a full browser walkthrough and structure check.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Inventory current platform API coverage for users, server instances, marketplace plugins, AI providers, config, and maintenance data.
|
||||
2. Add or extend backend routes and service behavior where required for edit, delete, archive, retire, and detail refresh operations.
|
||||
3. Update frontend API types, schemas, and shared contracts before page components.
|
||||
4. Replace silent demo fallbacks with explicit empty/error/local-development states.
|
||||
5. Implement page-level controls, confirmations, operation feedback, and tests per resource.
|
||||
6. Run frontend tests/build, relevant backend tests, browser walkthrough, `scripts/check-structure.sh`, and strict OpenSpec validation.
|
||||
|
||||
Rollback is contained before downstream changes depend on these workflows: remove the new routes/client methods, restore previous page interactions, and keep read-only views. After users rely on edit/archive actions, rollback should be handled by a new OpenSpec change with data compatibility notes.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Resolved: server instance removal is named archive in the UI and implemented as `DELETE` to a `deleted` state so history remains visible by explicit filter.
|
||||
- Resolved: AI provider removal is disable-only retirement for this implementation.
|
||||
- Resolved: user removal is deactivation (`disabled`) for this implementation; hard delete is not exposed.
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- `go test ./...` from `platform/` passed.
|
||||
- `cd platform_web && npm run typecheck && npm run test && npm run build` passed.
|
||||
- `scripts/browser-acceptance.sh` passed, covering users, servers, plugin marketplace, AI providers, server detail, plugin controls, desktop/mobile widths, black-mecha/magical-girl themes, and forbidden-fragment scans. Evidence: `.local-debug/browser-acceptance/browser-acceptance-evidence.json`.
|
||||
- `scripts/check-structure.sh` passed.
|
||||
- `openspec validate complete-platform-web-management-workflows --strict` passed. The CLI emitted PostHog telemetry flush network errors after the success line because external network access is unavailable.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user