first commit
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# 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.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# 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.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
## 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`.
|
||||
@@ -0,0 +1,36 @@
|
||||
# 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.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# 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
@@ -0,0 +1,45 @@
|
||||
# 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.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
## 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`.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -0,0 +1,55 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,123 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,94 @@
|
||||
## 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.
|
||||
@@ -0,0 +1,26 @@
|
||||
## 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
@@ -0,0 +1,67 @@
|
||||
## 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
|
||||
@@ -0,0 +1,27 @@
|
||||
## 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.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -0,0 +1,111 @@
|
||||
## 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?
|
||||
@@ -0,0 +1,34 @@
|
||||
## 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
@@ -0,0 +1,44 @@
|
||||
## 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
@@ -0,0 +1,48 @@
|
||||
## 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
@@ -0,0 +1,36 @@
|
||||
## 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
@@ -0,0 +1,45 @@
|
||||
## 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
@@ -0,0 +1,52 @@
|
||||
## 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
|
||||
@@ -0,0 +1,43 @@
|
||||
## 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.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -0,0 +1,75 @@
|
||||
## Context
|
||||
|
||||
The repository has the required project roots and architecture contracts, but there is no executable backend, run executor, frontend app, plugin SDK package, or common check command. Future changes need a stable local development baseline so every OpenSpec implementation can run tests and builds in the same way.
|
||||
|
||||
The local environment currently has Go 1.25.1, Node 22.17.0, and npm 11.6.1. This change uses those tool families without adding business behavior beyond minimal health or placeholder shells.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Add separate Go module baselines under `platform/` and `run/`.
|
||||
- Add minimal executable entry points and tests for both Go roots.
|
||||
- Add a Vite React TypeScript baseline under `platform_web/` with required route/page placeholders and a browser-verifiable shell.
|
||||
- Add a TypeScript/npm baseline under `plugins/` for manifest schema validation, SDK exports, example fixtures, and tests.
|
||||
- Add root orchestration scripts that run all baseline checks while keeping implementation code inside the owning roots.
|
||||
- Document development commands and update structure checks for new required baseline files.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No platform database implementation.
|
||||
- No real platform API resource behavior beyond minimal health/bootstrap endpoints needed to prove the server starts.
|
||||
- No run job execution, log ingest, artifact transfer, or game server lifecycle work.
|
||||
- No plugin marketplace behavior or hosted plugin page runtime.
|
||||
- No production deployment packaging.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Use separate Go modules for `platform/` and `run/`
|
||||
|
||||
`platform/` and `run/` SHALL each own a Go module, command entry point, internal packages, config loading, and tests. They must not import code from each other. Protocol sharing stays in documented contract files until a later OpenSpec introduces generated contracts.
|
||||
|
||||
Alternative considered: one root Go module for both backend roots. Rejected because it would make casual cross-root imports too easy and weaken the ownership boundary required by `AGENTS.md`.
|
||||
|
||||
### Decision 2: Use Vite, React, and TypeScript for `platform_web/`
|
||||
|
||||
`platform_web/` SHALL use npm scripts for dev, build, typecheck, test, and preview. The baseline app should render the required first-party navigation entries and page placeholders without implementing backend-driven workflows.
|
||||
|
||||
Alternative considered: a static HTML placeholder. Rejected because future frontend work needs route definitions, component structure, schema typing, and browser verification from the start.
|
||||
|
||||
### Decision 3: Use npm TypeScript tooling for `plugins/`
|
||||
|
||||
`plugins/` SHALL own its SDK package metadata, TypeScript sources, JSON schema validation scripts, example manifest fixtures, and tests. This keeps plugin contract checks close to plugin ownership while leaving platform registration behavior for a later change.
|
||||
|
||||
Alternative considered: validate plugin schemas from `platform/`. Rejected because plugin authoring and fixture tests belong in the plugin workspace; platform can later consume the same published or copied contracts through an explicit boundary.
|
||||
|
||||
### Decision 4: Root scripts orchestrate checks only
|
||||
|
||||
Root `scripts/` may contain shell scripts such as `check-structure.sh` and `check-all.sh`, but no application logic. These scripts call commands inside each root and provide a single verification entry point for future OpenSpec changes.
|
||||
|
||||
Alternative considered: a root package manager workspace. Deferred because there is not enough shared package structure yet, and root-level dependency metadata could blur ownership boundaries before generated contracts exist.
|
||||
|
||||
### Decision 5: Minimal UI still requires browser verification
|
||||
|
||||
Because this change creates the initial frontend shell, closure requires a local dev server and browser walkthrough. The walkthrough only needs to prove the shell renders, required navigation exists, and layout does not visibly overlap on desktop and mobile widths.
|
||||
|
||||
Alternative considered: rely on build and unit tests only. Rejected because the repository rules require a browser walkthrough when frontend pages are touched.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Separate Go modules add repeated tooling setup. Mitigation: add root orchestration scripts and keep shared protocol files documented until generation is introduced.
|
||||
- [Risk] Vite baseline may look like product UI before APIs exist. Mitigation: keep pages minimal and avoid fake workflows; later changes will implement data-backed pages.
|
||||
- [Risk] npm dependency versions may drift. Mitigation: commit lockfiles during implementation and document the Node/npm baseline.
|
||||
- [Risk] `scripts/check-all.sh` may be slow as features grow. Mitigation: start with baseline commands and allow future changes to add narrower scripts when needed.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add module/package metadata and minimal source files inside each project root.
|
||||
2. Add root orchestration scripts and update `scripts/check-structure.sh` for new required baseline files.
|
||||
3. Update README files with local development commands.
|
||||
4. Run root structure checks, per-root tests/builds, strict OpenSpec validation, and frontend browser walkthrough.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Whether future generated contracts should be produced from OpenAPI, protobuf, JSON Schema, or TypeScript source remains for a later contract-generation change.
|
||||
- Whether `platform/` starts with SQLite or Postgres remains for the platform API surface change.
|
||||
@@ -0,0 +1,26 @@
|
||||
## Why
|
||||
|
||||
The repository currently has architecture documents and ownership directories, but it does not yet have runnable project baselines. Later platform, run, frontend, and plugin changes need consistent local commands, package boundaries, and verification entry points before business behavior is implemented.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Establish Go module baselines for `platform/` and `run/` with minimal executable entry points and tests.
|
||||
- Establish a TypeScript/Vite baseline for `platform_web/` with a minimal browser-rendered management console shell.
|
||||
- Establish a TypeScript baseline for `plugins/` covering SDK exports, schema validation scripts, examples, and contract tests.
|
||||
- Add root orchestration scripts for build/test/check workflows without placing implementation code outside the matching project roots.
|
||||
- Document local development commands and required tool versions.
|
||||
- Extend structure verification only for new required baseline files and directories introduced by this change.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `development-runtime-baseline`: Runtime, tooling, command, and verification baseline for the four project roots.
|
||||
|
||||
### Modified Capabilities
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/`, `run/`, `platform_web/`, `plugins/`, root documentation, and root verification scripts.
|
||||
- Introduces Go and npm-based development commands but does not implement platform business APIs, run job execution, plugin marketplace behavior, or full frontend pages.
|
||||
- Future OpenSpec changes will rely on these commands for tests, builds, and local walkthroughs.
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Platform Go Runtime Baseline
|
||||
`platform/` SHALL contain an independent Go module with a minimal command entry point, configuration package, HTTP health surface, and automated tests.
|
||||
|
||||
#### Scenario: Platform tests run
|
||||
- **WHEN** a contributor runs the documented platform test command
|
||||
- **THEN** the platform Go module test suite completes successfully without importing code from `run/`, `platform_web/`, or `plugins/`
|
||||
|
||||
#### Scenario: Platform server starts
|
||||
- **WHEN** a contributor runs the documented platform development command
|
||||
- **THEN** the process starts a local HTTP server with a health response suitable for smoke testing
|
||||
|
||||
### Requirement: Run Go Runtime Baseline
|
||||
`run/` SHALL contain an independent Go module with a minimal command entry point, configuration package, platform client boundary, and automated tests.
|
||||
|
||||
#### Scenario: Run tests run
|
||||
- **WHEN** a contributor runs the documented run test command
|
||||
- **THEN** the run Go module test suite completes successfully without importing code from `platform/`, `platform_web/`, or `plugins/`
|
||||
|
||||
#### Scenario: Run executor starts
|
||||
- **WHEN** a contributor runs the documented run development command
|
||||
- **THEN** the process starts in a local smoke-test mode without exposing host paths, raw credentials, or direct sockets to plugins or frontend code
|
||||
|
||||
### Requirement: Platform Web TypeScript Runtime Baseline
|
||||
`platform_web/` SHALL contain a Vite React TypeScript app with route definitions, required first-party page placeholders, API client boundaries, shared components, theme tokens, and automated build/typecheck/test scripts.
|
||||
|
||||
#### Scenario: Frontend checks run
|
||||
- **WHEN** a contributor runs the documented platform_web verification commands
|
||||
- **THEN** TypeScript typecheck, tests, and production build complete successfully
|
||||
|
||||
#### Scenario: Required navigation renders
|
||||
- **WHEN** the platform_web dev server is opened in a browser
|
||||
- **THEN** the shell renders navigation entries for 首页、服务器管理、插件市场、用户管理、AI 提供商管理 without visible overlap on desktop and mobile widths
|
||||
|
||||
### Requirement: Plugin Workspace TypeScript Baseline
|
||||
`plugins/` SHALL contain npm TypeScript tooling for SDK exports, JSON schema validation, example plugin fixtures, and automated tests.
|
||||
|
||||
#### Scenario: Plugin checks run
|
||||
- **WHEN** a contributor runs the documented plugin verification commands
|
||||
- **THEN** SDK typecheck, schema validation, and tests complete successfully
|
||||
|
||||
#### Scenario: Example manifest validates
|
||||
- **WHEN** the plugin schema validation command is run
|
||||
- **THEN** `plugins/examples/dev-game-plugin/manifest.json` validates against `plugins/manifests/game-plugin.manifest.schema.json`
|
||||
|
||||
### Requirement: Root Verification Orchestration
|
||||
The repository SHALL provide root-level verification scripts that orchestrate structure checks and per-root build/test commands without containing application logic.
|
||||
|
||||
#### Scenario: Full baseline check runs
|
||||
- **WHEN** a contributor runs the documented full check command from the repository root
|
||||
- **THEN** it runs structure verification plus platform, run, platform_web, and plugin baseline checks
|
||||
|
||||
#### Scenario: Structure rules include new baseline files
|
||||
- **WHEN** `scripts/check-structure.sh` runs after this change
|
||||
- **THEN** it verifies the new required module, package, command, test, and documentation baseline files added by this change
|
||||
|
||||
### Requirement: Development Documentation
|
||||
The repository SHALL document required tool versions, local development commands, verification commands, and the scope limits of this runtime baseline.
|
||||
|
||||
#### Scenario: Contributor reads the README
|
||||
- **WHEN** a contributor reads the root and per-root README files
|
||||
- **THEN** they can identify how to install dependencies, start local processes, run tests, run builds, and perform the frontend browser walkthrough
|
||||
|
||||
#### Scenario: Future change reads baseline docs
|
||||
- **WHEN** a future OpenSpec implementation needs to add product behavior
|
||||
- **THEN** it can reuse the documented baseline commands instead of inventing a new verification surface
|
||||
@@ -0,0 +1,75 @@
|
||||
## 1. Go Runtime Baselines
|
||||
|
||||
- [x] 1.1 Add an independent Go module under `platform/` with minimal command, config, HTTP health surface, and tests.
|
||||
- [x] 1.2 Add an independent Go module under `run/` with minimal command, config, platform client boundary, smoke-test mode, and tests.
|
||||
- [x] 1.3 Verify neither Go module imports implementation code from another project root.
|
||||
|
||||
## 2. Platform Web Baseline
|
||||
|
||||
- [x] 2.1 Add npm, Vite, React, and TypeScript baseline files under `platform_web/`.
|
||||
- [x] 2.2 Add route definitions, API client boundaries, required page placeholders, shared components, theme tokens, and test setup in the required directories.
|
||||
- [x] 2.3 Add scripts for `dev`, `build`, `typecheck`, `test`, and `preview`.
|
||||
|
||||
## 3. Plugin Workspace Baseline
|
||||
|
||||
- [x] 3.1 Add npm and TypeScript baseline files under `plugins/`.
|
||||
- [x] 3.2 Add SDK export stubs, schema validation scripts, example manifest validation, and tests inside the plugin root.
|
||||
- [x] 3.3 Keep plugin checks scoped to plugin contracts and do not add platform marketplace behavior in this change.
|
||||
|
||||
## 4. Root Orchestration And Documentation
|
||||
|
||||
- [x] 4.1 Add a root verification script that runs structure checks plus each root's baseline checks without containing application logic.
|
||||
- [x] 4.2 Update `scripts/check-structure.sh` for new required baseline files and directories.
|
||||
- [x] 4.3 Update root and per-root README files with tool versions, dependency install commands, local start commands, verification commands, and baseline scope limits.
|
||||
|
||||
## 5. Verification
|
||||
|
||||
- [x] 5.1 Run `go test ./...` in `platform/`.
|
||||
- [x] 5.2 Run `go test ./...` in `run/`.
|
||||
- [x] 5.3 Run the documented install, typecheck, test, and build commands in `platform_web/`.
|
||||
- [x] 5.4 Run the documented install, typecheck, test, and schema validation commands in `plugins/`.
|
||||
- [x] 5.5 Run the root full-check script and `scripts/check-structure.sh`.
|
||||
- [x] 5.6 Start the platform_web dev server and complete a browser walkthrough at desktop and mobile widths.
|
||||
- [x] 5.7 Run `openspec validate establish-development-runtime-baseline --strict`.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `go test ./...` in `platform/`: passed.
|
||||
- `go test ./...` in `run/`: passed.
|
||||
- `npm install`, `npm run typecheck`, `npm run test`, and `npm run build` in `platform_web/`: passed.
|
||||
- `npm install`, `npm run typecheck`, `npm run test`, and `npm run validate:manifest` in `plugins/`: passed.
|
||||
- Cross-root import checks: `rg "browser\.local/(run|platform_web|plugins)" platform` and `rg "browser\.local/(platform|platform_web|plugins)" run` returned no matches.
|
||||
- `scripts/check-all.sh`: passed.
|
||||
- `scripts/check-structure.sh`: passed.
|
||||
- Browser walkthrough: Vite dev server at `http://127.0.0.1:5173/`; desktop 1440x900 and mobile 390x844 checks confirmed required labels, 5 navigation items, 3 metric cards, no nav/metric/header overlap, and mobile document width equal to viewport.
|
||||
- `openspec validate establish-development-runtime-baseline --strict`: passed.
|
||||
|
||||
## Implementation Handoff
|
||||
|
||||
```text
|
||||
Implement OpenSpec change: establish-development-runtime-baseline
|
||||
|
||||
Scope:
|
||||
- Implement only openspec/changes/establish-development-runtime-baseline/.
|
||||
- Add runtime/tooling baselines for platform, run, platform_web, and plugins.
|
||||
- Do not implement platform business APIs, run job execution, log ingest, artifact transfer, plugin marketplace workflows, billing, cloud host sales, or agent-provider/cloud-provider workflows.
|
||||
|
||||
Read first:
|
||||
- AGENTS.md
|
||||
- platform/AGENTS.md
|
||||
- run/AGENTS.md
|
||||
- platform_web/AGENTS.md
|
||||
- plugins/AGENTS.md
|
||||
- openspec/changes/bootstrap-game-server-platform-architecture/proposal.md
|
||||
- openspec/changes/bootstrap-game-server-platform-architecture/design.md
|
||||
- openspec/changes/architecture-delivery-stream/delivery-plan.md
|
||||
- openspec/changes/establish-development-runtime-baseline/proposal.md
|
||||
- openspec/changes/establish-development-runtime-baseline/design.md
|
||||
- openspec/changes/establish-development-runtime-baseline/tasks.md
|
||||
|
||||
Required closure:
|
||||
- Mark task checkboxes complete only after evidence exists.
|
||||
- Run platform Go tests, run Go tests, platform_web install/typecheck/test/build, plugin install/typecheck/test/schema validation, the root full-check script, scripts/check-structure.sh, and openspec validate establish-development-runtime-baseline --strict.
|
||||
- Because platform_web pages are touched, start the dev server and perform a browser walkthrough at desktop and mobile widths before claiming the UI is accepted.
|
||||
- Stop after this change is closed; do not start implement-platform-core-domain in the same chat unless explicitly asked.
|
||||
```
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-07
|
||||
@@ -0,0 +1,51 @@
|
||||
## Context
|
||||
|
||||
The platform already supports file and MySQL-backed metadata stores behind `repo.Store`. MySQL initialization is selected by `PLATFORM_STORAGE_BACKEND=mysql` and uses `PLATFORM_MYSQL_DSN`, but `platform/cmd/platform` calls `config.Load()` directly and `config.Load()` only reads process environment variables. A developer who edits `platform/.env` and starts the binary without sourcing that file still gets the default file-backed store.
|
||||
|
||||
The platform web shell currently embeds profile editing, theme palette selection, background presets, upload background, and logout inside the sidebar account popover. Those controls already call the current-user profile and theme APIs, but the interaction is cramped and visually hard to use.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Load repository-local `.env` values into platform configuration before storage initialization.
|
||||
- Preserve process environment precedence over `.env` values so deployment systems can override local files.
|
||||
- Keep profile and theme persistence backed by existing user APIs and the configured metadata repository.
|
||||
- Replace the account popover editor with a dedicated personal settings page that is available to all authenticated users.
|
||||
- Preserve the current magical crystal-moonlight shell style and shared surface classes.
|
||||
|
||||
**Non-Goals:**
|
||||
- Add a normalized relational user schema or migrations beyond the existing MySQL metadata snapshot table.
|
||||
- Add external account providers, billing, cloud host provisioning, or plugin marketplace workflows.
|
||||
- Expose raw credentials, host paths, or direct run/plugin internals to the web UI.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Load `.env` inside `platform/config`**
|
||||
- `config.Load()` will call a small local dotenv loader before reading values.
|
||||
- The loader will check common local paths such as `.env` and `platform/.env` relative to the current working directory.
|
||||
- Existing process environment values win over file values.
|
||||
- Alternative considered: requiring users to `source .env`. Rejected because the observed failure is that local `.env` exists but platform startup does not consume it.
|
||||
|
||||
2. **Keep MySQL persistence through the existing snapshot repository**
|
||||
- The fix only makes backend selection reliable; it does not introduce normalized SQL tables for users.
|
||||
- Profile and theme updates already flow through `UpdateUser`, which persists through `repo.Store`; this remains the single write path.
|
||||
- Alternative considered: adding user-specific SQL tables now. Rejected because it is broader than the current bug and would duplicate the existing store abstraction.
|
||||
|
||||
3. **Move personal settings to a route instead of a popover**
|
||||
- Add a `profileSettings` page id, route, registry entry, and page component.
|
||||
- The sidebar account control becomes a navigation entry point to that page, with logout remaining available from the settings page.
|
||||
- Theme controls move into the page but continue to use `theme/tokens.ts` helpers and the session store API methods.
|
||||
- Alternative considered: converting the popover into a larger drawer. Rejected because the user specifically wants a normal personal configuration interface, and a page is more ergonomic for forms and preview grids.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] `.env` parsing can accidentally override production environment values. → Mitigation: only set variables that are not already present in `os.Environ`.
|
||||
- [Risk] Multiple working directories make `.env` discovery ambiguous. → Mitigation: try root `.env` and `platform/.env` from the process working directory, and use deterministic later-file fallback only for missing keys.
|
||||
- [Risk] Uploaded background data URLs can be large. → Mitigation: preserve the existing client-side behavior and persistence API contract rather than expanding backend payload rules in this change.
|
||||
- [Risk] Removing the popover editor changes a familiar access point. → Mitigation: keep the sidebar account button visible and route it directly to the new personal settings page.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add dotenv loading tests that prove `platform/.env` selects MySQL settings and explicit process env overrides file values.
|
||||
2. Add the personal settings route/page and update existing shell/session wiring to keep API-backed persistence.
|
||||
3. Validate OpenSpec, backend config tests, frontend tests/typecheck/build, structure checks, and a browser walkthrough for the personal settings page.
|
||||
@@ -0,0 +1,30 @@
|
||||
## Why
|
||||
|
||||
Local operators can configure `platform/.env`, but the platform process currently reads only inherited environment variables. This makes MySQL metadata storage look uninitialized even when the `.env` file contains the correct `PLATFORM_STORAGE_BACKEND=mysql` and `PLATFORM_MYSQL_DSN` settings.
|
||||
|
||||
The current personal configuration experience is embedded in the sidebar account popover, which is cramped for profile, theme, and background preferences. Operators need a normal first-party personal settings page that saves profile and theme changes through platform APIs so values are durable in the configured metadata store.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Load platform environment variables from local `.env` files before building platform configuration, while preserving explicit process environment overrides.
|
||||
- Keep MySQL metadata initialization database-backed and make configured storage selection testable so operators can verify the remote metadata store is actually used.
|
||||
- Replace the sidebar profile popover with a dedicated personal settings page for profile, theme palette, background preset, uploaded background, and logout actions.
|
||||
- Add the personal settings route to the shell for authenticated users and keep account edits wired to `/api/v1/users/current/profile` and `/api/v1/users/current/theme`.
|
||||
- Preserve the magical-girl crystal-moonlight visual system by reusing shared shell/page surfaces and theme tokens rather than adding a one-off UI style.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `platform-env-bootstrap`: Platform startup loads local environment configuration and initializes the configured metadata backend predictably.
|
||||
- `personal-settings-workspace`: Authenticated users manage their own profile and console theme preferences from a full settings page backed by platform APIs.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/config` and platform startup tests for `.env` loading and storage backend selection.
|
||||
- Affects `platform_web` route definitions, page registry, shell account controls, session usage, API-bound personal settings UI, tests, and shared styling.
|
||||
- Does not add billing, cloud host sales, external marketplace behavior, raw AI key exposure, or plugin direct access to platform/run internals.
|
||||
@@ -0,0 +1,34 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Authenticated users have a personal settings page
|
||||
The platform web application SHALL provide a normal page-level personal settings workspace for every authenticated user.
|
||||
|
||||
#### Scenario: User opens personal settings
|
||||
- **WHEN** an authenticated user activates the account settings entry point
|
||||
- **THEN** the application MUST navigate to a full personal settings page instead of opening a cramped profile popover
|
||||
|
||||
#### Scenario: User sees current account data
|
||||
- **WHEN** the personal settings page renders
|
||||
- **THEN** it MUST show the current user's display name, email, role labels, status, profile fields, theme palette, background preset, and custom background state
|
||||
|
||||
### Requirement: Personal profile saves through platform APIs
|
||||
The personal settings page SHALL save editable profile fields through platform-mediated current-user APIs.
|
||||
|
||||
#### Scenario: User saves profile
|
||||
- **WHEN** a user submits display name, avatar URL, phone, QQ, or contact note changes
|
||||
- **THEN** the page MUST call the current-user profile API and render the updated current user from the response
|
||||
|
||||
#### Scenario: Profile API is unavailable
|
||||
- **WHEN** the current-user profile API cannot be reached in local development fallback mode
|
||||
- **THEN** the page MUST mark the resulting profile state as local fallback rather than pretending database persistence succeeded
|
||||
|
||||
### Requirement: Theme preferences save through platform APIs
|
||||
The personal settings page SHALL save theme palette, background preset, and custom background preferences through platform-mediated current-user APIs where available.
|
||||
|
||||
#### Scenario: User changes theme preference
|
||||
- **WHEN** a user selects a palette, selects a background preset, uploads a background, or removes a background
|
||||
- **THEN** the page MUST update the visible theme and persist the preference through the current-user theme API
|
||||
|
||||
#### Scenario: Theme API is unavailable
|
||||
- **WHEN** the current-user theme API cannot be reached in local development fallback mode
|
||||
- **THEN** the page MUST preserve local theme preference behavior and clearly show that the preference is local
|
||||
@@ -0,0 +1,23 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Platform startup loads local environment files
|
||||
The platform SHALL load local `.env` configuration before constructing runtime configuration for storage initialization.
|
||||
|
||||
#### Scenario: Platform env file selects MySQL storage
|
||||
- **WHEN** `platform/.env` contains `PLATFORM_STORAGE_BACKEND=mysql` and `PLATFORM_MYSQL_DSN`
|
||||
- **THEN** platform configuration MUST use the MySQL storage backend and DSN from the env file
|
||||
|
||||
#### Scenario: Process environment overrides env file
|
||||
- **WHEN** a process environment variable and a local `.env` file both define the same platform setting
|
||||
- **THEN** platform configuration MUST use the process environment value
|
||||
|
||||
### Requirement: Metadata backend selection remains database-backed
|
||||
The platform SHALL initialize the configured metadata repository through the existing store boundary rather than falling back to hardcoded local sample data.
|
||||
|
||||
#### Scenario: MySQL storage is configured
|
||||
- **WHEN** `PLATFORM_STORAGE_BACKEND=mysql` and a non-empty `PLATFORM_MYSQL_DSN` are loaded
|
||||
- **THEN** platform startup MUST initialize the MySQL metadata store
|
||||
|
||||
#### Scenario: MySQL storage is missing DSN
|
||||
- **WHEN** `PLATFORM_STORAGE_BACKEND=mysql` is loaded without `PLATFORM_MYSQL_DSN`
|
||||
- **THEN** platform startup MUST fail with a direct configuration error instead of silently using file or memory storage
|
||||
@@ -0,0 +1,31 @@
|
||||
## 1. Platform Env Bootstrap
|
||||
|
||||
- [x] 1.1 Add a small dotenv loader in `platform/config` that reads local `.env` files without overriding explicit process environment values.
|
||||
- [x] 1.2 Add config tests for `platform/.env` MySQL settings, process env precedence, and missing DSN behavior through storage initialization.
|
||||
|
||||
## 2. Personal Settings Workspace
|
||||
|
||||
- [x] 2.1 Add a first-party personal settings route, page id, registry entry, and navigation entry point for authenticated users.
|
||||
- [x] 2.2 Move profile, theme palette, background preset, uploaded background, and logout controls from the sidebar popover into the new page.
|
||||
- [x] 2.3 Keep profile and theme saves wired to current-user APIs and show API vs local fallback persistence state.
|
||||
- [x] 2.4 Add/update frontend tests for routing, shell account navigation, and profile/theme API calls.
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Run `cd platform && go test ./config ./api ./service ./repo -count=1`.
|
||||
- [x] 3.2 Run `cd platform_web && npm run typecheck && npm test && npm run build`.
|
||||
- [x] 3.3 Run `scripts/check-structure.sh`.
|
||||
- [x] 3.4 Run `openspec validate fix-env-profile-settings --strict`.
|
||||
- [x] 3.5 Perform a browser walkthrough for the personal settings page and record the result.
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- 2026-07-07: `cd platform && go test ./config ./api ./service ./repo -count=1` passed.
|
||||
- 2026-07-07: `cd platform_web && npm run typecheck` passed.
|
||||
- 2026-07-07: `cd platform_web && npm test` passed with 11 files / 47 tests.
|
||||
- 2026-07-07: `cd platform_web && npm run build` passed and Vite produced `dist/` assets.
|
||||
- 2026-07-07: `scripts/check-structure.sh` passed.
|
||||
- 2026-07-07: `openspec validate fix-env-profile-settings --strict` reported the change is valid; PostHog telemetry flush failed due restricted DNS and did not affect validation.
|
||||
- 2026-07-07: Started `cd platform_web && npm run dev -- --port 5173`; Vite served the app at `http://127.0.0.1:5174/` because 5173 was occupied. Browser walkthrough could not be completed in this tool session because no in-app browser/Chrome control tool or local Playwright/Puppeteer dependency was exposed.
|
||||
- 2026-07-08: Rechecked task `3.5` before generating the next architecture-stream OpenSpec. The browser walkthrough remains explicitly blocked in this session: an in-app browser connection opened the auth page at `http://127.0.0.1:5177/`, but DOM snapshot capture failed with `TypeError: o.incrementalAriaSnapshot is not a function`; the fallback-enabled dev server then failed to bind requested localhost ports with `listen EPERM` for `127.0.0.1:5180`, `127.0.0.1:5173`, and `127.0.0.1:5177`. The walkthrough is not accepted; it must be rerun manually or in a working browser/dev-server session before closing this change.
|
||||
- 2026-07-08: Browser walkthrough accepted after starting the platform API with file storage at `127.0.0.1:18080` and using the existing Vite dev server at `127.0.0.1:5173`. Logged in with the seeded API-backed platform administrator `operator.local@example.test`, landed on `#/home`, opened `#/profile`, verified `个人设置` showed `API 已连接`, `Operator`, `operator.local@example.test`, `active`, and platform-admin navigation. Edited the contact note to `api walkthrough verified 2026-07-08`, clicked `保存资料`, observed `个人资料已保存到数据库`, reloaded `#/profile`, and confirmed the note value persisted through the API-backed session.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-04
|
||||
@@ -0,0 +1,16 @@
|
||||
## Design
|
||||
|
||||
- Sessions are in-memory platform sessions keyed by a random bearer token. Clients send the token as `Authorization: Bearer <token>`.
|
||||
- The local development platform seeds one explicit platform administrator account so real login can reach the admin console:
|
||||
- account/email: `operator.local@example.test`
|
||||
- password: `operator-local`
|
||||
- Passwords are stored as PBKDF2-SHA256 hashes with per-user salts using only Go standard library primitives.
|
||||
- Public registration creates a pending user with `server-admin` role and returns `status=pending` rather than authenticating the user.
|
||||
- Current-user profile and theme updates operate only on the authenticated session user and return bounded DTOs.
|
||||
- User management updates reuse `PUT /api/v1/users/{id}` and allow status, roles, display name, email, and profile fields to be changed through service validation.
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Password hashes are not returned in DTOs.
|
||||
- Pending/disabled users cannot log in.
|
||||
- The frontend local fallback is disabled unless `VITE_ENABLE_LOCAL_AUTH_FALLBACK=true`, and its fallback user is not a platform admin.
|
||||
@@ -0,0 +1,17 @@
|
||||
## Why
|
||||
|
||||
The platform_web console already calls authentication, current-user, profile, theme, and user update endpoints, but the platform API has those routes deferred. That mismatch makes login/register appear broken and encourages the frontend local fallback to grant a platform administrator session without credentials.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a minimal first-party username/email + password session API for login, registration, logout, and current-user lookup.
|
||||
- Store password hashes in platform-owned user records and never expose password material to platform_web.
|
||||
- Default public registration to pending server-admin scope instead of platform administrator privileges.
|
||||
- Add controlled user update support so the 用户管理 page can change user status through the API.
|
||||
- Restrict frontend local fallback to development/demo mode and downgrade it away from platform administrator privileges.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` and `platform_web/`.
|
||||
- Keeps authentication in platform only; plugins do not receive raw credentials or auth secrets.
|
||||
- Does not add OAuth, SMS, production persistence, billing, cloud host sales, or unrelated marketplace behavior.
|
||||
@@ -0,0 +1,56 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Platform authentication sessions are implemented
|
||||
The platform SHALL expose login, registration, logout, and current-user routes backed by platform-owned user records and in-memory session tokens.
|
||||
|
||||
#### Scenario: Active user logs in
|
||||
- **WHEN** a client posts a valid account and password to `POST /api/v1/auth/login`
|
||||
- **THEN** the platform MUST return `200` with an authenticated `AuthSessionResponse` and a session token
|
||||
|
||||
#### Scenario: Pending user cannot log in
|
||||
- **WHEN** a pending user submits valid credentials
|
||||
- **THEN** the platform MUST reject the login with `403` and MUST NOT issue a session token
|
||||
|
||||
#### Scenario: Current user is requested
|
||||
- **WHEN** a client sends `GET /api/v1/users/current` with a valid bearer session token
|
||||
- **THEN** the platform MUST return the bounded current user DTO without password material
|
||||
|
||||
#### Scenario: Session logs out
|
||||
- **WHEN** a client posts to `POST /api/v1/auth/logout` with a valid bearer token
|
||||
- **THEN** the platform MUST invalidate that session token
|
||||
|
||||
### Requirement: Registration is low privilege by default
|
||||
Public registration SHALL create pending users with server scope and SHALL NOT grant platform administrator privileges.
|
||||
|
||||
#### Scenario: Visitor registers
|
||||
- **WHEN** a visitor submits display name, email, and password to `POST /api/v1/auth/register`
|
||||
- **THEN** the platform MUST create a pending user with a non-platform-admin role and return `status=pending`
|
||||
|
||||
### Requirement: User management updates are supported
|
||||
The platform SHALL support controlled user updates through `PUT /api/v1/users/{id}` using named DTOs and service validation.
|
||||
|
||||
#### Scenario: User status is updated
|
||||
- **WHEN** a platform client sends a valid status update for an existing user
|
||||
- **THEN** the platform MUST persist and return the updated user DTO
|
||||
|
||||
### Requirement: Current user preferences are supported
|
||||
The platform SHALL allow an authenticated current user to update bounded profile and theme preference fields.
|
||||
|
||||
#### Scenario: Current user profile is updated
|
||||
- **WHEN** a client sends `PUT /api/v1/users/current/profile` with a valid bearer session token
|
||||
- **THEN** the platform MUST persist the bounded profile fields and return the updated current user DTO
|
||||
|
||||
#### Scenario: Current user theme is updated
|
||||
- **WHEN** a client sends `PUT /api/v1/users/current/theme` with a valid bearer session token
|
||||
- **THEN** the platform MUST persist the theme preference and return a `UserThemePreferenceResponse`
|
||||
|
||||
### Requirement: Frontend fallback cannot silently grant platform admin
|
||||
The frontend SHALL NOT persist a local platform administrator user as a fallback authentication path.
|
||||
|
||||
#### Scenario: Auth API is unavailable
|
||||
- **WHEN** the auth API is unavailable and local fallback is not explicitly enabled
|
||||
- **THEN** the frontend MUST keep the user on the authentication screen and MUST NOT enter the console as platform administrator
|
||||
|
||||
#### Scenario: Development fallback is enabled
|
||||
- **WHEN** local fallback is explicitly enabled
|
||||
- **THEN** the fallback user MUST have server-scoped access only and MUST NOT expose platform administrator navigation
|
||||
@@ -0,0 +1,21 @@
|
||||
## 1. OpenSpec And Contracts
|
||||
|
||||
- [x] 1.1 Add auth/session requirements covering login, registration, logout, current-user, profile/theme updates, user update, and local fallback limits.
|
||||
|
||||
## 2. Platform Implementation
|
||||
|
||||
- [x] 2.1 Extend user domain, DTO, model, validation, and service contracts for password hashes, profile, theme, and controlled user updates.
|
||||
- [x] 2.2 Implement in-memory platform auth sessions and route handlers for `/api/v1/auth/*` and `/api/v1/users/current*`.
|
||||
- [x] 2.3 Implement `PUT /api/v1/users/{id}` for the 用户管理 page.
|
||||
|
||||
## 3. Frontend Implementation
|
||||
|
||||
- [x] 3.1 Send bearer session tokens on API calls and persist only the API session token, not a privileged local user.
|
||||
- [x] 3.2 Gate local fallback behind an explicit dev/demo env flag and ensure fallback never grants platform administrator privileges.
|
||||
- [x] 3.3 Keep metrics/config/AI suggestion gaps in graceful page-local fallback behavior.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Add backend API/service tests for login/register/current-user/logout/pending/disabled/user-update behavior.
|
||||
- [x] 4.2 Add frontend session tests for API login, failed auth, refresh session restoration, and fallback gating.
|
||||
- [x] 4.3 Run platform tests, platform_web tests/typecheck/build, `scripts/check-structure.sh`, and `openspec validate fix-platform-auth-session-api --strict`.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-08
|
||||
@@ -0,0 +1,66 @@
|
||||
## Context
|
||||
|
||||
The platform/run architecture already separates control registration, job lifecycle calls, durable log ingest, and artifact transfer into typed routes and protocol packages. Prior changes proved those channels individually, and the lifecycle proof showed that real plugin operations can route through platform-owned lifecycle APIs into run jobs.
|
||||
|
||||
This change hardens the cross-channel behavior. The important failure mode is not just malformed payloads; it is starvation under concurrent work. A large artifact or file transfer must not delay control heartbeat, job acknowledgement, job result delivery, or durable log spool upload. Likewise, retry queues must stay independently bounded so a blocked artifact transfer cannot consume the execution path needed for log ingest or job completion.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Prove run-side scheduling keeps control heartbeat, job ack/result, log upload, and artifact/file transfer on independently bounded paths.
|
||||
- Prove platform APIs validate and mutate state independently when log, artifact, job, and control requests interleave.
|
||||
- Add focused tests that simulate slow or large artifact/file work while verifying timely heartbeat, job ack/result, and log acknowledgement.
|
||||
- Document the channel priority and non-starvation invariants in run/platform protocol docs.
|
||||
- Preserve the existing channel APIs unless implementation reveals a contract gap that must be made explicit in the spec.
|
||||
|
||||
**Non-Goals:**
|
||||
- Do not add new plugin-facing transport or direct run access.
|
||||
- Do not add a browser UI flow unless implementation discovers an existing platform_web surface incorrectly exposes channel details.
|
||||
- Do not redesign storage backends, introduce external queues, or require distributed infrastructure.
|
||||
- Do not change artifact/log/job payload semantics except where needed to enforce bounded isolation.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. Keep isolation proof local to run/platform packages before adding broader e2e tooling.
|
||||
|
||||
The current risk lives in queueing, retry, route handling, and worker scheduling. Package-level tests can deterministically simulate slow artifact uploads, retryable platform failures, and interleaved requests without relying on brittle timing from a full browser stack. A later browser acceptance suite can reuse this confidence without becoming the primary proof.
|
||||
|
||||
Alternative considered: start with a full local platform/run/browser smoke. That gives nice operator evidence but is weaker for starvation because browser timing is noisy and harder to make deterministic.
|
||||
|
||||
2. Treat control and job lifecycle calls as high-priority bounded work.
|
||||
|
||||
Heartbeats, job claim/ack/progress/result, and cancellation/reconcile calls remain small JSON payloads. They must never carry artifact chunks, file bodies, or large inline logs. Tests should assert that delayed artifact/file uploads cannot prevent these calls from completing.
|
||||
|
||||
Alternative considered: one shared retry worker for all run-to-platform calls. That is simpler, but a stuck artifact transfer could monopolize retries and delay lifecycle visibility.
|
||||
|
||||
3. Keep log ingest durable and independently retryable.
|
||||
|
||||
The log spool already persists batches until platform acknowledgement. This change should assert that log batch selection, upload, ack handling, and retry bookkeeping stay independent from artifact chunk retry queues and job result submission.
|
||||
|
||||
Alternative considered: merge log and artifact retry state because both are upload queues. That would blur priority boundaries and make it easier for large artifact payloads to starve small log acknowledgements.
|
||||
|
||||
4. Verify platform state isolation with interleaved service/API tests.
|
||||
|
||||
Platform tests should interleave control heartbeat, job ack/result, log batch ingest, and artifact transfer requests for the same run endpoint. Success means each route validates only its own contract, mutates only its own state, and preserves idempotency when requests are retried or reordered within valid channel rules.
|
||||
|
||||
Alternative considered: only test run-side clients. That would miss platform-side cross-route coupling, such as artifact completion accidentally blocking log acknowledgement state.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- Timing-sensitive tests become flaky -> Use deterministic fakes, channels, contexts, and bounded wait helpers instead of wall-clock sleeps wherever possible.
|
||||
- Hardening may reveal that current worker scheduling is too serial -> Introduce small, explicit channel executors or queue limits rather than broad worker rewrites.
|
||||
- Additional docs can drift -> Keep docs close to `run/protocol/` and `platform/protocol/` route contracts, and update them in the same implementation task as tests.
|
||||
- Full starvation proof can become too broad -> Scope the first pass to platform/run package behavior and exact commands in `tasks.md`; leave browser-wide automation to the later acceptance-suite queue item.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add failing tests for platform and run channel isolation around existing APIs and queues.
|
||||
2. Adjust run scheduling, retry queues, or client sequencing only where tests prove coupling.
|
||||
3. Update protocol documentation with the enforced invariants.
|
||||
4. Run platform/run tests, structure check, and strict OpenSpec validation.
|
||||
|
||||
Rollback is straightforward because expected changes are test and scheduling hardening around existing APIs. If a scheduling change regresses behavior, revert that implementation while keeping the new tests as the contract for the corrected approach.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None currently. The implementation should stay within `run/` and `platform/` unless a failing test proves a shared contract needs a spec update.
|
||||
@@ -0,0 +1,25 @@
|
||||
## Why
|
||||
|
||||
Log ingest, artifact/file transfer, control heartbeat, and job ack/result delivery already exist as separate platform/run channels, but the current evidence mostly proves each channel in isolation. The next risk is starvation under load: a large artifact or file operation must not delay heartbeat, lifecycle acknowledgement, job result delivery, or durable log upload.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add channel-isolation requirements that define priority, bounded payloads, retry behavior, and non-starvation guarantees across run/platform channels.
|
||||
- Add run-side concurrency and queue tests proving large artifact/file work cannot block control heartbeat, job ack/result submission, or log spool upload.
|
||||
- Add platform service/API tests proving artifact/log/job/control endpoints preserve independent validation, state mutation, and idempotency under interleaved requests.
|
||||
- Add a local verification command set that exercises platform and run test suites plus strict OpenSpec validation.
|
||||
- No breaking API changes are expected; the change hardens behavior and verification around existing channel contracts.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `log-artifact-channel-isolation`: Defines cross-channel non-starvation, bounded-transfer, durable-retry, and verification guarantees for run/platform control, job, log, artifact, and file operations.
|
||||
|
||||
### Modified Capabilities
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected roots: `run/` and `platform/`.
|
||||
- Affected areas: run worker scheduling, platform client calls, log spool retry, artifact/file queue retry, platform run-facing APIs, service tests, API tests, and protocol documentation.
|
||||
- Validation impact: requires focused run/platform concurrency tests, existing package tests, `scripts/check-structure.sh`, and `openspec validate harden-log-artifact-channel-isolation --strict`.
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Run channels preserve non-starvation under large transfers
|
||||
The run executor SHALL keep control heartbeat, job acknowledgement, job result delivery, and log batch upload on bounded execution paths that are not blocked by large artifact or file transfer work.
|
||||
|
||||
#### Scenario: Artifact upload does not block lifecycle calls
|
||||
- **WHEN** a run endpoint is uploading or retrying a large artifact or file transfer
|
||||
- **THEN** control heartbeat, job acknowledgement, job progress, cancellation polling, reconciliation, and terminal job result calls MUST remain able to complete through their typed platform client methods without waiting for the transfer payload to finish
|
||||
|
||||
#### Scenario: Log upload continues during transfer pressure
|
||||
- **WHEN** artifact or file transfer chunks are queued, slow, or retrying
|
||||
- **THEN** the run log spool MUST still select bounded log batches, upload them through the log ingest client, and remove acknowledged batches independently from artifact/file queue state
|
||||
|
||||
### Requirement: Platform routes mutate only their own channel state
|
||||
The platform SHALL handle interleaved control, job, log, artifact, and file requests for the same run endpoint without one channel accepting another channel's payload or mutating another channel's state.
|
||||
|
||||
#### Scenario: Interleaved valid requests succeed independently
|
||||
- **WHEN** a registered run endpoint interleaves valid heartbeat, job ack/result, log batch ingest, and artifact chunk or completion requests
|
||||
- **THEN** each route MUST validate its own typed DTO, update only the corresponding control/job/log/artifact state, and return the same acknowledgement semantics as if the requests were sent without interleaving
|
||||
|
||||
#### Scenario: Heavy payload is rejected from lightweight routes
|
||||
- **WHEN** a control, job, or log route receives an artifact chunk, file body, host path, raw credential, direct socket, or other transport payload owned by another channel
|
||||
- **THEN** the platform MUST reject the request as a JSON validation error and MUST NOT mutate control session, job lifecycle, log acknowledgement, or artifact state
|
||||
|
||||
### Requirement: Retry queues remain independently bounded
|
||||
The run executor SHALL keep log retry state and artifact/file retry state independently bounded and independently acknowledged.
|
||||
|
||||
#### Scenario: Artifact retry backlog does not consume log retry state
|
||||
- **WHEN** artifact or file chunks remain unacknowledged after platform upload failures
|
||||
- **THEN** the artifact/file retry queue MUST retain those chunks without preventing log spool retry listing, log batch upload, or acknowledged log batch removal
|
||||
|
||||
#### Scenario: Log retry backlog does not consume artifact retry state
|
||||
- **WHEN** log batches remain unacknowledged after platform ingest failures
|
||||
- **THEN** the log spool MUST retain those batches without preventing artifact/file retry listing, chunk upload, or acknowledged artifact chunk removal
|
||||
|
||||
### Requirement: Job terminal results remain bounded and prioritized
|
||||
The run job channel SHALL submit terminal job results as bounded metadata and result references, not inline logs, artifact chunks, file bodies, host paths, raw credentials, or direct sockets.
|
||||
|
||||
#### Scenario: Terminal result arrives while transfer is active
|
||||
- **WHEN** a job finishes while artifact/file transfer work is still active or retrying
|
||||
- **THEN** run MUST submit the terminal job result through the job result endpoint with bounded result metadata and the platform MUST accept or reject it only according to job lease and idempotency rules
|
||||
|
||||
#### Scenario: Duplicate terminal result remains idempotent under pressure
|
||||
- **WHEN** run retries an equivalent terminal job result while log and artifact retries are also pending
|
||||
- **THEN** platform MUST return the accepted idempotent terminal result response and MUST NOT duplicate logs, chunks, artifacts, or unrelated job metadata
|
||||
|
||||
### Requirement: Channel isolation is documented and verified
|
||||
The change SHALL document the enforced priority and isolation rules and SHALL include deterministic platform/run tests for interleaved requests, retry independence, and large-transfer non-starvation.
|
||||
|
||||
#### Scenario: Contributor inspects channel docs
|
||||
- **WHEN** a contributor opens run or platform protocol documentation
|
||||
- **THEN** the docs MUST state that control and job lifecycle calls are lightweight, log ingest is durable and independently retried, artifact/file transfer is chunked and lower priority, and no lightweight route accepts heavy transfer payloads
|
||||
|
||||
#### Scenario: Verification commands run
|
||||
- **WHEN** the change is complete
|
||||
- **THEN** `go test ./...` from `platform/`, `go test ./...` from `run/`, `scripts/check-structure.sh`, and `openspec validate harden-log-artifact-channel-isolation --strict` MUST pass
|
||||
@@ -0,0 +1,56 @@
|
||||
## 1. Run-Side Channel Isolation
|
||||
|
||||
- [x] 1.1 Add deterministic run tests that simulate slow or retrying artifact/file transfer work while control heartbeat and job ack/progress/result calls continue through bounded client calls.
|
||||
- [x] 1.2 Add run tests proving log spool selection, upload acknowledgement, and retry cleanup continue while artifact/file chunks are queued, slow, or retrying.
|
||||
- [x] 1.3 Add run tests proving artifact/file retry listing, chunk acknowledgement, and cleanup continue while log batches are queued, slow, or retrying.
|
||||
- [x] 1.4 Update run scheduling, retry queue, or worker orchestration code only where needed to make the tests pass without exposing host paths, raw credentials, direct sockets, or large inline payloads through lightweight channels.
|
||||
- [x] 1.5 Run `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` and record evidence.
|
||||
|
||||
## 2. Platform Interleaving and Validation
|
||||
|
||||
- [x] 2.1 Add platform service/API tests that interleave valid heartbeat, job ack/result, log batch ingest, and artifact transfer requests for one registered run endpoint.
|
||||
- [x] 2.2 Prove each interleaved platform route mutates only its own state and preserves existing idempotency semantics.
|
||||
- [x] 2.3 Add negative platform tests proving control, job, and log routes reject artifact chunks, file bodies, host paths, raw credentials, direct sockets, and channel-owned transport payloads from other routes.
|
||||
- [x] 2.4 Update platform validators, DTOs, service logic, or route documentation only where needed to enforce the isolation contract.
|
||||
- [x] 2.5 Run `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` and record evidence.
|
||||
|
||||
## 3. Protocol Documentation
|
||||
|
||||
- [x] 3.1 Update `run/protocol/*.md`, `run/spool/README.md`, `run/artifact/README.md`, `platform/protocol/run-contracts.md`, or `platform/api/routes.md` as needed to document channel priority and payload boundaries.
|
||||
- [x] 3.2 Confirm docs state that control/job calls remain lightweight, log ingest is durable and independently retried, artifact/file transfer is chunked and lower priority, and lightweight routes never accept heavy transfer payloads.
|
||||
|
||||
## 4. Verification and Stream Handoff
|
||||
|
||||
- [x] 4.1 Record implementation evidence in this tasks file only after each command has actually run.
|
||||
- [x] 4.2 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 4.3 Run `openspec validate harden-log-artifact-channel-isolation --strict` and record evidence.
|
||||
- [x] 4.4 Update `openspec/changes/architecture-delivery-stream/delivery-plan.md` to mark `harden-log-artifact-channel-isolation` complete only after evidence exists and move the next queue item to active.
|
||||
- [x] 4.5 Update `openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md` with the next implementation/generator handoff after this change closes.
|
||||
|
||||
## Evidence
|
||||
|
||||
- Run-side channel isolation:
|
||||
- Added `run/api/channel_isolation_test.go`, proving heartbeat, terminal job result, and log ingest complete while an artifact chunk upload is deliberately blocked.
|
||||
- Added `run/spool/channel_isolation_test.go`, proving log acknowledgement cleanup remains independent from artifact backlog and artifact acknowledgement cleanup remains independent from log backlog.
|
||||
- No run scheduling or queue production code changes were required; existing separate client calls and separate `logs` / `artifacts` spool areas satisfied the new regression tests.
|
||||
- Initial sandbox run of `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./api ./spool -count=1` was blocked by `httptest` loopback bind permissions after `run/spool` passed.
|
||||
- Escalated rerun of `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./api ./spool -count=1` passed for `browser.local/run/api` and `browser.local/run/spool`.
|
||||
- Full sandbox run of `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` was blocked by `httptest` loopback bind permissions in `run/api` and `run/runtime`; non-listener packages passed.
|
||||
- Escalated rerun of `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` passed for `api`, `config`, `protocol`, `runtime`, and `spool`.
|
||||
|
||||
- Platform interleaving and validation:
|
||||
- Added `platform/api/channel_isolation_handlers_test.go`, proving interleaved heartbeat, job ack/result, log batch ingest, and artifact transfer requests mutate only their own channel state.
|
||||
- Added negative API coverage proving lightweight control/job/log routes reject artifact chunks, inline log arrays, host paths, raw credential fragments, direct socket strings, and heavy transfer payload fields through strict JSON decoding.
|
||||
- Added rejection-state coverage proving a rejected heavy heartbeat payload does not mutate endpoint capacity or store heavy payload text.
|
||||
- Focused command `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./api -run 'TestRunChannelAPI|TestLightweightRunRoutes' -count=1` passed.
|
||||
- Full command `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` passed for `api`, `config`, `domain`, `dto`, `model`, `repo`, `service`, and `validator`.
|
||||
|
||||
- Protocol documentation:
|
||||
- Updated `run/spool/README.md`, `run/artifact/README.md`, `run/protocol/artifact.md`, `run/protocol/log-ingest.md`, and `run/protocol/job.md` with channel priority, independent retry, and heavy-payload boundary rules.
|
||||
- Updated `platform/protocol/run-contracts.md` and `platform/api/routes.md` to state that control/job calls remain lightweight, log ingest is durable and independently retried, artifact/file transfer is lower priority and chunked, and lightweight routes reject heavy transfer payloads.
|
||||
|
||||
- Final gates and stream handoff:
|
||||
- `scripts/check-structure.sh` passed with `structure check passed`.
|
||||
- `openspec validate harden-log-artifact-channel-isolation --strict` passed with `Change 'harden-log-artifact-channel-isolation' is valid`; the process exited 0. PostHog telemetry flush reported `ENOTFOUND edge.openspec.dev`, which did not affect validation.
|
||||
- `openspec/changes/architecture-delivery-stream/delivery-plan.md` now marks `harden-log-artifact-channel-isolation` complete and `implement-local-debug-workspace` active.
|
||||
- `openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md` now points the next generator chat at creating `implement-local-debug-workspace`, because that OpenSpec directory does not exist yet.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -0,0 +1,77 @@
|
||||
## Context
|
||||
|
||||
The platform already has domain, DTO, validator, repository, service, and HTTP API foundations for AI provider resources. The route catalog previously deferred provider test/model actions, and `platform_web/pages/AiProvidersPage.tsx` is still a placeholder. The architecture requires AI provider credentials and base URLs to remain platform-owned, and plugin pages must never receive raw provider keys.
|
||||
|
||||
This change turns AI provider management into a usable first-party workflow across `platform/` and `platform_web/` while keeping the scope intentionally local: configuration validation, status management, and model inventory are platform metadata operations, not live external model calls.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Add backend AI provider management APIs for update, enable/disable, configuration test, and model listing.
|
||||
- Keep all provider responses redacted to `apiKeyRef`; reject raw keys in create and update paths.
|
||||
- Keep management behavior inside `service.Core` and named DTOs, with handlers acting as transport adapters.
|
||||
- Implement a functional AI provider management page in `platform_web` with API client/types, create/edit form, status filters, model display, enable/disable, and test actions.
|
||||
- Add backend and frontend tests for management behavior and secret redaction.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No real OpenAI/Claude/local provider network calls.
|
||||
- No secret vault implementation or raw secret storage.
|
||||
- No plugin-facing AI invocation API.
|
||||
- No AI-generated config diff/write dispatch.
|
||||
- No authentication, RBAC, SQL persistence, run-side behavior, billing, cloud host sales, or agent-provider/cloud-provider workflows.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Provider test is metadata validation
|
||||
|
||||
The test endpoint will validate stored provider metadata and report whether the provider is active, has a secret reference when required, includes a default model in its model list, and passes existing validator rules. It will not contact external AI services.
|
||||
|
||||
Alternative considered: performing a live chat/model request. Rejected because this change must not introduce external network behavior, raw key handling, or provider-specific clients.
|
||||
|
||||
### Decision 2: Status changes use a dedicated action route
|
||||
|
||||
Enable/disable behavior will use `POST /api/v1/ai-providers/{id}/status` with a named status request DTO. General update will edit provider metadata while preserving status unless the dedicated action changes it.
|
||||
|
||||
Alternative considered: overloading generic update with status changes. Rejected because explicit status actions are easier to audit and test.
|
||||
|
||||
### Decision 3: Update uses full provider metadata
|
||||
|
||||
The update request will accept the same safe fields as create plus provider metadata fields, with no raw key field. `apiKeyRef` remains a secret reference string and is validated the same way as create.
|
||||
|
||||
Alternative considered: partial patch semantics. Rejected for this stage because full update is deterministic, simpler to validate, and matches the existing in-memory repository implementation.
|
||||
|
||||
### Decision 4: Frontend page owns UI state but not contracts
|
||||
|
||||
`AiProvidersPage` will manage local loading/form selection state, while API DTOs and client functions remain in `platform_web/api`. The page will use API responses for persisted provider data and seed a local demo fallback only when the backend is unavailable in standalone frontend development.
|
||||
|
||||
Alternative considered: hard-coded page data only. Rejected because this would not exercise the platform API client or management workflow.
|
||||
|
||||
### Decision 5: UI stays operational and dense
|
||||
|
||||
The AI provider page will use a table, compact metrics, a form panel, filter controls, and action buttons. It will avoid marketing layout and will not display instructional copy or raw secrets.
|
||||
|
||||
Alternative considered: a large hero/empty-state page. Rejected because this is an operational console area used for repeated configuration work.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] The test endpoint can only validate metadata, not live connectivity. Mitigation: return an explicit `mode` value and reserve live tests for a later provider invocation change.
|
||||
- [Risk] Frontend fallback data could be mistaken for persisted data. Mitigation: mark fallback state as local-only in view state and prefer API data whenever the backend responds.
|
||||
- [Risk] Full update requires clients to send all editable provider fields. Mitigation: centralize the request builder in the page and API client.
|
||||
- [Risk] In-memory backend state remains process-local. Mitigation: retain service/router injection and leave persistence to a future storage change.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add backend DTOs, service methods, handler routes, and route catalog updates for AI provider management.
|
||||
2. Add backend service/API tests covering update, status, test/model responses, duplicate/missing resources, and raw key rejection.
|
||||
3. Add frontend API types/client methods, replace the placeholder AI provider page, and add rendering/client tests.
|
||||
4. Run backend tests, frontend tests/build, structure check, browser walkthrough, and strict OpenSpec validation.
|
||||
|
||||
Rollback before dependent changes is removal of the new AI provider management endpoints/page and this OpenSpec change. After dependent plugin or frontend workflows consume these APIs, rollback must be handled through a new OpenSpec change.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which persistence-backed secret reference provider should store `apiKeyRef` targets?
|
||||
- Which later change should add live provider connectivity tests and model discovery calls?
|
||||
- Which authorization policy will restrict who can create or disable providers?
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
AI providers are a required first-party platform area, but the backend and console currently expose only the generic core resource API and a placeholder page. Operators need a usable management workflow that configures model endpoints safely without exposing raw provider credentials to plugins or UI responses.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add AI-provider-specific backend management actions for update, enable/disable, configuration test, and configured model listing.
|
||||
- Preserve the existing create/list/detail API while tightening response behavior around secret references and raw key rejection.
|
||||
- Add service methods and DTOs for AI provider management without adding external provider calls or raw secret storage.
|
||||
- Replace the `platform_web` placeholder AI provider page with a functional management view that lists providers, creates/edits provider metadata, toggles status, tests configuration, and displays model inventory.
|
||||
- Add frontend API types/client methods and tests that assert raw keys are never part of returned provider shapes.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `ai-provider-management`: Safe platform and management-console workflows for creating, editing, enabling/disabling, testing, and viewing AI provider configuration.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` and `platform_web/` only.
|
||||
- Extends AI provider DTOs, service methods, API handlers, route catalog, frontend API contracts, and the AI provider page.
|
||||
- Adds backend API tests, frontend rendering/client tests, and a browser walkthrough.
|
||||
- Does not add raw key exposure, plugin-facing raw credentials, run-side behavior, external AI network invocation, billing, cloud host sales, or agent-provider/cloud-provider workflows.
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: AI providers can be managed through platform APIs
|
||||
The platform SHALL expose AI provider management APIs for create, list, detail, update, enable/disable, configuration test, and configured model listing.
|
||||
|
||||
#### Scenario: Provider is updated
|
||||
- **WHEN** a client sends a valid provider update request to an existing AI provider
|
||||
- **THEN** the platform MUST validate the request, persist the metadata through `service.Core`, and return a redacted `AIProviderResponse`
|
||||
|
||||
#### Scenario: Provider status is changed
|
||||
- **WHEN** a client enables or disables an existing AI provider through the status action route
|
||||
- **THEN** the platform MUST persist the requested status and return a redacted `AIProviderResponse`
|
||||
|
||||
#### Scenario: Provider configuration is tested
|
||||
- **WHEN** a client tests an existing AI provider
|
||||
- **THEN** the platform MUST validate stored metadata locally and return a named test result DTO without contacting external AI services
|
||||
|
||||
#### Scenario: Provider model list is requested
|
||||
- **WHEN** a client requests configured models for an existing AI provider
|
||||
- **THEN** the platform MUST return the provider ID, default model, and configured model names without exposing credentials
|
||||
|
||||
### Requirement: AI provider management preserves secret boundaries
|
||||
AI provider management SHALL reject raw key material in request fields and SHALL never expose raw API keys in API responses or frontend-visible types.
|
||||
|
||||
#### Scenario: Raw key is submitted during update
|
||||
- **WHEN** a create or update request includes raw key material instead of a secret reference in `apiKeyRef`
|
||||
- **THEN** the platform MUST reject the request with a validation error and MUST NOT persist the provider
|
||||
|
||||
#### Scenario: Provider is returned to UI
|
||||
- **WHEN** the backend or frontend API client returns provider data
|
||||
- **THEN** the response/type MUST include `apiKeyRef` only and MUST NOT include `apiKey`, `rawApiKey`, or equivalent raw credential fields
|
||||
|
||||
### Requirement: AI provider service owns management invariants
|
||||
The platform service layer SHALL own AI provider update, status, local test, and model-list behavior rather than implementing those rules directly in HTTP handlers.
|
||||
|
||||
#### Scenario: Management handler receives request
|
||||
- **WHEN** an AI provider management HTTP handler accepts a request
|
||||
- **THEN** it MUST decode named DTOs, call `service.Core`, and encode named DTO responses
|
||||
|
||||
#### Scenario: Missing provider is managed
|
||||
- **WHEN** a management action targets a missing provider ID
|
||||
- **THEN** the platform MUST return a stable `404` JSON error response
|
||||
|
||||
### Requirement: AI provider console page is functional
|
||||
The management console SHALL replace the placeholder AI provider page with a functional operational view for configured providers.
|
||||
|
||||
#### Scenario: Operator opens AI provider page
|
||||
- **WHEN** the AI provider page renders
|
||||
- **THEN** it MUST show provider counts, status distribution, configured model counts, and a provider table
|
||||
|
||||
#### Scenario: Operator edits provider form
|
||||
- **WHEN** an operator creates or edits a provider through the page form
|
||||
- **THEN** the page MUST submit named API requests and refresh or update the provider list without displaying raw key material
|
||||
|
||||
#### Scenario: Operator uses provider actions
|
||||
- **WHEN** an operator triggers enable/disable, test, or model-list actions
|
||||
- **THEN** the page MUST call the matching API client methods and display the redacted result state
|
||||
|
||||
### Requirement: Frontend contracts are centralized
|
||||
The frontend SHALL keep AI provider API types and client methods in `platform_web/api` and SHALL keep shared UI contracts out of page-local hidden types.
|
||||
|
||||
#### Scenario: Page consumes provider data
|
||||
- **WHEN** `AiProvidersPage` needs provider data or actions
|
||||
- **THEN** it MUST use named API types and `PlatformApiClient` methods instead of inline fetch contracts
|
||||
|
||||
#### Scenario: Frontend tests inspect provider types
|
||||
- **WHEN** frontend tests check provider response shapes
|
||||
- **THEN** they MUST confirm raw key fields are absent from returned provider data
|
||||
|
||||
### Requirement: AI provider management is verified end to end
|
||||
The change SHALL include backend API/service tests, frontend tests/build, a browser walkthrough, structure validation, and strict OpenSpec validation.
|
||||
|
||||
#### Scenario: Verification commands run
|
||||
- **WHEN** the change is complete
|
||||
- **THEN** `go test ./...` from `platform/`, frontend tests/build, `scripts/check-structure.sh`, and `openspec validate implement-ai-provider-management --strict` MUST pass
|
||||
|
||||
#### Scenario: Browser walkthrough runs
|
||||
- **WHEN** frontend AI provider page behavior is claimed complete
|
||||
- **THEN** a browser walkthrough MUST verify the page renders, exposes the AI provider workflow, and does not show raw credential fields
|
||||
@@ -0,0 +1,36 @@
|
||||
## 1. Backend Contracts And Service
|
||||
|
||||
- [x] 1.1 Add AI provider update, status, test, and model-list DTO contracts with redacted response shapes.
|
||||
- [x] 1.2 Extend `service.Core` with AI provider update, status, local test, and model-list methods using existing validators and repositories.
|
||||
|
||||
## 2. Backend API Surface
|
||||
|
||||
- [x] 2.1 Implement AI provider management routes for update, status, test, and models using named DTOs and service methods.
|
||||
- [x] 2.2 Update platform route/protocol documentation for implemented AI provider management routes and deferred live invocation.
|
||||
- [x] 2.3 Add backend service/API tests for update, enable/disable, test/models, missing resources, duplicate handling, and raw key rejection.
|
||||
|
||||
## 3. Frontend Contracts And Page
|
||||
|
||||
- [x] 3.1 Add centralized `platform_web/api` AI provider types and `PlatformApiClient` methods for list/create/update/status/test/models.
|
||||
- [x] 3.2 Replace the placeholder AI provider page with a functional operational management view using the API client and no raw key display.
|
||||
- [x] 3.3 Add frontend tests for page rendering, management actions, API client calls, and raw-key field absence.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run `go test ./...` from `platform/` and record evidence.
|
||||
- [x] 4.2 Run frontend tests/build from `platform_web/` and record evidence.
|
||||
- [x] 4.3 Run a browser walkthrough of the AI provider page and record evidence.
|
||||
- [x] 4.4 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 4.5 Run `openspec validate implement-ai-provider-management --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `go test ./domain ./dto`: passed.
|
||||
- `go test ./service ./api`: passed.
|
||||
- `go test ./...` from `platform/`: passed.
|
||||
- `npm test` from `platform_web/`: passed.
|
||||
- `npm run typecheck` from `platform_web/`: passed.
|
||||
- `npm run build` from `platform_web/`: passed.
|
||||
- Browser walkthrough with Playwright Chromium against `http://127.0.0.1:5173/#/aiProviders`: passed; rendered AI provider management, created `Browser Check Provider`, tested metadata, toggled status, and verified visible text did not contain `rawApiKey`, `api_key=`, `Bearer `, or `sk-`.
|
||||
- `scripts/check-structure.sh`: passed.
|
||||
- `openspec validate implement-ai-provider-management --strict`: passed.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-06
|
||||
@@ -0,0 +1,61 @@
|
||||
## Context
|
||||
|
||||
The existing artifact transfer channel handles run-to-platform upload with chunk/resume semantics and platform-owned artifact metadata. Browser consumers need the opposite user-facing surface: list and download available artifacts from server/job/plugin contexts through platform authorization. The browser should receive safe references and platform routes, not raw storage locations.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Add platform artifact download metadata and content routes for authorized browser users and plugin bridge actions.
|
||||
- Support bounded chunk/range reads or download responses that can report progress in the frontend.
|
||||
- Enforce artifact owner scope, user/server access, plugin permissions, availability state, and response redaction.
|
||||
- Add frontend API client methods and UI controls for artifact download/open from operational pages.
|
||||
- Add plugin bridge artifact helpers that return safe references rather than raw paths or storage credentials.
|
||||
- Verify with tests and browser walkthrough.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No external object storage backend or presigned raw storage URLs.
|
||||
- No browser direct access to run endpoints, host filesystem paths, sockets, or storage backend credentials.
|
||||
- No artifact upload from browser unless a future change explicitly adds it.
|
||||
- No archive extraction, malware scanning, lifecycle cleanup, billing, cloud host sales, or unrelated marketplace behavior.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Browser downloads go through platform routes
|
||||
|
||||
The platform exposes artifact content through authorized API routes. Any download URL or token is a platform route scoped to the requesting user/session and artifact, not a raw backend location.
|
||||
|
||||
Alternative considered: return storage adapter paths or presigned backend URLs. Rejected because no storage backend exists yet and raw locations can leak internals.
|
||||
|
||||
### Decision 2: Artifact availability is required for download
|
||||
|
||||
Only artifacts in an available/complete state can be downloaded by browser consumers. Uploading, failed, missing, or unauthorized artifacts return stable safe errors.
|
||||
|
||||
Alternative considered: stream partial uploading artifacts. Rejected because partial reads complicate integrity and user expectations.
|
||||
|
||||
### Decision 3: Plugin bridge receives artifact references, not bytes by default
|
||||
|
||||
Bridge actions can request artifact metadata/open/download references. Large byte transfer stays in platform/browser client code, preserving bounded payloads across plugin bridge messages.
|
||||
|
||||
Alternative considered: pass base64 artifact bytes through plugin page bridge messages. Rejected because large payloads can block UI and violate channel separation.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] In-memory artifact payload storage limits realistic download size. Mitigation: keep interfaces ready for storage adapters and test bounded content behavior.
|
||||
- [Risk] Browser downloads can expose sensitive server files if ownership checks are weak. Mitigation: validate artifact owner scope, user/server access, plugin permissions, and availability before content reads.
|
||||
- [Risk] Plugin pages may expect direct bytes. Mitigation: provide safe artifact references and frontend host download helpers.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add platform artifact download contracts, validators, service methods, routes, and docs.
|
||||
2. Add frontend API client, UI controls, bridge host helpers, and tests.
|
||||
3. Add plugin SDK artifact reference helpers/tests if needed.
|
||||
4. Run browser walkthrough, structure check, and strict OpenSpec validation.
|
||||
|
||||
Rollback removes browser download routes/client integration and this change's artifacts before plugin pages depend on them.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which durable artifact storage adapter should back downloads after in-memory transfer state is replaced?
|
||||
- Whether browser upload should be a separate future transfer direction.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
Run can upload artifacts to the platform transfer channel, but operators and plugin pages still need a safe way to discover, download, and hand off artifact references in the browser. Artifact download must remain platform-mediated so browser code never receives raw storage backend credentials, raw host paths, or direct run sockets.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add platform artifact download/read APIs that authorize artifact access and stream or return bounded content through platform-owned routes.
|
||||
- Add browser-facing artifact metadata, download URL/token, chunk read, and transfer progress contracts without exposing storage internals.
|
||||
- Add frontend API client and UI behavior for artifact download from server/job/plugin contexts.
|
||||
- Integrate plugin bridge artifact actions with browser-safe artifact references.
|
||||
- Add platform and frontend tests plus browser walkthrough for download, access denial, resume/progress, and no-secret rendering.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `artifact-download-and-browser-transfer`: Browser-safe platform-mediated artifact discovery, download, and plugin bridge transfer references.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- Builds on `artifact-transfer-channel`, plugin bridge contracts, and server/job workflows without changing run upload semantics.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` artifact DTOs, validators, services, APIs, and docs.
|
||||
- Affects `platform_web/` API contracts, artifact UI/download behavior, plugin bridge host integration, and tests.
|
||||
- May affect `plugins/` SDK artifact reference helpers/tests.
|
||||
- Does not add external object storage, presigned raw backend URLs, direct plugin-to-run access, billing, cloud host sales, or unrelated SaaS marketplace features.
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Browser artifact downloads are platform-mediated
|
||||
|
||||
The platform SHALL provide browser-safe artifact metadata and content download APIs that authorize access and do not expose storage backend credentials, raw host paths, or direct run sockets.
|
||||
|
||||
#### Scenario: Authorized artifact download starts
|
||||
- **WHEN** an authorized operator requests download metadata for an available artifact in an accessible server or job context
|
||||
- **THEN** the platform MUST return a browser-safe artifact reference or platform download route with filename, content type, size, checksum, and expiry metadata
|
||||
|
||||
#### Scenario: Unauthorized artifact download is denied
|
||||
- **WHEN** a user or plugin page requests an artifact outside its server, job, or plugin permission scope
|
||||
- **THEN** the platform MUST return a stable safe error and MUST NOT return artifact bytes or download references
|
||||
|
||||
### Requirement: Artifact content reads are bounded and integrity-aware
|
||||
|
||||
The platform SHALL validate artifact availability, requested range/chunk bounds, checksum metadata, and response size before returning artifact content to browser clients.
|
||||
|
||||
#### Scenario: Available artifact content is read
|
||||
- **WHEN** a browser client requests a valid byte range or full download for an available artifact
|
||||
- **THEN** the platform MUST return content with safe headers and integrity metadata
|
||||
|
||||
#### Scenario: Incomplete artifact cannot be downloaded
|
||||
- **WHEN** a browser client requests an uploading, failed, missing, or incomplete artifact
|
||||
- **THEN** the platform MUST reject the request and leave artifact state unchanged
|
||||
|
||||
### Requirement: Frontend exposes artifact download workflow
|
||||
|
||||
The frontend SHALL provide centralized API client methods and UI controls for artifact download/open flows from server, job, or plugin contexts.
|
||||
|
||||
#### Scenario: Operator downloads artifact
|
||||
- **WHEN** an operator clicks an artifact download/open action
|
||||
- **THEN** the page MUST request platform download metadata/content, show progress or completion state, and avoid raw path/credential display
|
||||
|
||||
#### Scenario: Download fails safely
|
||||
- **WHEN** an artifact download request fails validation, authorization, or availability checks
|
||||
- **THEN** the UI MUST show a safe error state without exposing backend paths, run sockets, storage credentials, or raw secrets
|
||||
|
||||
### Requirement: Plugin bridge uses artifact references safely
|
||||
|
||||
The plugin bridge SHALL expose artifact actions as safe metadata or download references rather than raw bytes, host paths, direct run endpoints, or storage backend credentials.
|
||||
|
||||
#### Scenario: Plugin page opens artifact reference
|
||||
- **WHEN** a plugin page requests an allowed artifact action
|
||||
- **THEN** the platform/host MUST return a scoped artifact reference that the browser host can download through platform APIs
|
||||
|
||||
#### Scenario: Plugin page lacks artifact permission
|
||||
- **WHEN** a plugin page requests artifact access without required manifest/page permission
|
||||
- **THEN** the platform MUST deny the request before returning metadata, bytes, or download references
|
||||
|
||||
### Requirement: Artifact download is verified end to end
|
||||
|
||||
The change SHALL include backend tests, frontend tests/build, plugin SDK tests if artifact bridge helpers are added, browser walkthrough evidence, structure validation, and strict OpenSpec validation.
|
||||
|
||||
#### Scenario: Verification commands pass
|
||||
- **WHEN** the change is complete
|
||||
- **THEN** platform tests, platform_web tests/typecheck/build, relevant plugin tests, `scripts/check-structure.sh`, and `openspec validate implement-artifact-download-and-browser-transfer --strict` MUST pass
|
||||
@@ -0,0 +1,46 @@
|
||||
## 1. Platform Artifact Download Contracts
|
||||
|
||||
- [x] 1.1 Add domain and DTO contracts for browser artifact metadata, download references, range/content requests, progress, and safe errors.
|
||||
- [x] 1.2 Add validators for artifact IDs, owner/user/plugin scope, availability state, range bounds, response size, checksum metadata, and unsafe secret/path/socket content.
|
||||
- [x] 1.3 Add service methods for authorized artifact metadata lookup, download reference creation, and bounded content reads.
|
||||
|
||||
## 2. Platform Artifact Download API
|
||||
|
||||
- [x] 2.1 Implement artifact metadata/download reference route using named DTOs and service methods.
|
||||
- [x] 2.2 Implement bounded artifact content/range route with safe headers and integrity metadata.
|
||||
- [x] 2.3 Integrate plugin bridge artifact actions with safe artifact references.
|
||||
- [x] 2.4 Update platform route/protocol documentation for browser artifact download and deferred storage backend behavior.
|
||||
- [x] 2.5 Add platform tests for successful download, range reads, unavailable artifacts, unauthorized scope, unsafe references, and no raw path/credential responses.
|
||||
|
||||
## 3. Frontend Browser Transfer
|
||||
|
||||
- [x] 3.1 Add centralized `platform_web/api` artifact download types and client methods.
|
||||
- [x] 3.2 Add UI controls/state for artifact download/open flows from relevant server/job/plugin contexts.
|
||||
- [x] 3.3 Add bridge host handling for artifact references and browser-mediated download actions.
|
||||
- [x] 3.4 Add frontend tests for progress/success/error states, unauthorized failures, and no raw secret/path rendering.
|
||||
|
||||
## 4. Plugin SDK Artifact Helpers
|
||||
|
||||
- [x] 4.1 Add or update plugin SDK helpers for artifact bridge request/reference parsing if bridge artifact actions need new helper types.
|
||||
- [x] 4.2 Add plugin tests for artifact reference helpers and forbidden direct run/storage access assumptions if helper code changes.
|
||||
|
||||
## 5. Verification
|
||||
|
||||
- [x] 5.1 Run `cd platform && go test ./...` and record evidence.
|
||||
- [x] 5.2 Run `cd platform_web && npm run typecheck && npm test && npm run build` and record evidence.
|
||||
- [x] 5.3 Run relevant plugin tests/typecheck if plugin SDK helpers changed and record evidence.
|
||||
- [x] 5.4 Run browser walkthrough for artifact download/browser transfer and record evidence.
|
||||
- [x] 5.5 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 5.6 Run `openspec validate implement-artifact-download-and-browser-transfer --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- 1.1-2.5: `cd platform && go test ./api -run TestArtifactDownload` passed, covering browser-safe references, bounded content/range reads, unavailable artifact rejection, unauthorized scope denial, bridge `artifacts.open`, and forbidden fragment checks.
|
||||
- 3.1-3.4: `cd platform_web && npm run typecheck` passed. `cd platform_web && npm test -- --run api/client.test.ts utils/pluginBridgeHost.test.ts pages/ServerDetailPage.test.tsx` passed, covering artifact client methods, chunk metadata, bridge artifact reference parsing/rejection, and server detail artifact workflow source checks.
|
||||
- 4.1-4.2: `cd plugins && npm run typecheck` passed. `cd plugins && npm test` passed, covering `createArtifactOpenRequest`, `parseArtifactReference`, permission checks, and rejection of direct storage URL assumptions.
|
||||
- 5.1: `cd platform && go test ./...` passed.
|
||||
- 5.2: `cd platform_web && npm run typecheck` passed; `cd platform_web && npm test` passed; `cd platform_web && npm run build` passed.
|
||||
- 5.3: `cd plugins && npm run typecheck` passed; `cd plugins && npm test` passed.
|
||||
- 5.4: Browser walkthrough passed with a temporary local mock server and headless Chrome: opened server detail, selected `操作历史`, clicked artifact `打开`, observed `已打开 artifact-walk.bin`, and checked rendered text for forbidden path/token/storage fragments. Temporary walkthrough files were removed.
|
||||
- 5.5: `scripts/check-structure.sh` passed.
|
||||
- 5.6: `openspec validate implement-artifact-download-and-browser-transfer --strict` reported `Change 'implement-artifact-download-and-browser-transfer' is valid`. PostHog telemetry flush logged DNS errors afterward, but validation exited 0.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-03
|
||||
@@ -0,0 +1,86 @@
|
||||
## Context
|
||||
|
||||
Run control, job lifecycle, and durable log ingest are implemented as separate HTTP JSON channels. Artifact metadata exists in the platform, and job results can reference artifacts, but there is no transfer workflow that can move large run-produced files into platform-managed artifact records with resume and checksum semantics.
|
||||
|
||||
This change implements the first run-to-platform artifact upload channel. Platform storage remains in memory and artifact payloads are held only long enough to prove chunk ordering and final checksum behavior. The channel is intentionally separate from control, jobs, logs, and the optional game client bridge so large payloads do not share those routes or DTOs.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Define typed artifact transfer payloads in `run/protocol` and matching platform DTO/domain contracts.
|
||||
- Add platform artifact transfer routes for open, chunk upload, resume/status, and complete.
|
||||
- Validate active run session, owner relationship, transfer identity, bounded chunk size, chunk checksum, byte ranges, resume state, and final checksum.
|
||||
- Update existing `Artifact` metadata from `uploading` to `available` only after every chunk is present and the final checksum matches.
|
||||
- Add a run-side artifact spool/queue that persists unacknowledged chunk upload requests and deletes them only after platform acknowledgement.
|
||||
- Extend `run/api.PlatformClient` with typed artifact transfer methods.
|
||||
- Add tests for platform service/API transfer behavior, resume, duplicate chunk acknowledgement, checksum errors, completion errors, run spool retention, and client request/response handling.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No platform-to-run download flow, browser upload/download UI, external object storage backend, presigned URL flow, or streaming transport.
|
||||
- No plugin bridge file APIs, AI artifact inspection, archive extraction, or artifact lifecycle cleanup jobs.
|
||||
- No raw host paths, raw credentials, direct sockets, logs, or job result bodies inside artifact chunk requests.
|
||||
- No billing, cloud host sales, agent-provider/cloud-provider workflows, or direct plugin-to-run access.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: HTTP JSON chunk endpoints first
|
||||
|
||||
The initial channel uses separate JSON `POST` endpoints under `/api/v1/run/artifacts/*`: `open`, `chunks`, `status`, and `complete`. Chunk payloads use JSON byte encoding, which Go represents as base64, and validators enforce a bounded maximum chunk size.
|
||||
|
||||
Alternative considered: multipart upload or object-storage signed URLs. Rejected for this change because there is no storage backend yet, and the first requirement is to prove protocol, validation, resume, and checksum semantics in tests.
|
||||
|
||||
### Decision 2: Run uploads only in this change
|
||||
|
||||
The transfer direction is explicit but only `upload` is accepted. Platform-to-run download will need separate authorization, cache, and throttling semantics after upload behavior is stable.
|
||||
|
||||
Alternative considered: implementing upload and download together. Rejected because download would add browser/plugin access questions and storage-adapter behavior that are outside this queue item.
|
||||
|
||||
### Decision 3: Existing Artifact metadata remains the public resource
|
||||
|
||||
Opening a transfer creates or validates the existing `Artifact` metadata record in `uploading` state. Completion updates that same record to `available`; failed checksum or missing chunk errors leave the artifact non-available.
|
||||
|
||||
Alternative considered: adding a separate persisted transfer model now. Rejected because current platform persistence is in-memory and the transfer session can stay behind `service.Core` until a database-backed storage change exists.
|
||||
|
||||
### Decision 4: Chunks are accepted idempotently by checksum
|
||||
|
||||
The platform records received chunk indexes, byte ranges, sizes, checksums, and payload bytes in memory. Re-uploading the same chunk with the same checksum returns a duplicate acknowledgement; re-uploading a different payload for an acknowledged index is rejected.
|
||||
|
||||
Alternative considered: allowing overwrite of existing chunk indexes. Rejected because resumable upload cleanup must be deterministic and conflicting retries should be visible immediately.
|
||||
|
||||
### Decision 5: Owner authorization is platform mediated
|
||||
|
||||
Run uploads are accepted only for job-owned or server-instance-owned artifacts that belong to the requesting run endpoint. Platform/plugin-owned artifact records can still be created through metadata APIs, but this run transfer channel does not let a run endpoint spoof unrelated owners.
|
||||
|
||||
Alternative considered: accepting any artifact owner kind. Rejected because run must not become a direct write path for platform/plugin-owned data without an explicit authorization change.
|
||||
|
||||
### Decision 6: Run spool stores chunk upload requests, not host paths
|
||||
|
||||
The run-side artifact spool writes one JSON file per pending chunk request. It stores the bounded request payload needed for retry and never stores or exposes the local host path that originally produced the bytes.
|
||||
|
||||
Alternative considered: storing file path plus offset for retry. Rejected because run must enforce scoped paths and must not expose raw host paths through platform-facing transfer state.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] In-memory platform chunk storage disappears on restart. Mitigation: keep transfer state behind `service.Core`; storage adapters and durable transfer sessions can replace it later.
|
||||
- [Risk] JSON/base64 chunks are inefficient for large production artifacts. Mitigation: enforce bounded chunks now and leave streaming/object-storage transfer to a later change.
|
||||
- [Risk] No background artifact uploader exists. Mitigation: run client and spool semantics are implemented and tested; scheduling and priority throttling can build on them later.
|
||||
- [Risk] Upload-only support does not cover all artifact use cases. Mitigation: explicitly keep direction in the protocol so a future download change can extend without renaming the channel.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add artifact transfer protocol, DTO, domain, validation, and service contracts.
|
||||
2. Add platform API handlers and tests for open, chunk upload, resume/status, and complete.
|
||||
3. Add run artifact spool implementation and tests.
|
||||
4. Add run client methods and tests.
|
||||
5. Update protocol and route docs.
|
||||
6. Verify with platform tests, run tests, structure check, and strict OpenSpec validation.
|
||||
|
||||
Rollback before dependent changes is removal of the artifact transfer route/client/spool additions and this OpenSpec change. After server workflows depend on artifact transfer, rollback must use a new OpenSpec change.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which durable artifact storage backend should be implemented first: local segments, filesystem package storage, S3-compatible object storage, or another adapter?
|
||||
- What production chunk size, concurrency limits, and backoff policy should artifact uploaders use?
|
||||
- How should platform-to-run download authorization interact with plugin pages and server management workflows?
|
||||
@@ -0,0 +1,29 @@
|
||||
## Why
|
||||
|
||||
Jobs and logs now have separate run-platform channels, but large files still only exist as artifact metadata or opaque result references. This change adds the first artifact transfer channel so run can upload and resume bounded file chunks with checksum verification without blocking control, job, or log traffic.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add typed run artifact transfer protocol payloads for transfer creation, chunk upload, resume status, and completion acknowledgements.
|
||||
- Add platform API routes that create artifact transfer sessions, accept bounded chunks, validate sequence/order/checksums, report resume state, and complete verified artifacts.
|
||||
- Extend platform service behavior to store chunk state in memory, update existing artifact metadata, and keep artifact transfer traffic separate from control, job, and log workflows.
|
||||
- Add a run-side local artifact transfer queue/spool abstraction that records pending chunk manifests and removes chunks only after platform acknowledgement.
|
||||
- Extend the run-side platform client with typed artifact transfer methods.
|
||||
- Add platform service/API tests and run queue/client tests covering chunk resume, checksum failures, completion validation, retry cleanup, and channel isolation assumptions.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `artifact-transfer-channel`: Chunked and resumable run-to-platform artifact transfer, checksum validation, local retry retention, and transfer completion workflow.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` and `run/` only.
|
||||
- Adds Go protocol/DTO/domain/service/API/queue code and tests for artifact transfer.
|
||||
- Updates run/platform protocol and route documentation.
|
||||
- Does not implement browser upload/download UI, external object storage backends, plugin bridge file access, AI artifact inspection, billing, cloud host sales, or direct plugin/run access.
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Artifact transfer channel is separate from other run channels
|
||||
|
||||
The platform SHALL expose artifact transfer behavior through dedicated run artifact routes and SHALL NOT require control, job, or log routes to carry artifact chunk payloads.
|
||||
|
||||
#### Scenario: Dedicated artifact routes handle chunks
|
||||
- **WHEN** a registered run endpoint uploads an artifact chunk
|
||||
- **THEN** the request is handled by a run artifact transfer route and no control, job, or log route accepts the chunk payload
|
||||
|
||||
### Requirement: Run opens upload transfer sessions
|
||||
|
||||
The platform SHALL allow an active run session to open an upload transfer for a job-owned or server-instance-owned artifact assigned to that run endpoint.
|
||||
|
||||
#### Scenario: Valid upload session opens
|
||||
- **WHEN** a run endpoint opens an upload transfer with a valid session token, artifact metadata, owner, total size, chunk size, checksum, and idempotency key
|
||||
- **THEN** the platform returns an accepted transfer ID, records the artifact in uploading state, and reports no received chunks
|
||||
|
||||
#### Scenario: Invalid owner is rejected
|
||||
- **WHEN** a run endpoint opens an upload transfer for an artifact owner that is not assigned to that run endpoint
|
||||
- **THEN** the platform rejects the request without marking the artifact available
|
||||
|
||||
### Requirement: Platform validates chunk upload integrity
|
||||
|
||||
The platform SHALL validate artifact transfer ID, run session, chunk index, byte range, payload size, and chunk checksum before acknowledging an uploaded chunk.
|
||||
|
||||
#### Scenario: Valid chunk is acknowledged
|
||||
- **WHEN** a run endpoint uploads a chunk whose byte range, payload size, and checksum match the opened transfer
|
||||
- **THEN** the platform records the chunk and returns an acknowledgement with the accepted chunk index and received chunk list
|
||||
|
||||
#### Scenario: Conflicting duplicate chunk is rejected
|
||||
- **WHEN** a run endpoint uploads a chunk index that was already acknowledged with different payload bytes or checksum
|
||||
- **THEN** the platform rejects the request as a validation error
|
||||
|
||||
### Requirement: Artifact transfer resume state is queryable
|
||||
|
||||
The platform SHALL report the current transfer state, received chunk indexes, next missing chunk index, total chunk count, and completion status for an active artifact transfer.
|
||||
|
||||
#### Scenario: Resume status reports missing chunk
|
||||
- **WHEN** a run endpoint queries transfer status after only part of an artifact has uploaded
|
||||
- **THEN** the platform returns the acknowledged chunk indexes and the next missing chunk index
|
||||
|
||||
### Requirement: Artifact completion verifies full checksum
|
||||
|
||||
The platform SHALL mark an artifact available only after all chunks are present and the final artifact checksum matches the opened transfer metadata.
|
||||
|
||||
#### Scenario: Complete verified artifact
|
||||
- **WHEN** every chunk has been uploaded and the run endpoint completes the transfer with the correct final checksum
|
||||
- **THEN** the platform marks the artifact available and returns the updated artifact metadata
|
||||
|
||||
#### Scenario: Missing chunk prevents completion
|
||||
- **WHEN** the run endpoint completes a transfer before every chunk is present
|
||||
- **THEN** the platform rejects completion and leaves the artifact non-available
|
||||
|
||||
### Requirement: Run retains unacknowledged artifact chunks
|
||||
|
||||
The run executor SHALL persist pending artifact chunk upload requests locally and SHALL remove a chunk from the pending queue only after platform acknowledgement for that artifact transfer and chunk index.
|
||||
|
||||
#### Scenario: Acknowledged chunk is removed from retry queue
|
||||
- **WHEN** a pending artifact chunk receives a platform acknowledgement for the same transfer ID and chunk index
|
||||
- **THEN** the run artifact queue removes that chunk from pending retry state
|
||||
|
||||
#### Scenario: Unacknowledged chunk remains pending
|
||||
- **WHEN** an artifact chunk has not received a matching platform acknowledgement
|
||||
- **THEN** the run artifact queue keeps the chunk available for retry
|
||||
@@ -0,0 +1,35 @@
|
||||
## 1. Artifact Transfer Contracts
|
||||
|
||||
- [x] 1.1 Add typed run artifact transfer protocol payloads in `run/protocol` for open, chunk upload, status/resume, completion, and acknowledgements.
|
||||
- [x] 1.2 Add matching platform DTO/domain contracts and conversion helpers for artifact transfer requests and responses.
|
||||
- [x] 1.3 Add validation rules for active upload direction, owner scope, bounded chunk size, byte ranges, chunk checksums, final checksums, and completion state.
|
||||
|
||||
## 2. Platform Artifact Transfer
|
||||
|
||||
- [x] 2.1 Extend platform service behavior to open upload transfers, accept idempotent chunks, reject conflicting chunks, report resume status, and mark artifacts available only after verified completion.
|
||||
- [x] 2.2 Implement platform artifact transfer HTTP routes using named DTOs and service methods.
|
||||
- [x] 2.3 Add platform service/API tests for successful upload, resume status, duplicate ack, checksum mismatch, invalid owner/session, and missing-chunk completion rejection.
|
||||
|
||||
## 3. Run Artifact Queue And Client
|
||||
|
||||
- [x] 3.1 Implement a run-side local artifact queue that writes pending chunk requests to disk, lists them for retry, and removes acknowledged chunks.
|
||||
- [x] 3.2 Extend `run/api.PlatformClient` with typed artifact transfer methods.
|
||||
- [x] 3.3 Add run queue/client tests for retry retention, acknowledgement cleanup, request paths, JSON payloads, response decoding, and platform error handling.
|
||||
|
||||
## 4. Documentation
|
||||
|
||||
- [x] 4.1 Update run and platform protocol/route documentation to mark artifact open/chunk/status/complete implemented and keep control/job/log/game-client channels separate.
|
||||
|
||||
## 5. Verification
|
||||
|
||||
- [x] 5.1 Run `go test ./...` from `platform/` and record evidence.
|
||||
- [x] 5.2 Run `go test ./...` from `run/` and record evidence.
|
||||
- [x] 5.3 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 5.4 Run `openspec validate implement-artifact-transfer-channel --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- 2026-07-03: `go test ./...` from `platform/` passed.
|
||||
- 2026-07-03: `go test ./...` from `run/` passed.
|
||||
- 2026-07-03: `scripts/check-structure.sh` passed with `structure check passed`.
|
||||
- 2026-07-03: `openspec validate implement-artifact-transfer-channel --strict` passed with `Change 'implement-artifact-transfer-channel' is valid`.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-08
|
||||
@@ -0,0 +1,77 @@
|
||||
## Context
|
||||
|
||||
The architecture stream now has API-backed platform, run, platform_web, and plugin proof, plus a documented local debug workspace that can start the real stack, seed `game.example`, create `server-local-debug`, and verify a manual browser walkthrough. The remaining gap is repeatability: browser acceptance currently lives as task evidence and operator procedure, so regressions can slip in when route text, auth behavior, local fixture setup, plugin marketplace data, lifecycle operation surfaces, or safety redaction drift.
|
||||
|
||||
The automated suite should preserve the existing architecture boundaries. Browser checks must exercise platform_web through platform-owned API routes, not direct run or plugin transports. Fixture setup should reuse the local debug scripts and safe dev plugin manifest instead of inventing a second seed path. The suite should be useful locally and in CI-like verification while staying scoped to the game server management platform.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Provide one automated browser acceptance command that verifies the API-backed local debug console path end to end.
|
||||
- Reuse or orchestrate the documented local debug stack and smoke fixture so acceptance data matches the manual proof path.
|
||||
- Verify login and required first-party routes: 首页、服务器管理、插件市场、用户管理、AI 提供商管理.
|
||||
- Verify server detail and core plugin/server operation surfaces, including plugin marketplace data, lifecycle controls or operation-history proof, and log/artifact references.
|
||||
- Fail when platform_web uses local/demo fallback data, when required API-backed evidence is missing, or when visible content exposes forbidden sensitive fragments.
|
||||
- Record deterministic evidence that can be cited from OpenSpec tasks.
|
||||
|
||||
**Non-Goals:**
|
||||
- Do not change product behavior, visual direction, authorization semantics, or plugin/runtime contracts.
|
||||
- Do not implement a cloud, billing, host marketplace, or unrelated SaaS workflow.
|
||||
- Do not require Docker-only infrastructure, real game binaries, raw credentials, raw AI keys, direct sockets, or plugin/browser direct access to run.
|
||||
- Do not replace unit, API, manifest, or local-debug smoke tests; this suite complements those checks by verifying browser-visible behavior.
|
||||
- Do not broaden acceptance into full visual regression testing or screenshot comparison.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. Reuse the local debug workspace as the acceptance fixture.
|
||||
|
||||
The suite should either self-start the documented local debug stack or require an explicit command that does so, then run `scripts/local-debug-smoke.sh` to seed and verify the platform/run/plugin fixture before browser checks. This keeps the browser acceptance data aligned with `docs/local-debug-workspace.md` and avoids parallel fixture drift.
|
||||
|
||||
Alternative considered: seed browser acceptance through a separate frontend-only mock. That would make the suite faster but would not prove real platform/run/plugin integration or prevent demo-only regressions.
|
||||
|
||||
2. Put the acceptance harness near platform_web but keep stack orchestration at repository script level.
|
||||
|
||||
Browser route assertions are frontend-facing and should live with platform_web tests or a clearly named acceptance harness. Starting platform, run, smoke, and frontend should remain in scripts so contributors can run one documented command without learning test internals.
|
||||
|
||||
Alternative considered: hide all service orchestration inside a test file. That makes local failures harder to diagnose because logs, ports, and reset behavior become less visible than the existing local debug workflow.
|
||||
|
||||
3. Assert stable user-visible and route-level signals, not screenshots.
|
||||
|
||||
The suite should inspect URLs, visible text, buttons/links, and API-backed markers such as `数据已加载`, `账号 API 已连接`, `game.example`, `server-local-debug`, `run-local-debug`, lifecycle controls, and marketplace bridge actions. It should avoid brittle pixel assertions and should not depend on decorative theme details beyond preserving the existing UI test/build gates.
|
||||
|
||||
Alternative considered: screenshot or visual diff acceptance. That is higher maintenance and better suited for a later design-polish workflow.
|
||||
|
||||
4. Centralize fallback and forbidden-fragment scanning.
|
||||
|
||||
Every route check should run a shared scanner for fallback/demo indicators and forbidden fragments: `/Users/`, `/private/`, `unix://`, `tcp://`, `Bearer `, `sk-`, `password=`, `apiKeyRef`, `rawApiKey`, run session tokens, direct run URLs, and plugin-owned transport details. Keeping this scanner shared makes new route coverage safer to add.
|
||||
|
||||
Alternative considered: duplicate string checks per page. That is easy to start but likely to drift and miss new route surfaces.
|
||||
|
||||
5. Produce machine-readable and human-readable evidence.
|
||||
|
||||
The acceptance command should print concise pass/fail output and write an evidence artifact, such as JSON or markdown, listing routes visited, assertions passed, stack URLs, seed evidence directory, and any failure details. OpenSpec tasks should cite that evidence after the command actually runs.
|
||||
|
||||
Alternative considered: rely only on terminal output. Terminal output is useful but too easy to lose during long stream handoffs.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- Port collisions -> Allow configurable local debug ports and make the acceptance command print resolved URLs and log paths.
|
||||
- Browser automation flakiness -> Use deterministic local data, stable route URLs, bounded waits for specific page states, and concise route assertions rather than long click chains.
|
||||
- Long-running service cleanup -> Reuse `scripts/local-debug-reset.sh` and ensure self-started acceptance runs stop tracked processes on success and failure.
|
||||
- False positives from sensitive text inside docs or forms -> Scan only visible browser content and acceptance evidence intended for users, while still treating sensitive visible strings as failures.
|
||||
- Fixture drift from smoke data -> Run or require `scripts/local-debug-smoke.sh` before browser assertions and fail if expected local debug IDs are missing.
|
||||
- Sandbox limitations around localhost listeners or browser tooling -> Document when elevated permissions are needed for local listener tests, while keeping the suite command itself explicit and reproducible.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add the browser acceptance harness and repository command wrapper.
|
||||
2. Reuse the local debug smoke fixture and add evidence output for route assertions and forbidden-fragment scanning.
|
||||
3. Run the new acceptance command against a clean local debug root.
|
||||
4. Run frontend typecheck/tests/build, relevant local debug smoke checks, `scripts/check-structure.sh`, and strict OpenSpec validation.
|
||||
5. Update stream evidence and next pointer after the change is implemented.
|
||||
|
||||
Rollback is straightforward: remove the acceptance harness and command wrapper if it proves unstable; no product runtime state or persisted user data model changes are introduced.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None currently. During implementation, follow existing platform_web test tooling and local debug script conventions rather than adding a new browser framework if a suitable one already exists in the repository.
|
||||
@@ -0,0 +1,26 @@
|
||||
## Why
|
||||
|
||||
The architecture stream now has a repeatable local debug workspace and a manually verified API-backed browser walkthrough, but the walkthrough still depends on an operator remembering route checks, seed order, and forbidden-fragment scans. An automated browser acceptance suite is needed now so required first-party console flows stay real, API-backed, and safe as platform, run, platform_web, and plugin features keep evolving.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add an automated browser acceptance suite for the local debug/API-backed console path.
|
||||
- Cover login and navigation across 首页、服务器管理、插件市场、用户管理、AI 提供商管理, plus server detail and core plugin/server operation surfaces.
|
||||
- Require the suite to seed or reuse the documented local debug fixture before browser checks run.
|
||||
- Require fallback/demo-only data rejection and visible forbidden-fragment scanning on every accepted route.
|
||||
- Require concrete commands that can run the suite locally and in CI-like verification without relying on manual browser-only evidence.
|
||||
- No breaking changes are expected; this change automates an existing verified workflow instead of changing product behavior.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `browser-acceptance-suite`: Defines automated browser acceptance coverage for the API-backed management console, local debug fixture prerequisites, required route assertions, plugin/server lifecycle proof, fallback rejection, forbidden-fragment scanning, and verification commands.
|
||||
|
||||
### Modified Capabilities
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected roots: `platform_web/`, `scripts/`, documentation, and potentially shared local debug fixtures under `platform/`, `run/`, and `plugins/` only as needed to support deterministic acceptance setup.
|
||||
- Expected implementation areas: browser acceptance test harness, local debug stack orchestration or reuse hooks, visible content assertions, forbidden-fragment scanner, route coverage fixtures, and task evidence.
|
||||
- Validation impact: requires frontend typecheck/tests/build, automated browser acceptance command, local debug smoke prerequisites, `scripts/check-structure.sh`, and `openspec validate implement-browser-acceptance-suite --strict`.
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Acceptance suite runs against the real local debug stack
|
||||
The repository SHALL provide an automated browser acceptance suite that verifies platform_web against the API-backed local debug stack and safe game plugin fixture.
|
||||
|
||||
#### Scenario: Suite prepares local debug fixture
|
||||
- **WHEN** the acceptance suite is run from a clean checkout with documented local debug prerequisites
|
||||
- **THEN** it MUST start or reuse platform, run worker, platform_web, and the dev game plugin fixture through documented local debug commands and MUST seed or verify `game.example`, `server-local-debug`, and `run-local-debug` before browser assertions begin
|
||||
|
||||
#### Scenario: Suite uses platform-owned browser API path
|
||||
- **WHEN** platform_web is exercised by the acceptance suite
|
||||
- **THEN** browser requests MUST go through the configured platform API proxy with `VITE_PLATFORM_API_BASE_URL=/api/v1` and MUST NOT require direct run URLs, run credentials, or plugin-owned transports in browser code or visible output
|
||||
|
||||
### Requirement: Acceptance suite verifies first-party console areas
|
||||
The browser acceptance suite SHALL verify the required first-party platform_web areas with an API-backed user session.
|
||||
|
||||
#### Scenario: Suite logs in with local debug user
|
||||
- **WHEN** the acceptance suite opens platform_web
|
||||
- **THEN** it MUST log in with the documented local debug operator account and confirm the session lands on an API-backed workspace rather than local fallback data
|
||||
|
||||
#### Scenario: Suite verifies required routes
|
||||
- **WHEN** browser acceptance route checks run
|
||||
- **THEN** they MUST open 首页、服务器管理、插件市场、用户管理、AI 提供商管理 and assert stable API-backed content for each route
|
||||
|
||||
#### Scenario: Suite rejects fallback content
|
||||
- **WHEN** any required route renders fallback, mock, demo-only, or local-auth fallback content
|
||||
- **THEN** the acceptance suite MUST fail and report the route, visible evidence, and failed assertion
|
||||
|
||||
### Requirement: Acceptance suite verifies plugin and server operation surfaces
|
||||
The browser acceptance suite SHALL verify core plugin/server operation surfaces that prove the console is connected to platform-mediated lifecycle and plugin data.
|
||||
|
||||
#### Scenario: Suite verifies server detail lifecycle surface
|
||||
- **WHEN** the suite opens the local debug server detail route
|
||||
- **THEN** it MUST assert that `Local Debug Example Server`, `server-local-debug`, `game.example`, `run-local-debug`, lifecycle controls, operation history, log entry points, and artifact or artifact-reference entry points are visible or otherwise represented through platform-owned UI state
|
||||
|
||||
#### Scenario: Suite verifies plugin marketplace data
|
||||
- **WHEN** the suite opens the plugin marketplace route or plugin detail surface
|
||||
- **THEN** it MUST assert that `game.example`, manifest reference metadata, installed state, platform-mediated permissions, bridge actions, and lifecycle capabilities are visible without exposing unsafe runtime transport details
|
||||
|
||||
#### Scenario: Suite verifies operation proof without direct run access
|
||||
- **WHEN** the suite triggers or inspects a lifecycle operation
|
||||
- **THEN** it MUST verify platform-owned job or operation-history evidence and MUST NOT rely on platform_web or plugin pages contacting run directly
|
||||
|
||||
### Requirement: Acceptance suite scans visible safety boundaries
|
||||
The browser acceptance suite SHALL scan accepted browser-visible content for fallback indicators and forbidden sensitive fragments.
|
||||
|
||||
#### Scenario: Suite scans each accepted route
|
||||
- **WHEN** a required route or plugin/server operation surface is accepted
|
||||
- **THEN** the suite MUST scan visible text for `/Users/`, `/private/`, `unix://`, `tcp://`, `Bearer `, `sk-`, `password=`, `apiKeyRef`, `rawApiKey`, run session tokens, direct run URLs, and plugin-owned transport details
|
||||
|
||||
#### Scenario: Suite fails on forbidden visible fragments
|
||||
- **WHEN** any forbidden sensitive fragment is visible on an accepted route
|
||||
- **THEN** the suite MUST fail and report the route, matched fragment class, and enough nearby evidence to debug the leak without printing raw credentials
|
||||
|
||||
### Requirement: Acceptance suite produces reproducible evidence
|
||||
The browser acceptance suite SHALL provide concrete commands and evidence outputs that can be used to close OpenSpec tasks.
|
||||
|
||||
#### Scenario: Suite command is documented
|
||||
- **WHEN** contributors read the change documentation or tasks
|
||||
- **THEN** they MUST find concrete commands for running local debug smoke, browser acceptance, frontend checks, structure checks, and strict OpenSpec validation
|
||||
|
||||
#### Scenario: Suite writes acceptance evidence
|
||||
- **WHEN** browser acceptance passes
|
||||
- **THEN** it MUST write or print evidence including stack URLs, seed evidence directory, routes checked, required assertions, fallback scan results, forbidden-fragment scan results, and plugin/server operation proof
|
||||
|
||||
#### Scenario: Suite cleans up self-started services
|
||||
- **WHEN** the suite starts local debug services itself
|
||||
- **THEN** it MUST stop or reset only the documented local debug root after completion or failure, using the same safe reset scope as the local debug workspace
|
||||
@@ -0,0 +1,65 @@
|
||||
## 1. Acceptance Harness and Command Shape
|
||||
|
||||
- [x] 1.1 Add an automated browser acceptance harness in the existing platform_web test/tooling structure, keeping route assertions near frontend code and stack orchestration in repository scripts.
|
||||
- [x] 1.2 Add a repository command wrapper for running browser acceptance against the local debug stack, with configurable `LOCAL_DEBUG_PLATFORM_PORT`, `LOCAL_DEBUG_WEB_PORT`, and `LOCAL_DEBUG_ROOT`.
|
||||
- [x] 1.3 Ensure the command can self-start or explicitly reuse the documented local debug stack, and records the resolved platform URL, platform_web URL, log paths, and evidence directory.
|
||||
- [x] 1.4 Ensure self-started runs clean up with `scripts/local-debug-reset.sh` and only remove allowed local debug roots.
|
||||
|
||||
## 2. Local Debug Fixture Prerequisites
|
||||
|
||||
- [x] 2.1 Reuse `scripts/local-debug-smoke.sh` or equivalent platform-owned setup before browser assertions so `game.example`, `server-local-debug`, and `run-local-debug` exist.
|
||||
- [x] 2.2 Fail early when platform health, API login, plugin manifest validation, plugin registration, run heartbeat, server lifecycle fixture creation, or job/log/artifact/marketplace references are missing.
|
||||
- [x] 2.3 Preserve the existing browser/API boundary: platform_web must use `PLATFORM_API_PROXY` and `VITE_PLATFORM_API_BASE_URL=/api/v1`, with `VITE_ENABLE_LOCAL_AUTH_FALLBACK=false`.
|
||||
- [x] 2.4 Keep fixture commands harmless and bounded, with no Docker-only dependency, real game binaries, raw credentials, raw AI keys, direct sockets, or browser/plugin direct access to run.
|
||||
|
||||
## 3. Browser Route Assertions
|
||||
|
||||
- [x] 3.1 Automate login at platform_web with `operator.local@example.test` / `operator-local` and verify the session lands on an API-backed workspace.
|
||||
- [x] 3.2 Verify 首页 `#/home` includes API-backed platform overview signals such as `平台概览`, `数据已加载`, game/plugin instance counts, and run node state.
|
||||
- [x] 3.3 Verify 服务器管理 `#/servers` includes `Local Debug Example Server` and `server-local-debug`.
|
||||
- [x] 3.4 Verify 插件市场 `#/plugins` includes `game.example`, installed state, manifest reference metadata, lifecycle capabilities, platform-mediated permissions, and bridge actions.
|
||||
- [x] 3.5 Verify 用户管理 `#/users` includes API-connected account data for `operator.local@example.test`.
|
||||
- [x] 3.6 Verify AI 提供商管理 `#/aiProviders` includes API-backed provider rows with redacted key references only.
|
||||
|
||||
## 4. Plugin and Server Operation Surface Assertions
|
||||
|
||||
- [x] 4.1 Verify server detail `#/servers/server-local-debug` includes `Local Debug Example Server`, `game.example@0.1.0`, `run-local-debug`, lifecycle controls, logs, config, plugin controls, AI assistant, and operation history entry points.
|
||||
- [x] 4.2 Trigger or inspect a platform-mediated lifecycle operation and verify platform-owned job or operation-history evidence without requiring direct run access from browser or plugin pages.
|
||||
- [x] 4.3 Verify log and artifact entry points are represented by logical IDs, platform routes, log refs, artifact refs, or safe metadata only.
|
||||
- [x] 4.4 Record route-level assertion results in machine-readable evidence, including URL, required markers, and plugin/server operation proof.
|
||||
|
||||
## 5. Safety and Fallback Scanning
|
||||
|
||||
- [x] 5.1 Add a shared fallback scanner that fails on local/demo/fallback workspace indicators on all accepted routes.
|
||||
- [x] 5.2 Add a shared visible-content forbidden-fragment scanner for `/Users/`, `/private/`, `unix://`, `tcp://`, `Bearer `, `sk-`, `password=`, `apiKeyRef`, `rawApiKey`, run session tokens, direct run URLs, and plugin-owned transport details.
|
||||
- [x] 5.3 Ensure scanner failures report the route, matched fragment class, and safe nearby evidence without printing raw credentials.
|
||||
- [x] 5.4 Confirm sensitive values remain hidden from browser-visible output while safe redacted references such as `secret://...` or `env://...` are allowed when expected.
|
||||
|
||||
## 6. Documentation and Verification
|
||||
|
||||
- [x] 6.1 Document the browser acceptance command and expected evidence output in the appropriate local debug or frontend development documentation.
|
||||
- [x] 6.2 Run `LOCAL_DEBUG_PLATFORM_PORT=18189 LOCAL_DEBUG_WEB_PORT=5183 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-acceptance <browser-acceptance-command>` and record the exact final command after implementation.
|
||||
- [x] 6.3 Run `LOCAL_DEBUG_PLATFORM_PORT=18189 LOCAL_DEBUG_WEB_PORT=5183 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-acceptance scripts/local-debug-smoke.sh` or document why the acceptance command already ran the same smoke prerequisite.
|
||||
- [x] 6.4 Run `cd platform_web && npm run typecheck && npm test && npm run build` and record evidence.
|
||||
- [x] 6.5 Run relevant touched-root checks, including `cd plugins && npm run typecheck && npm run test && npm run validate:manifest`, `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1`, and `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` when implementation touches those roots or local debug orchestration.
|
||||
- [x] 6.6 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 6.7 Run `openspec validate implement-browser-acceptance-suite --strict` and record evidence.
|
||||
- [x] 6.8 Update `openspec/changes/architecture-delivery-stream/delivery-plan.md` and `openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md` after implementation evidence exists, then stop without implementing `polish-platform-interaction-design` unless explicitly asked.
|
||||
|
||||
## Evidence
|
||||
|
||||
- Implemented `platform_web/acceptance/browser-acceptance.mjs`, `scripts/browser-acceptance.sh`, `platform_web` package script `acceptance:browser`, and documentation in `docs/local-debug-workspace.md` plus `platform_web/README.md`.
|
||||
- `node --check platform_web/acceptance/browser-acceptance.mjs` passed.
|
||||
- `bash -n scripts/browser-acceptance.sh` passed.
|
||||
- `LOCAL_DEBUG_PLATFORM_PORT=18189 LOCAL_DEBUG_WEB_PORT=5183 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-acceptance scripts/browser-acceptance.sh` passed after clearing a stale listener from an earlier interrupted run.
|
||||
- Browser acceptance evidence: `/private/tmp/browser-local-debug-acceptance/browser-acceptance/browser-acceptance-evidence.json`, checked at `2026-07-08T05:13:43.494Z`.
|
||||
- Acceptance command ran `scripts/local-debug-smoke.sh` as a prerequisite and wrote seed evidence under `/private/tmp/browser-local-debug-acceptance/smoke`.
|
||||
- Browser routes verified: 首页, 服务器管理, 插件市场, 用户管理, AI 提供商管理, 服务器详情, and 服务器详情 / 插件控制.
|
||||
- Operation proof verified platform API accepted `process.start` for `server-local-debug`, platform-owned jobs endpoint returned `server-lifecycle:server-local-debug:start:e93f12eb71c03646`, and browser operation history exposed platform task records without direct run access.
|
||||
- `cd platform_web && npm run typecheck && npm test && npm run build` passed: 11 test files and 49 tests passed, Vite production build succeeded.
|
||||
- `cd plugins && npm run typecheck && npm run test` passed: 1 test file and 11 tests passed.
|
||||
- `cd plugins && npm run validate:manifest` passed after an escalated rerun because sandboxed `tsx` IPC failed with `listen EPERM`.
|
||||
- `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` passed.
|
||||
- `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` passed after an escalated rerun because sandboxed `httptest` localhost binding failed with `listen tcp6 [::1]:0: bind: operation not permitted`.
|
||||
- `scripts/check-structure.sh` passed.
|
||||
- `openspec validate implement-browser-acceptance-suite --strict` passed. OpenSpec emitted PostHog DNS flush warnings after validation, but the command exited 0 and reported `Change 'implement-browser-acceptance-suite' is valid`.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-06
|
||||
@@ -0,0 +1,59 @@
|
||||
## Context
|
||||
|
||||
The frontend already has a useful diff review UX, but it dispatches config writes by calling `POST /jobs` with `capability=config.write`. That bypasses platform-owned config validation, stale version checks, and scoped file semantics.
|
||||
|
||||
This change creates a platform service boundary for config/file dispatch. Later run worker and plugin bridge changes can execute the queued jobs using the same safe envelopes.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Add config diff preview and approval routes.
|
||||
- Validate expected config version, bounded content size, logical config keys, and server ACLs.
|
||||
- Queue scoped run jobs for approved config/file operations.
|
||||
- Update frontend to call approval routes rather than generic job creation.
|
||||
- Keep all write operations reviewable and auditable.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No real process execution or local file mutation in this change.
|
||||
- No unrestricted file manager or raw path API.
|
||||
- No plugin page bridge execution beyond shared dispatch contracts.
|
||||
- No external storage backend implementation.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Platform service owns write approval
|
||||
|
||||
Config write approval is a service method, not a frontend-generated generic job. It validates server access, config version, diff payload, and logical file key before creating a queued job.
|
||||
|
||||
### Decision 2: File operations use logical keys and refs
|
||||
|
||||
Requests identify server-scoped config/file targets by logical keys or artifact/input refs. Raw absolute paths, home directories, sockets, and credentials are rejected.
|
||||
|
||||
### Decision 3: Diff preview can be pure platform computation
|
||||
|
||||
The backend can compute a textual diff from current config and proposed content without dispatching work. Approval is a separate explicit call.
|
||||
|
||||
### Decision 4: Frontend keeps second confirmation
|
||||
|
||||
ServerDetailPage and AI suggestion flows must keep an explicit confirmation after showing the diff. Approval dispatch happens only after that confirmation.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Queued jobs may not execute until the real run worker change lands. Mitigation: this change verifies dispatch and state, not local mutation.
|
||||
- [Risk] Diff preview duplicates frontend diff code. Mitigation: frontend diff remains display-oriented; backend diff validates dispatch input.
|
||||
- [Risk] Logical file keys may be too narrow. Mitigation: keep schema extensible and add cases through future OpenSpec changes.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add platform contracts and validators for config diff/write and file dispatch.
|
||||
2. Add API handlers and route docs.
|
||||
3. Extend run protocol payload validation for scoped config/file jobs.
|
||||
4. Update ServerDetailPage config and AI write flows.
|
||||
5. Add backend/frontend/run tests and walkthrough.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Whether approved config writes should become a first-class operation resource rather than a job-only response.
|
||||
- Whether future restart/update/delete workflows should share the same approval envelope.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
ServerDetailPage currently previews config diffs locally and then creates a generic `config.write` job directly from the browser. The route catalog still lists config diff review and file operation dispatch as future work. Operators need a platform-mediated, auditable flow that validates config versions and dispatches scoped run jobs without leaking host paths or credentials.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add backend config diff preview and config write approval workflows.
|
||||
- Add scoped file operation dispatch contracts for safe file read/write jobs.
|
||||
- Move config write dispatch out of generic frontend job creation and into platform-owned service methods.
|
||||
- Keep explicit user confirmation before any write job is dispatched.
|
||||
- Update frontend config and AI suggestion write paths to use approved platform routes.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `config-write-and-file-dispatch`: Safe config diff review, approval, and scoped file operation dispatch.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `server-management-workflows`: Server detail config writes use platform lifecycle/file dispatch rules instead of direct generic job creation.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` domain, DTO, validators, service, API handlers, route/protocol docs, and tests.
|
||||
- Affects `run/` protocol validation for scoped config/file job payloads.
|
||||
- Affects `platform_web/` ServerDetailPage config and AI suggestion apply flows.
|
||||
- Does not add unrestricted file browsing, raw path exposure, billing, cloud sales, or direct plugin-to-run access.
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Config diff preview is platform mediated
|
||||
The platform SHALL provide a config diff preview route that compares current server config with proposed content without dispatching a write.
|
||||
|
||||
#### Scenario: Preview accepted
|
||||
- **WHEN** an authorized operator submits proposed config content with the current config version
|
||||
- **THEN** the platform MUST return a bounded diff and MUST NOT create a run job
|
||||
|
||||
#### Scenario: Preview rejects stale config
|
||||
- **WHEN** proposed config content references a stale config version
|
||||
- **THEN** the platform MUST reject the preview and MUST NOT dispatch work
|
||||
|
||||
### Requirement: Config write approval dispatches scoped job
|
||||
The platform SHALL dispatch config writes only after an explicit approval request passes validation.
|
||||
|
||||
#### Scenario: Approved config write queued
|
||||
- **WHEN** an authorized operator approves a reviewed config diff
|
||||
- **THEN** the platform MUST queue a bounded `config.write` job for the server instance and return job metadata
|
||||
|
||||
#### Scenario: Config write hides unsafe internals
|
||||
- **WHEN** the platform dispatches a config write job
|
||||
- **THEN** the request and response MUST NOT expose raw host paths, run credentials, direct sockets, or raw secret values
|
||||
|
||||
### Requirement: File operation dispatch is scoped
|
||||
The platform SHALL provide scoped file operation dispatch for server/plugin workflows using logical file keys or artifact refs.
|
||||
|
||||
#### Scenario: Scoped file read dispatched
|
||||
- **WHEN** an authorized caller requests a declared logical file read
|
||||
- **THEN** the platform MUST queue a bounded file read job with scoped target metadata
|
||||
|
||||
#### Scenario: Unsafe file target rejected
|
||||
- **WHEN** a request includes an absolute path, parent traversal, raw credential, direct socket, or host-local secret path
|
||||
- **THEN** the platform MUST reject the request before creating a job
|
||||
|
||||
### Requirement: Frontend config writes use approval APIs
|
||||
The frontend SHALL use platform config preview and approval APIs for config writes.
|
||||
|
||||
#### Scenario: User previews and approves config write
|
||||
- **WHEN** a user edits config, previews the diff, and confirms approval
|
||||
- **THEN** ServerDetailPage MUST call the approval API and render the returned platform job state
|
||||
|
||||
#### Scenario: Frontend avoids generic write job creation
|
||||
- **WHEN** a config write is initiated from manual edit or AI suggestion
|
||||
- **THEN** the frontend MUST NOT create a generic `config.write` job directly through `POST /jobs`
|
||||
@@ -0,0 +1,58 @@
|
||||
## 1. Config Diff Review Contracts
|
||||
|
||||
- [x] 1.1 Add domain contracts for config diff review, proposed content, approval status, and dispatch metadata.
|
||||
- [x] 1.2 Add DTO contracts for config diff preview, approval, rejection, and dispatch responses.
|
||||
- [x] 1.3 Add validators for bounded config size, allowed file keys, expected config version, and diff content safety.
|
||||
- [x] 1.4 Add service methods for previewing and approving config writes without exposing host paths.
|
||||
|
||||
## 2. File Operation Dispatch Contracts
|
||||
|
||||
- [x] 2.1 Add domain/DTO contracts for scoped file read/write requests.
|
||||
- [x] 2.2 Map file operations to platform job capabilities such as `config.write`, `files.read`, and `files.write`.
|
||||
- [x] 2.3 Enforce plugin/server permissions and role-scoped server access before dispatch.
|
||||
- [x] 2.4 Ensure dispatch payloads use logical file keys or artifact/input refs, not raw host paths.
|
||||
|
||||
## 3. Backend API Surface
|
||||
|
||||
- [x] 3.1 Implement config diff preview route for a server instance.
|
||||
- [x] 3.2 Implement config write approval route that queues a bounded run job.
|
||||
- [x] 3.3 Implement file operation dispatch route for scoped plugin/platform file jobs.
|
||||
- [x] 3.4 Update route/protocol documentation to mark config and file dispatch implemented.
|
||||
|
||||
## 4. Frontend Integration
|
||||
|
||||
- [x] 4.1 Update ServerDetailPage config write flow to call config diff preview API.
|
||||
- [x] 4.2 Update confirmation flow to call config write approval API instead of creating a generic job directly.
|
||||
- [x] 4.3 Keep explicit second confirmation before dispatching any config write.
|
||||
- [x] 4.4 Remove local-only config mutation after job dispatch; show pending platform job state instead.
|
||||
|
||||
## 5. Run Integration Prep
|
||||
|
||||
- [x] 5.1 Extend run protocol job payloads to carry scoped config/file input refs.
|
||||
- [x] 5.2 Add run-side validation for allowed logical paths and bounded write payloads.
|
||||
- [x] 5.3 Add tests proving raw host paths and credentials are rejected.
|
||||
|
||||
## 6. Verification
|
||||
|
||||
- [x] 6.1 Add platform tests for preview, approval, stale config version, unauthorized server access, and unsafe paths.
|
||||
- [x] 6.2 Add frontend tests for diff preview, approval, failure, and no local mutation on dispatch.
|
||||
- [x] 6.3 Run platform, run, and platform_web test/build commands and record evidence.
|
||||
- [x] 6.4 Run browser walkthrough for config diff and write approval.
|
||||
- [x] 6.5 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 6.6 Run `openspec validate implement-config-write-and-file-dispatch --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- 2026-07-06: `cd platform && go test ./domain ./dto ./validator ./service ./api ./model` passed after adding config diff/write contracts, validators, service methods, and API handlers.
|
||||
- 2026-07-06: `cd run && go test ./protocol` passed after adding scoped job target/input refs and run protocol validation tests for raw host paths and raw credential refs.
|
||||
- 2026-07-06: Updated `platform/api/routes.md`, `platform/protocol/server-lifecycle.md`, `run/protocol/job.md`, and `platform_web/api/contracts.md` to document implemented config diff/approval and scoped file dispatch routes/protocol payloads.
|
||||
- 2026-07-06: `cd platform && go test ./service ./api -run 'TestCoreServiceConfigWriteAndFileDispatchAreScoped|TestConfigWriteAndFileDispatchAPIAreScoped'` passed, covering preview, approval, stale config version, unauthorized access, unsafe keys, and scoped file dispatch.
|
||||
- 2026-07-06: `cd platform_web && npm run typecheck` passed after adding config diff/approval/file dispatch API types and client methods.
|
||||
- 2026-07-06: `cd platform_web && npm test -- --run api/client.test.ts pages/ServerDetailPage.test.tsx` passed, covering preview/approval client requests, preview failure surfacing, platform diff mapping, no generic `config.write` job creation, and no local config mutation after approval dispatch.
|
||||
- 2026-07-06: `cd platform && go test ./...` passed.
|
||||
- 2026-07-06: `cd run && go test ./...` passed.
|
||||
- 2026-07-06: `cd platform_web && npm test` passed with 11 files / 40 tests.
|
||||
- 2026-07-06: `cd platform_web && npm run build` passed.
|
||||
- 2026-07-06: Browser walkthrough passed using local platform `127.0.0.1:18090`, Vite `127.0.0.1:5177`, and headless Chrome: logged in, opened `#/servers/server-walkthrough`, edited config, previewed the platform diff, confirmed approval dispatch, saw the returned `config.write` job badge, and verified no `/Users/`, `unix://`, bearer token, raw key, password, or billing fragments were visible.
|
||||
- 2026-07-06: `scripts/check-structure.sh` passed.
|
||||
- 2026-07-06: `openspec validate implement-config-write-and-file-dispatch --strict` reported `Change 'implement-config-write-and-file-dispatch' is valid`; PostHog telemetry flush failed due restricted DNS and did not affect validation.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-07
|
||||
@@ -0,0 +1,62 @@
|
||||
## Overview
|
||||
|
||||
The platform needs two storage shapes:
|
||||
|
||||
- **Metadata store** for users, AI providers, plugins, server instances, run endpoints, jobs, artifacts, log stream metadata, and audit events.
|
||||
- **Log body store** for high-volume append/query log entries.
|
||||
|
||||
The first can be MySQL or another transactional database. The second should not be a row-per-line table for large installations. This change implements a local durable metadata store and a segmented log body store using only the Go standard library, with interfaces that can later gain MySQL/PostgreSQL/ClickHouse/Loki adapters.
|
||||
|
||||
## Metadata Storage
|
||||
|
||||
Current repository interfaces stay unchanged. A new file-backed store wraps the existing in-memory store and persists a snapshot after successful create/update operations. It is suitable for local and single-node deployments, tests, and development environments where no external database is available.
|
||||
|
||||
Configuration:
|
||||
|
||||
- `PLATFORM_STORAGE_BACKEND=memory|file`
|
||||
- `PLATFORM_DATA_DIR=<path>`
|
||||
- `PLATFORM_METADATA_PATH=<path>`
|
||||
|
||||
Default startup uses file-backed storage under `.platform-data/metadata.json`, so data survives restarts. Tests can continue using `repo.NewMemoryStore()`.
|
||||
|
||||
The file store is not positioned as a multi-writer clustered database. A future MySQL adapter should implement the same `repo.Store` interfaces and keep database table models in `platform/model`.
|
||||
|
||||
## Log Body Storage
|
||||
|
||||
`CoreService` currently stores log bodies in memory maps. This change introduces a `LogBodyStore` service boundary:
|
||||
|
||||
- `AppendBatch(streamID, batch)` for validated, contiguous batch appends.
|
||||
- `GetBatch(streamID, firstSeq)` for duplicate/conflict detection.
|
||||
- `Query(streamID, afterSeq, limit)` for bounded cursor reads.
|
||||
|
||||
The local durable implementation writes JSONL segment files:
|
||||
|
||||
- Directory: `<PLATFORM_LOG_DIR>/<safe stream id>/`
|
||||
- Segment naming: `segment-00000000000000000001.jsonl` using the first sequence in that segment.
|
||||
- Each line is one `LogEntry`, keeping append and recovery simple.
|
||||
- A small in-memory index is rebuilt on startup from segment files.
|
||||
|
||||
This keeps control, jobs, and log upload channel semantics unchanged. It also avoids turning MySQL into a log body sink. For large production deployments, the same boundary can route log bodies to ClickHouse/Loki/OpenSearch/object storage and keep MySQL for metadata, stream state, retention policy, and query indexes.
|
||||
|
||||
## Security And Boundaries
|
||||
|
||||
- Storage paths are platform-owned configuration; they are never returned to plugins or frontend responses.
|
||||
- Log query APIs still return bounded entries only.
|
||||
- Run session tokens and bearer sessions remain service-side only.
|
||||
- No raw database credentials are exposed through DTOs.
|
||||
|
||||
## Failure Modes
|
||||
|
||||
- File store creation fails fast on invalid or unwritable paths.
|
||||
- Snapshot writes use temp-file then rename to avoid partial metadata files.
|
||||
- Log segment writes return service errors instead of acknowledging batches that were not durably written.
|
||||
- Existing in-memory tests remain valid; new tests cover restart/reload behavior for file metadata and log body stores.
|
||||
|
||||
## Validation
|
||||
|
||||
- Unit tests for file-backed metadata persistence across store reloads.
|
||||
- Unit tests for segmented log store append, duplicate lookup, cursor query, and reload.
|
||||
- API/service tests for default router admin persistence and log ingest behavior.
|
||||
- `go test ./...` in `platform`.
|
||||
- `scripts/check-structure.sh`.
|
||||
- `openspec validate implement-durable-platform-storage --strict`.
|
||||
@@ -0,0 +1,26 @@
|
||||
## Why
|
||||
|
||||
The platform currently uses in-memory repositories and in-memory log buffers, so users, sessions, jobs, server state, artifacts, and logs disappear when the platform process restarts. Hundreds or thousands of game servers also make row-per-log-line relational storage a poor default: platform metadata needs a durable database, while log bodies need append-friendly segmented storage with bounded cursor reads.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add configurable durable platform storage so the default local platform process no longer depends on volatile in-memory repositories.
|
||||
- Add a local file-backed metadata store for immediate durable operation without external database credentials.
|
||||
- Add a segmented log body store that persists log entries by stream and segment on disk, keeping log query semantics and duplicate detection intact.
|
||||
- Update platform startup configuration to choose memory or durable local storage with explicit data/log paths.
|
||||
- Document that MySQL/PostgreSQL-style databases are appropriate for platform metadata and log indexes, while high-volume log bodies should use segmented object/file storage or a purpose-built log backend such as ClickHouse/Loki/OpenSearch in later changes.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `durable-platform-storage`: Platform metadata and log bodies survive process restarts through configurable durable storage backends.
|
||||
|
||||
### Modified Capabilities
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected backend areas: `platform/config`, `platform/repo`, `platform/service`, `platform/api`, `platform/cmd/platform`, `platform/protocol`.
|
||||
- No frontend page changes.
|
||||
- No external paid services, real database credentials, or network downloads are required for this implementation.
|
||||
- Future MySQL or analytics log backends can be added behind the new storage boundaries without exposing raw host paths, credentials, or direct sockets to plugins or the frontend.
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Durable Metadata Store
|
||||
|
||||
The platform SHALL support a configurable durable metadata store so platform resources survive process restarts without relying on in-memory maps.
|
||||
|
||||
#### Scenario: File-backed platform metadata survives restart
|
||||
|
||||
- **GIVEN** the platform is configured with the file storage backend and a metadata file path
|
||||
- **WHEN** users, server instances, jobs, artifacts, log streams, or other platform resources are created or updated
|
||||
- **THEN** the metadata SHALL be persisted to disk
|
||||
- **AND** recreating the store from the same file SHALL restore those resources.
|
||||
|
||||
#### Scenario: Memory backend remains available for tests
|
||||
|
||||
- **GIVEN** tests or development code explicitly request the memory backend
|
||||
- **WHEN** the platform creates a store
|
||||
- **THEN** it SHALL use the existing in-memory repository behavior without filesystem persistence.
|
||||
|
||||
#### Scenario: Startup seeds local admin once
|
||||
|
||||
- **GIVEN** durable metadata already contains the local platform administrator
|
||||
- **WHEN** the platform starts again
|
||||
- **THEN** startup seeding SHALL be idempotent and SHALL NOT overwrite the existing user.
|
||||
|
||||
### Requirement: Segmented Log Body Storage
|
||||
|
||||
The platform SHALL store high-volume log bodies in an append-friendly segmented log store instead of relying on in-memory maps or a row-per-log-line metadata database.
|
||||
|
||||
#### Scenario: Log ingest persists entries durably
|
||||
|
||||
- **GIVEN** a valid contiguous log batch for an existing stream
|
||||
- **WHEN** the platform accepts the batch
|
||||
- **THEN** the log body entries SHALL be written to the configured log body store before the stream latest sequence is advanced.
|
||||
|
||||
#### Scenario: Duplicate batch detection survives reload
|
||||
|
||||
- **GIVEN** a log batch has already been accepted and the platform restarts
|
||||
- **WHEN** the same batch is submitted again
|
||||
- **THEN** the platform SHALL return a duplicate acknowledgement when the first sequence, last sequence, and checksum match.
|
||||
|
||||
#### Scenario: Cursor query stays bounded
|
||||
|
||||
- **GIVEN** a log stream has many persisted entries
|
||||
- **WHEN** a client queries after a sequence with a limit
|
||||
- **THEN** the platform SHALL return at most the requested bounded number of entries ordered by sequence
|
||||
- **AND** SHALL include next and latest sequence metadata.
|
||||
|
||||
### Requirement: Storage Backend Boundaries
|
||||
|
||||
The platform SHALL separate metadata storage from log body storage and SHALL NOT expose storage paths, database credentials, run sockets, or raw credentials through API responses.
|
||||
|
||||
#### Scenario: Storage details remain platform-owned
|
||||
|
||||
- **GIVEN** plugins or frontend clients request platform resources, logs, artifacts, or bridge actions
|
||||
- **WHEN** responses are generated
|
||||
- **THEN** they SHALL include only bounded DTO data and SHALL NOT include filesystem paths, database DSNs, direct storage backend URLs, run session tokens, or bearer tokens.
|
||||
@@ -0,0 +1,25 @@
|
||||
## 1. OpenSpec Artifacts
|
||||
|
||||
- [x] 1.1 Create proposal, design, spec, and tasks for durable metadata and log storage.
|
||||
- [x] 1.2 Validate the change with `openspec validate implement-durable-platform-storage --strict`.
|
||||
|
||||
## 2. Durable Metadata Store
|
||||
|
||||
- [x] 2.1 Add platform storage configuration for backend, metadata path, data directory, and log directory.
|
||||
- [x] 2.2 Implement a file-backed metadata store that persists repository snapshots and reloads them.
|
||||
- [x] 2.3 Wire platform startup to use the configured durable store by default while keeping memory store available.
|
||||
- [x] 2.4 Add tests proving metadata persistence and default admin idempotency across store reloads.
|
||||
|
||||
## 3. Segmented Log Body Store
|
||||
|
||||
- [x] 3.1 Add a `LogBodyStore` service boundary with append, duplicate lookup, and cursor query operations.
|
||||
- [x] 3.2 Implement an in-memory log body store for tests and a file-segment log body store for durable startup.
|
||||
- [x] 3.3 Refactor log ingest/query service code to use `LogBodyStore` and persist before advancing stream metadata.
|
||||
- [x] 3.4 Add tests for duplicate acknowledgement and cursor query after log store reload.
|
||||
|
||||
## 4. Documentation And Verification
|
||||
|
||||
- [x] 4.1 Document storage backend choices and log storage guidance in platform protocol/API docs.
|
||||
- [x] 4.2 Run `cd platform && go test ./...`.
|
||||
- [x] 4.3 Run `scripts/check-structure.sh`.
|
||||
- [x] 4.4 Run `openspec validate implement-durable-platform-storage --strict`.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-08
|
||||
@@ -0,0 +1,66 @@
|
||||
## Context
|
||||
|
||||
The platform now has real local capabilities across `platform/`, `run/`, `platform_web/`, and `plugins/`: platform can serve API-backed metadata, run can register and execute lifecycle jobs, platform_web can operate against platform APIs, and the local proof plugin can drive server lifecycle through platform-mediated contracts. The remaining local-development gap is repeatability. Contributors currently need to reconstruct proof commands, temporary data roots, setup payloads, frontend proxy settings, browser walkthrough steps, and cleanup procedures from scattered task evidence.
|
||||
|
||||
This change creates a first-party local debug workspace. It should make the real stack easy to boot, reset, inspect, and verify without introducing production deployment scope or bypassing platform mediation.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Provide one documented and/or scripted local workflow for platform, run worker, platform_web, and the dev game plugin path.
|
||||
- Use explicit local ports, environment variables, data roots, spool roots, log roots, and reset commands.
|
||||
- Include smoke checks for platform health, run registration/heartbeat, plugin registration/installation, server lifecycle, logs/artifact references, and API-backed frontend behavior.
|
||||
- Include browser walkthrough requirements for 首页、服务器管理、插件市场、用户管理、AI 提供商管理 and one plugin lifecycle path.
|
||||
- Keep all plugin/browser operations platform-mediated and prove no raw host paths, credentials, direct sockets, run tokens, raw AI keys, or plugin-owned transport details are visible.
|
||||
|
||||
**Non-Goals:**
|
||||
- Do not add cloud deployment, billing, host sales, agent-provider flows, or unrelated SaaS marketplace behavior.
|
||||
- Do not add Docker-only requirements; local workflow may coexist with Docker but must be runnable with repository commands.
|
||||
- Do not replace the existing magical-girl crystal-moonlight platform_web style.
|
||||
- Do not make plugins connect directly to run or expose run sockets/tokens to platform_web.
|
||||
- Do not implement the later automated browser acceptance suite here; this change may define a manual/semiautomated walkthrough that a later change can automate.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. Use repository-owned local scripts/docs instead of only OpenSpec task notes.
|
||||
|
||||
The workflow must survive after the implementation chat. A script plus a short markdown guide is preferable to evidence-only commands because contributors need a stable entry point. The script should print the exact platform, run, and frontend commands and write logs to predictable local files.
|
||||
|
||||
Alternative considered: keep commands solely in `tasks.md`. That satisfies the change once but does not improve day-to-day local debugging.
|
||||
|
||||
2. Keep local data under a disposable workspace root.
|
||||
|
||||
Platform metadata, platform log bodies, run workspace files, and run spool files should live under an explicit root such as `.local-debug/` or `/private/tmp/browser-local-debug-workspace`. Reset must remove only that root and should never delete broad user directories.
|
||||
|
||||
Alternative considered: reuse `.platform-data` and `.run-workspace` defaults. That is convenient but makes reset behavior less auditable and can mix unrelated local experiments.
|
||||
|
||||
3. Use the existing API-backed platform and Vite proxy shape.
|
||||
|
||||
The frontend should run with `PLATFORM_API_PROXY=http://127.0.0.1:<platform-port>` and `VITE_PLATFORM_API_BASE_URL=/api/v1`, proving browser calls go through platform-owned APIs. Browser/plugin pages must not receive direct run URLs or run credentials.
|
||||
|
||||
Alternative considered: have platform_web point directly at a run worker or plugin dev server. That violates the architecture boundaries and is explicitly out of scope.
|
||||
|
||||
4. Seed only safe local fixtures.
|
||||
|
||||
The local workflow may create a dev plugin, one or more server instances, and lifecycle action templates under the scoped run workspace. Fixtures must use logical IDs and harmless commands. They must not require real game binaries, raw credentials, shell launchers, direct sockets, absolute host paths in API payloads, or raw AI keys.
|
||||
|
||||
Alternative considered: require a real game server installation. That would make the debug workflow too heavy and environment-specific for this stream step.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- Port collisions -> Provide configurable env vars and print the resolved ports before starting services.
|
||||
- Background process cleanup is brittle -> Prefer explicit log/PID files and a stop/reset command over hidden shell process management.
|
||||
- Smoke setup can drift from APIs -> Implement smoke using the same public/local API routes and plugin manifest validation used elsewhere.
|
||||
- Browser walkthrough remains manual -> Record exact pages, expected API-backed signals, and forbidden-fragment scan requirements so the later acceptance-suite change can automate it.
|
||||
- Reset can become dangerous -> Scope cleanup to the local debug root and document what is removed before removing it.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add local debug documentation and scripts or command wrappers under the appropriate repository location.
|
||||
2. Add or update tests/smoke checks for generated commands, safe reset scope, and API-backed local fixture setup.
|
||||
3. Run the documented local stack and browser/API walkthrough.
|
||||
4. Record evidence in `tasks.md`, run structure checks and strict OpenSpec validation, and advance the stream pointer.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None currently. If implementation reveals an existing script location convention, follow it rather than inventing a parallel tool layout.
|
||||
@@ -0,0 +1,26 @@
|
||||
## Why
|
||||
|
||||
The architecture stream now has real platform, run, platform_web, and plugin lifecycle proof, but reproducing that stack still requires ad hoc commands, temporary paths, manual fixture setup, and scattered evidence. A first-party local debug workspace is needed so contributors can boot the same API-backed workflow repeatedly, inspect logs clearly, reset state safely, and prove the console is not falling back to demo-only data.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a local debug workflow that starts platform, run worker, platform_web, and one local game management plugin path with documented ports, environment variables, data roots, and log locations.
|
||||
- Add reset and cleanup steps for local platform metadata, log body storage, run workspace state, run spool state, and frontend dev-server state.
|
||||
- Add smoke verification that proves platform health, run registration/heartbeat, plugin registration/installation, server instance lifecycle, log/artifact references, and browser/API-backed console navigation.
|
||||
- Add safety checks proving browser/plugin page surfaces do not expose host paths, raw credentials, run session tokens, direct sockets, raw AI provider keys, or plugin-owned transport details.
|
||||
- Add concrete commands and browser walkthrough requirements so future implementation chats can verify the local debug workflow without inventing a new proof path.
|
||||
- No breaking changes are expected; this change standardizes local orchestration and verification around existing roots.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `local-debug-workspace`: Defines the local developer workflow for running platform, run, platform_web, and one game management plugin together with clear logs, reset steps, API-backed smoke checks, and browser walkthrough evidence.
|
||||
|
||||
### Modified Capabilities
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected roots: `platform/`, `run/`, `platform_web/`, `plugins/`, `scripts/`, and documentation.
|
||||
- Expected implementation areas: local workflow scripts or docs, fixture/setup helpers, reset commands, smoke verification commands, browser walkthrough checklist, and OpenSpec task evidence.
|
||||
- Validation impact: requires platform/run/plugin/frontend command checks where relevant, `scripts/check-structure.sh`, `openspec validate implement-local-debug-workspace --strict`, and a browser walkthrough for the API-backed console path.
|
||||
@@ -0,0 +1,67 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Local debug workspace starts the real stack
|
||||
The repository SHALL provide a local debug workflow that starts platform, run worker, platform_web, and one local game management plugin path using explicit local configuration.
|
||||
|
||||
#### Scenario: Developer starts local debug services
|
||||
- **WHEN** a developer follows the local debug workflow
|
||||
- **THEN** the workflow MUST provide concrete commands or scripts for platform, run worker, and platform_web with explicit local ports, data directories, log directories, run workspace root, run spool root, frontend API proxy, and Vite API base URL
|
||||
|
||||
#### Scenario: Local debug uses API-backed frontend
|
||||
- **WHEN** platform_web is started by the local debug workflow
|
||||
- **THEN** it MUST use platform-owned API routes through the configured proxy and MUST NOT require platform_web to connect directly to run or plugin-owned transports
|
||||
|
||||
### Requirement: Local debug workspace can be reset safely
|
||||
The repository SHALL provide reset or cleanup steps that remove only local debug workspace state and leave unrelated user files, repository source files, and non-debug service data untouched.
|
||||
|
||||
#### Scenario: Developer resets local debug state
|
||||
- **WHEN** a developer runs the documented reset path
|
||||
- **THEN** platform metadata, platform log bodies, run workspace files, run spool files, local fixture state, and local service logs for the debug workspace MUST be removed or reinitialized only within the documented local debug root
|
||||
|
||||
#### Scenario: Reset scope is auditable
|
||||
- **WHEN** a contributor inspects the reset command or script
|
||||
- **THEN** the command MUST show the exact local debug paths it removes and MUST NOT remove broad directories such as the repository root, home directory, `/Users`, `/private`, `/tmp`, or unrelated service data
|
||||
|
||||
### Requirement: Local debug workflow seeds a safe game plugin lifecycle fixture
|
||||
The local debug workflow SHALL seed or document a safe local game plugin fixture that can create and manage at least one server instance through platform-mediated lifecycle APIs.
|
||||
|
||||
#### Scenario: Developer prepares lifecycle fixture
|
||||
- **WHEN** the local debug setup creates plugin/server lifecycle data
|
||||
- **THEN** it MUST register or reuse a local game plugin manifest, install the plugin through platform data, create at least one logical server instance, and use scoped run workspace lifecycle templates with harmless commands
|
||||
|
||||
#### Scenario: Fixture preserves safety boundaries
|
||||
- **WHEN** plugin lifecycle data is visible through platform APIs or platform_web
|
||||
- **THEN** responses MUST NOT expose raw host paths, raw credentials, run session tokens, direct sockets, raw AI provider keys, shell launchers, or plugin-owned transport details
|
||||
|
||||
### Requirement: Local debug workflow includes smoke verification
|
||||
The local debug workflow SHALL include concrete smoke commands that prove the stack is healthy and API-backed before browser acceptance is claimed.
|
||||
|
||||
#### Scenario: Smoke commands verify backend state
|
||||
- **WHEN** smoke verification runs
|
||||
- **THEN** it MUST check platform health, run endpoint registration or heartbeat, plugin registration/installation, server instance lifecycle state, queued or completed lifecycle jobs, and safe log/artifact references through platform APIs
|
||||
|
||||
#### Scenario: Smoke commands reject demo-only fallback
|
||||
- **WHEN** smoke verification inspects frontend or API state
|
||||
- **THEN** it MUST prove platform_web is using the configured platform API and MUST flag local/demo fallback data as a failed smoke condition
|
||||
|
||||
### Requirement: Browser walkthrough verifies first-party areas and safety
|
||||
The local debug workflow SHALL include a browser walkthrough that verifies the API-backed console across required first-party areas and one plugin lifecycle path.
|
||||
|
||||
#### Scenario: Browser walkthrough opens first-party areas
|
||||
- **WHEN** the browser walkthrough runs
|
||||
- **THEN** it MUST open 首页、服务器管理、插件市场、用户管理、AI 提供商管理 with an API-backed user session and confirm the pages are not local fallback views
|
||||
|
||||
#### Scenario: Browser walkthrough verifies plugin lifecycle path
|
||||
- **WHEN** the browser walkthrough operates a local debug server instance
|
||||
- **THEN** it MUST use platform_web to inspect plugin/server details, trigger or verify a platform-mediated lifecycle action, observe operation history or job state, and confirm sibling/log/artifact references remain safe
|
||||
|
||||
#### Scenario: Browser walkthrough scans visible sensitive fragments
|
||||
- **WHEN** the browser walkthrough inspects visible page content
|
||||
- **THEN** it MUST fail if `/Users/`, `/private/`, `unix://`, `tcp://`, `Bearer `, `sk-`, `password=`, `apiKeyRef`, `rawApiKey`, run session tokens, direct run URLs, or plugin-owned transport details are visible
|
||||
|
||||
### Requirement: Local debug workflow is documented and verified
|
||||
The change SHALL include documentation, tests or smoke checks, and final verification commands proving the local debug workflow is reproducible.
|
||||
|
||||
#### Scenario: Verification commands run
|
||||
- **WHEN** the change is complete
|
||||
- **THEN** the documented test/build/smoke commands, `scripts/check-structure.sh`, and `openspec validate implement-local-debug-workspace --strict` MUST pass, and browser walkthrough evidence MUST be recorded if platform_web pages are touched or verified
|
||||
@@ -0,0 +1,83 @@
|
||||
## 1. Local Debug Workflow Definition
|
||||
|
||||
- [x] 1.1 Add or update repository documentation for the local debug workspace, including startup, ports, env vars, data roots, log files, reset, smoke verification, and browser walkthrough.
|
||||
- [x] 1.2 Add scripts or command wrappers for starting platform, run worker, and platform_web with explicit local debug configuration.
|
||||
- [x] 1.3 Add a reset/cleanup path that removes only the documented local debug root and prints or documents exactly what it deletes.
|
||||
- [x] 1.4 Ensure the workflow does not require Docker-only infrastructure, external cloud services, real game binaries, raw credentials, raw AI keys, direct sockets, or browser/plugin direct access to run.
|
||||
|
||||
## 2. Safe Plugin and Server Fixture
|
||||
|
||||
- [x] 2.1 Add or document setup for one local game management plugin fixture using the existing dev plugin manifest or a safe local proof plugin.
|
||||
- [x] 2.2 Add setup steps that create or reuse at least one server instance through platform-owned data/API paths and scoped run workspace lifecycle templates.
|
||||
- [x] 2.3 Ensure fixture commands are harmless and bounded, and that API/platform_web responses expose only logical IDs, platform routes, job refs, log refs, artifact refs, and safe metadata.
|
||||
- [x] 2.4 Add tests or smoke checks that reject raw host paths, raw credentials, run session tokens, direct sockets, raw AI provider keys, shell launchers, and plugin-owned transport details in fixture outputs.
|
||||
|
||||
## 3. Smoke Verification Commands
|
||||
|
||||
- [x] 3.1 Add concrete smoke commands for platform health, run endpoint registration/heartbeat, plugin registration/installation, server instance lifecycle state, lifecycle jobs, and log/artifact references.
|
||||
- [x] 3.2 Add smoke verification that platform_web is configured with `PLATFORM_API_PROXY` and `VITE_PLATFORM_API_BASE_URL=/api/v1`, and that demo/local fallback data is treated as a failure.
|
||||
- [x] 3.3 Run the documented backend smoke commands and record evidence.
|
||||
- [x] 3.4 Run relevant unit/build checks for touched roots, such as `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1`, `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1`, `cd plugins && npm run typecheck && npm run test && npm run validate:manifest`, and `cd platform_web && npm run typecheck && npm test && npm run build` as applicable, then record evidence.
|
||||
|
||||
## 4. Browser Walkthrough
|
||||
|
||||
- [x] 4.1 Start the documented local debug stack and log the exact platform, run worker, and platform_web commands used.
|
||||
- [x] 4.2 In a browser with an API-backed user session, open 首页、服务器管理、插件市场、用户管理、AI 提供商管理 and confirm no page is using local fallback data.
|
||||
- [x] 4.3 Use the browser to inspect a local debug plugin/server lifecycle path, including server detail, plugin detail or marketplace data, operation history, and log/artifact references.
|
||||
- [x] 4.4 Scan visible browser content for forbidden fragments: `/Users/`, `/private/`, `unix://`, `tcp://`, `Bearer `, `sk-`, `password=`, `apiKeyRef`, `rawApiKey`, run session tokens, direct run URLs, and plugin-owned transport details.
|
||||
- [x] 4.5 Record browser walkthrough evidence in this tasks file only after the walkthrough has actually run.
|
||||
|
||||
## 5. Final Verification and Stream Handoff
|
||||
|
||||
- [x] 5.1 Record implementation evidence in this tasks file only after each command, smoke check, or browser walkthrough has actually run.
|
||||
- [x] 5.2 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 5.3 Run `openspec validate implement-local-debug-workspace --strict` and record evidence.
|
||||
- [x] 5.4 Update `openspec/changes/architecture-delivery-stream/delivery-plan.md` to mark `implement-local-debug-workspace` complete only after evidence exists and move the next queue item to active.
|
||||
- [x] 5.5 Update `openspec/changes/architecture-delivery-stream/NEXT_CHANGE.md` with the next implementation/generator handoff after this change closes.
|
||||
|
||||
## Evidence
|
||||
|
||||
- Added local debug documentation and repository pointers:
|
||||
- `docs/local-debug-workspace.md` documents startup, ports, env vars, data roots, log files, reset scope, smoke verification, browser walkthrough, account credentials, and manual commands.
|
||||
- `README.md` points contributors to `scripts/local-debug-start.sh`, `scripts/local-debug-smoke.sh`, `LOCAL_DEBUG_SELF_START=true`, and the local debug guide.
|
||||
- `plugins/docs/local-development.md` documents the dev plugin fixture and safe API-backed proof path.
|
||||
- Added local debug scripts:
|
||||
- `scripts/local-debug-env.sh` centralizes `LOCAL_DEBUG_*`, platform, run, frontend, and forbidden-fragment settings.
|
||||
- `scripts/local-debug-start.sh` starts platform, run worker, and platform_web with explicit logs, PIDs, ports, data roots, run workspace root, run spool root, Vite proxy, and fallback disabled.
|
||||
- `scripts/local-debug-stop.sh` stops only tracked local-debug PIDs.
|
||||
- `scripts/local-debug-reset.sh` refuses unexpected roots and deletes only `<repo>/.local-debug`, `/private/tmp/browser-local-debug-*`, or `/tmp/browser-local-debug-*`.
|
||||
- `scripts/local-debug-smoke.sh` verifies platform health, API login, dev plugin manifest validation, plugin registration, run heartbeat, server lifecycle workflow creation, jobs, log streams, artifacts, marketplace refs, frontend proxy env, fallback disabled, and forbidden-fragment absence.
|
||||
- Script syntax check passed:
|
||||
- `bash -n scripts/local-debug-env.sh scripts/local-debug-start.sh scripts/local-debug-stop.sh scripts/local-debug-reset.sh scripts/local-debug-smoke.sh`
|
||||
- Frontend verification passed:
|
||||
- `cd platform_web && npm run typecheck`
|
||||
- `cd platform_web && npm test` -> 11 test files, 49 tests passed.
|
||||
- `cd platform_web && npm run build` -> Vite production build completed.
|
||||
- Plugin verification passed:
|
||||
- `cd plugins && npm run typecheck`
|
||||
- `cd plugins && npm run test` -> 1 test file, 11 tests passed.
|
||||
- `cd plugins && npm run validate:manifest` initially failed in the sandbox because `tsx` could not create an IPC pipe (`listen EPERM .../tsx-501/...pipe`); rerunning with elevated sandbox permissions passed and validated `examples/dev-game-plugin/manifest.json`.
|
||||
- Backend verification passed:
|
||||
- `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` passed for platform API, config, domain, DTO, model, repo, service, and validator packages.
|
||||
- `cd run && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -count=1` initially failed in the sandbox because `httptest` could not bind local listeners; rerunning with elevated sandbox permissions passed for run API, config, protocol, runtime, and spool packages.
|
||||
- Self-start local debug smoke passed:
|
||||
- `LOCAL_DEBUG_PLATFORM_PORT=18187 LOCAL_DEBUG_WEB_PORT=5181 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-final LOCAL_DEBUG_SELF_START=true scripts/local-debug-smoke.sh`
|
||||
- Evidence directory: `/private/tmp/browser-local-debug-final/smoke`
|
||||
- Output confirmed platform health, dev plugin manifest validation, plugin API registration, run endpoint heartbeat, server lifecycle workflow creation, job/log/artifact/marketplace reference checks, and forbidden-fragment rejection.
|
||||
- Browser walkthrough stack and seed smoke passed:
|
||||
- Reset: `LOCAL_DEBUG_PLATFORM_PORT=18188 LOCAL_DEBUG_WEB_PORT=5182 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-walkthrough scripts/local-debug-reset.sh`
|
||||
- Stack command: `/bin/zsh -lc 'LOCAL_DEBUG_PLATFORM_PORT=18188 LOCAL_DEBUG_WEB_PORT=5182 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-walkthrough scripts/local-debug-reset.sh; LOCAL_DEBUG_PLATFORM_PORT=18188 LOCAL_DEBUG_WEB_PORT=5182 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-walkthrough scripts/local-debug-start.sh; sleep 1200'`
|
||||
- Seed smoke: `LOCAL_DEBUG_PLATFORM_PORT=18188 LOCAL_DEBUG_WEB_PORT=5182 LOCAL_DEBUG_ROOT=/private/tmp/browser-local-debug-walkthrough scripts/local-debug-smoke.sh`
|
||||
- Evidence directory: `/private/tmp/browser-local-debug-walkthrough/smoke`
|
||||
- Browser walkthrough evidence:
|
||||
- Logged in at `http://127.0.0.1:5182` with `operator.local@example.test` / `operator-local`; login landed on `#/home` with API-backed platform data.
|
||||
- Opened 首页 `#/home`: showed `平台概览`, `数据已加载`, `game.example:1 个实例`, and `运行节点 1`; no fallback/demo text and no forbidden fragments.
|
||||
- Opened 服务器管理 `#/servers`: showed `Local Debug Example Server` / `server-local-debug`; no fallback/demo text and no forbidden fragments.
|
||||
- Opened 插件市场 `#/plugins`: showed `game.example`, `artifact://manifests/game.example/0.1.0`, `process.install`, `process.start`, `process.stop`, `server.instances.read`, `jobs.dispatch`, `logs.query`, and `artifacts.open`; no fallback/demo text and no forbidden fragments.
|
||||
- Opened 用户管理 `#/users`: showed `operator.local@example.test`, `账号 API 已连接`, and local admin metadata; no fallback/demo text and no forbidden fragments.
|
||||
- Opened AI 提供商管理 `#/aiProviders`: showed API-backed provider rows with redacted secret refs (`secret://providers/openai`, `env://OLLAMA_API_KEY`); no fallback/demo text and no forbidden fragments.
|
||||
- Opened server detail `#/servers/server-local-debug`: showed `Local Debug Example Server`, `game.example@0.1.0`, `run-local-debug`, lifecycle buttons, `日志`, `配置`, `插件控制`, `AI 助手`, and `操作历史`; no fallback/demo text and no forbidden fragments.
|
||||
- The browser DOM snapshot helper failed with `incrementalAriaSnapshot is not a function`, so the walkthrough used read-only page evaluation to inspect visible text, buttons, URLs, and forbidden fragments.
|
||||
- Final verification commands:
|
||||
- `scripts/check-structure.sh` passed after implementation evidence was recorded.
|
||||
- `openspec validate implement-local-debug-workspace --strict` passed after implementation evidence and stream handoff were updated; PostHog telemetry DNS errors, if emitted after success, do not affect the validation result.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-03
|
||||
@@ -0,0 +1,81 @@
|
||||
## Context
|
||||
|
||||
Run control and job lifecycle routes are implemented, but logs still exist only as metadata records. The architecture requires logs to be treated as durable historical data: run writes batches to a local spool before upload, platform acknowledges accepted sequence ranges, and artifacts must not block control, job, or log traffic.
|
||||
|
||||
This change implements the first HTTP JSON log ingest path and an in-repository run spool abstraction. It keeps platform storage in memory and updates existing `LogStream` metadata because durable database/log backend selection is a later architecture decision.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Define typed log ingest protocol payloads in `run/protocol` and matching platform DTO/domain contracts.
|
||||
- Add platform log ingest API routes for batch upload and bounded stream cursor query.
|
||||
- Validate run session continuity, stream identity, sequence ranges, checksums, and batch size.
|
||||
- Track accepted log entries and latest acknowledged sequence in platform service state and existing `LogStream.LatestSeq`.
|
||||
- Add a run-side local spool abstraction that persists unacknowledged batches to disk and removes acknowledged ranges only after platform ack.
|
||||
- Extend `run/api.PlatformClient` with a typed log batch ingest method.
|
||||
- Add tests for platform ack/query behavior, duplicate/out-of-order rejection, run spool retry retention, and client request/response behavior.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No external log storage backends such as Loki, ClickHouse, OpenSearch, or Elasticsearch.
|
||||
- No browser live tail, log websocket, AI log analysis windows, or frontend behavior.
|
||||
- No compression codec implementation beyond typed metadata and checksum validation for the JSON payload.
|
||||
- No artifact transfer, game client bridge, billing, cloud host sales, or direct plugin-to-run access.
|
||||
- No raw host paths, raw credentials, direct sockets, or artifact chunks inside log payloads.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: HTTP JSON batch ingest first
|
||||
|
||||
The initial ingest route uses `POST /api/v1/run/logs/batches` with typed JSON batches. This keeps the path testable, bounded, and independent from control, jobs, and artifacts.
|
||||
|
||||
Alternative considered: streaming logs over the control or job channel. Rejected because logs are high-volume historical data and must not block heartbeat, claim/ack/result, or artifact traffic.
|
||||
|
||||
### Decision 2: Platform validates contiguous sequence ranges
|
||||
|
||||
Each batch carries `streamKey`, `firstSeq`, `lastSeq`, checksum, and entries. The platform accepts the next contiguous range, treats already-acknowledged duplicate batches as idempotent acks, and rejects sequence gaps or conflicting duplicates.
|
||||
|
||||
Alternative considered: accepting any sequence order and sorting later. Rejected because retry/ack semantics need deterministic spool cleanup and missing ranges must be visible immediately.
|
||||
|
||||
### Decision 3: Log body storage is in-memory for now
|
||||
|
||||
The service stores accepted log entries in memory keyed by stream ID and updates existing `LogStream.LatestSeq`. This matches the current repository scope and lets later storage adapters replace the implementation behind service methods.
|
||||
|
||||
Alternative considered: adding a local compressed segment storage backend now. Rejected because this change needs API semantics and run spool behavior first; backend choice remains open.
|
||||
|
||||
### Decision 4: Run spool stores batches as JSON segment files
|
||||
|
||||
The run-side spool writes one JSON file per unacknowledged batch in a caller-provided directory. Tests can inspect retry behavior without a daemon loop, and future uploaders can reuse the same abstraction.
|
||||
|
||||
Alternative considered: purely in-memory spool. Rejected because the architecture requires local retention across temporary platform unavailability and restart.
|
||||
|
||||
### Decision 5: Client stays transport-only
|
||||
|
||||
`run/api.PlatformClient` will encode and decode log ingest requests and responses. Collector loops, file tailing, backpressure scheduling, and artifact priority throttling remain future runtime work.
|
||||
|
||||
Alternative considered: implementing a background log uploader now. Rejected because that would expand scope beyond protocol, spool, and ack semantics.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] In-memory platform log storage disappears on restart. Mitigation: keep storage behind `service.Core` and document this as early development behavior.
|
||||
- [Risk] JSON spool files are not optimized for very large log volumes. Mitigation: enforce bounded batch sizes now; later changes can swap segment encoding without changing ack semantics.
|
||||
- [Risk] Checksums only cover entries in this change. Mitigation: keep checksum metadata explicit and add compressed segment checksums when compression/chunking is implemented.
|
||||
- [Risk] No background uploader means no automatic retry loop. Mitigation: tests cover retained batches and client upload behavior; scheduling remains a later runtime concern.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add log protocol, DTO, domain, validation, and service contracts.
|
||||
2. Add platform API handlers and tests for ingest and query.
|
||||
3. Add run local spool implementation and tests.
|
||||
4. Add run client method and tests.
|
||||
5. Update protocol/route docs.
|
||||
6. Verify with platform tests, run tests, structure check, and strict OpenSpec validation.
|
||||
|
||||
Rollback before dependent changes is removal of the log ingest route/client/spool additions and this OpenSpec change. After artifact/server workflow changes depend on logs, rollback must use a new OpenSpec change.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which production log body backend should be implemented first: local compressed segments, Loki, ClickHouse, OpenSearch, or Elasticsearch?
|
||||
- What maximum batch size and compression settings should production use?
|
||||
- How should browser live tail subscribe to stored logs without weakening durable ingest guarantees?
|
||||
@@ -0,0 +1,29 @@
|
||||
## Why
|
||||
|
||||
The run job channel can now execute lifecycle work, but server and process logs still have no durable ingest path. This change adds the first log pipeline so run can spool logs locally, upload bounded batches, and receive sequence acknowledgements without mixing log traffic into control, job, or artifact channels.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add typed run log ingest protocol payloads for log entries, batch ingest requests, batch acknowledgements, and stream cursors.
|
||||
- Add platform API routes that accept durable log batches, validate stream identity and sequence continuity, acknowledge accepted ranges, and expose bounded query by stream cursor.
|
||||
- Extend platform service behavior to append log batches to existing log stream metadata, track latest acknowledged sequence, and reject duplicate or out-of-order batches.
|
||||
- Add a run-side local spool/WAL abstraction that stores unacknowledged batches and removes only acknowledged sequence ranges.
|
||||
- Extend the run-side platform client with typed log batch ingest calls.
|
||||
- Add platform service/API tests and run spool/client tests covering retry, acknowledgement, duplicate/out-of-order rejection, and query behavior.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `log-ingest-pipeline`: Durable run-to-platform log batch ingest, acknowledgement, local spool retention, and stream cursor query workflow.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` and `run/` only.
|
||||
- Adds Go protocol/DTO/domain/service/API/spool code and tests for log ingest.
|
||||
- Updates run/platform protocol and route documentation.
|
||||
- Does not implement artifact transfer, browser live tail, external log backends, AI log analysis, frontend pages, billing, cloud host sales, or direct plugin/run access.
|
||||
@@ -0,0 +1,74 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Log ingest payloads are typed and bounded
|
||||
The system SHALL define typed log ingest payloads for log entries, batch ingest requests, batch acknowledgements, and stream cursor queries without carrying artifact chunks, host paths, raw credentials, direct sockets, or unbounded inline data.
|
||||
|
||||
#### Scenario: Log payloads are used
|
||||
- **WHEN** run or platform code sends log ingest data
|
||||
- **THEN** it MUST use named protocol/DTO types from dedicated protocol or DTO packages
|
||||
|
||||
#### Scenario: Log batch stays bounded
|
||||
- **WHEN** run uploads a log batch
|
||||
- **THEN** the request MUST include run endpoint ID, session token, stream identity, sequence range, checksum, compression metadata, and bounded entries only
|
||||
|
||||
### Requirement: Platform accepts durable log batches
|
||||
The platform SHALL expose a log batch ingest endpoint that validates run session continuity, stream metadata, checksum, and sequence continuity before acknowledging accepted ranges.
|
||||
|
||||
#### Scenario: Contiguous batch succeeds
|
||||
- **WHEN** run uploads a valid batch whose first sequence follows the platform's latest acknowledged sequence for that stream
|
||||
- **THEN** platform MUST store the entries, update latest acknowledged sequence, and return an accepted acknowledgement for the range
|
||||
|
||||
#### Scenario: Duplicate acknowledged batch is retried
|
||||
- **WHEN** run uploads a batch whose range is already fully acknowledged and checksum matches the stored range
|
||||
- **THEN** platform MUST return an accepted idempotent acknowledgement without duplicating entries
|
||||
|
||||
#### Scenario: Out-of-order batch is submitted
|
||||
- **WHEN** run uploads a batch with a sequence gap or conflicting duplicate data
|
||||
- **THEN** platform MUST return a JSON validation error and MUST NOT advance the acknowledged sequence
|
||||
|
||||
### Requirement: Platform exposes bounded log stream query
|
||||
The platform SHALL expose a bounded log query endpoint that returns entries for one stream after a cursor sequence and includes the next cursor.
|
||||
|
||||
#### Scenario: Query returns entries after cursor
|
||||
- **WHEN** a caller queries a stream after an acknowledged sequence
|
||||
- **THEN** platform MUST return ordered entries after that cursor up to the requested limit and include the next cursor
|
||||
|
||||
#### Scenario: Query target is missing
|
||||
- **WHEN** a caller queries a missing stream
|
||||
- **THEN** platform MUST return a JSON not found error
|
||||
|
||||
### Requirement: Run spool retains unacknowledged batches
|
||||
The run-side log spool SHALL persist unacknowledged batches locally and remove them only after platform acknowledgement covers their sequence range.
|
||||
|
||||
#### Scenario: Platform upload fails
|
||||
- **WHEN** a batch remains unacknowledged after an upload failure
|
||||
- **THEN** the spool MUST retain the batch for retry
|
||||
|
||||
#### Scenario: Platform acknowledges batch
|
||||
- **WHEN** platform returns an acknowledgement covering a batch range
|
||||
- **THEN** the spool MUST mark that range acknowledged and remove the batch from pending retry listing
|
||||
|
||||
### Requirement: Run client uploads log batches
|
||||
The run-side platform client SHALL provide a typed log batch ingest method that calls the platform log endpoint and decodes typed acknowledgement responses.
|
||||
|
||||
#### Scenario: Run uploads log batch through client
|
||||
- **WHEN** run code calls the log ingest client method
|
||||
- **THEN** the client MUST send a JSON `POST` to `/api/v1/run/logs/batches` and decode the acknowledgement response
|
||||
|
||||
#### Scenario: Platform rejects log batch
|
||||
- **WHEN** the platform log ingest endpoint returns a non-success status
|
||||
- **THEN** the run client MUST return an error and MUST NOT treat the batch as acknowledged
|
||||
|
||||
### Requirement: Log ingest is documented separately from other channels
|
||||
The run/platform route and protocol documentation SHALL identify implemented log ingest routes and explicitly keep control, job, artifact, and game client bridge transport separate.
|
||||
|
||||
#### Scenario: Contributor inspects log docs
|
||||
- **WHEN** a contributor opens run or platform protocol docs
|
||||
- **THEN** the docs MUST show log batch ingest and query as implemented while artifact and game client channels remain separate
|
||||
|
||||
### Requirement: Log ingest pipeline is verified
|
||||
The change SHALL include platform service/API tests, run spool tests, run client tests, and retry/ack/query coverage.
|
||||
|
||||
#### Scenario: Verification commands run
|
||||
- **WHEN** the change is complete
|
||||
- **THEN** `go test ./...` from `platform/`, `go test ./...` from `run/`, `scripts/check-structure.sh`, and `openspec validate implement-log-ingest-pipeline --strict` MUST pass
|
||||
@@ -0,0 +1,35 @@
|
||||
## 1. Log Contracts
|
||||
|
||||
- [x] 1.1 Add typed run log ingest protocol payloads in `run/protocol` for entries, batch ingest, acknowledgements, and stream cursors.
|
||||
- [x] 1.2 Add matching platform DTO/domain contracts and conversion helpers for log batch ingest and query.
|
||||
- [x] 1.3 Add validation rules for bounded log batches, stream identity, sequence ranges, checksum, and query limits.
|
||||
|
||||
## 2. Platform Log Ingest
|
||||
|
||||
- [x] 2.1 Extend platform service behavior to ingest contiguous batches, acknowledge duplicates, reject out-of-order/conflicting batches, update `LogStream.LatestSeq`, and query entries after a cursor.
|
||||
- [x] 2.2 Implement platform log ingest/query HTTP routes using named DTOs and service methods.
|
||||
- [x] 2.3 Add platform service/API tests for accepted batches, duplicate ack, out-of-order rejection, missing stream, and cursor query.
|
||||
|
||||
## 3. Run Log Spool And Client
|
||||
|
||||
- [x] 3.1 Implement a run-side local spool abstraction that writes pending batches to disk, lists them for retry, and removes acknowledged ranges.
|
||||
- [x] 3.2 Extend `run/api.PlatformClient` with a typed log batch ingest method.
|
||||
- [x] 3.3 Add run spool/client tests for retry retention, acknowledgement cleanup, request path, JSON payload, response decoding, and platform error handling.
|
||||
|
||||
## 4. Documentation
|
||||
|
||||
- [x] 4.1 Update run and platform protocol/route documentation to mark log batch ingest/query implemented and keep control/job/artifact/game-client channels separate.
|
||||
|
||||
## 5. Verification
|
||||
|
||||
- [x] 5.1 Run `go test ./...` from `platform/` and record evidence.
|
||||
- [x] 5.2 Run `go test ./...` from `run/` and record evidence.
|
||||
- [x] 5.3 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 5.4 Run `openspec validate implement-log-ingest-pipeline --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- 2026-07-03: `go test ./...` from `platform/` passed.
|
||||
- 2026-07-03: `go test ./...` from `run/` passed.
|
||||
- 2026-07-03: `scripts/check-structure.sh` passed with `structure check passed`.
|
||||
- 2026-07-03: `openspec validate implement-log-ingest-pipeline --strict` passed with `Change 'implement-log-ingest-pipeline' is valid`.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -0,0 +1,79 @@
|
||||
## Context
|
||||
|
||||
`platform/` already contains typed domain resources, DTO contracts, model projections, validators, repositories, and `service.Core` workflows for the first platform resources. The current executable only exposes `/healthz`, so frontend, run, and plugin changes cannot yet rely on HTTP behavior for users, game plugins, server instances, AI providers, run endpoints, jobs, artifacts, log streams, or audit events.
|
||||
|
||||
This change stays inside `platform/` and implements the first HTTP adapter layer over the existing core service. It must preserve the repository structure rules: handlers belong in `api/`, request/response DTOs in `dto/`, domain rules in `domain/` and `validator/`, and storage concerns in `repo/` or future persistence packages.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Expose create, list, and detail HTTP routes for core platform resources.
|
||||
- Keep handlers as adapters that decode named DTOs, call `service.Core`, and encode named DTO responses.
|
||||
- Return deterministic JSON error responses for malformed JSON, validation failures, duplicate IDs, missing resources, and unexpected failures.
|
||||
- Preserve AI provider redaction by returning `apiKeyRef` only and never raw API key material.
|
||||
- Make router construction injectable for tests and future persistence while retaining an in-memory default for local development.
|
||||
- Update `platform/api/routes.md` to reflect implemented routes.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No authentication, session, RBAC, or authorization engine.
|
||||
- No SQL database, migrations, or external persistence dependency.
|
||||
- No frontend or run-side implementation.
|
||||
- No run job claim/ack/result protocol implementation beyond platform-side job resource creation and query.
|
||||
- No plugin page bridge implementation, AI invocation endpoint, file content transfer, log body ingest, or artifact chunk transfer.
|
||||
- No billing, cloud host sales, agent-provider/cloud-provider workflows, or unrelated SaaS marketplace features.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Use `net/http` ServeMux with explicit method dispatch
|
||||
|
||||
The platform will keep using the Go standard library. Route wiring will use `http.ServeMux` path patterns, `PathValue` for detail routes, and explicit method dispatch inside resource handlers so unsupported methods can return the named JSON error DTO.
|
||||
|
||||
Alternative considered: adding a third-party router. Rejected because the API surface is still small and the current module has no external runtime dependencies.
|
||||
|
||||
### Decision 2: Router accepts `service.Core`
|
||||
|
||||
`api.NewRouter()` will build the current in-memory service for local execution, while `api.NewRouterWithCore(core service.Core)` will allow tests and later persistence changes to provide a service implementation.
|
||||
|
||||
Alternative considered: constructing repositories directly inside every handler. Rejected because it hides storage choices in transport code and bypasses the service layer that already owns cross-resource invariants.
|
||||
|
||||
### Decision 3: DTO package owns request conversion and API envelopes
|
||||
|
||||
Create-request DTOs will expose `ToDomain()` helpers. Response DTOs and list/error envelopes will remain named structs under `platform/dto` so handlers do not define request/response shapes inline.
|
||||
|
||||
Alternative considered: constructing ad hoc response maps in handlers. Rejected because API contracts must remain discoverable and testable.
|
||||
|
||||
### Decision 4: Handlers map service errors to stable HTTP errors
|
||||
|
||||
Handlers will translate `validator.ValidationError` to `400`, malformed JSON to `400`, `repo.ErrNotFound` to `404`, `repo.ErrDuplicate` to `409`, and unexpected errors to `500`. All errors will use `dto.ErrorResponse`.
|
||||
|
||||
Alternative considered: returning plain-text `http.Error`. Rejected because clients need predictable JSON responses and AGENTS.md requires named error DTOs.
|
||||
|
||||
### Decision 5: Implement metadata routes only for logs and artifacts
|
||||
|
||||
This change implements log stream metadata and artifact metadata resources. Chunk upload/download, durable log ingest, tail transport, and storage adapters remain future changes because they affect run communication channels and transfer backpressure.
|
||||
|
||||
Alternative considered: implementing chunk and ingest endpoints now. Rejected because the delivery stream has separate changes for run channels, logs, and artifacts.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] In-memory default storage loses data on restart. Mitigation: document it as local development wiring and keep router injection ready for future persistence.
|
||||
- [Risk] Create/list/get routes are narrower than the full route catalog. Mitigation: document deferred lifecycle, chunk, ingest, and plugin bridge behavior explicitly in `platform/api/routes.md`.
|
||||
- [Risk] Query filter values are string-based and rely on domain enum strings. Mitigation: keep filters narrow and let create/update validation remain in the service and validator layers.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add DTO conversion helpers, list envelopes, and error DTOs.
|
||||
2. Add API router wiring and handlers over `service.Core`.
|
||||
3. Update route catalog documentation.
|
||||
4. Add focused handler tests for route behavior, validation/error mapping, and AI provider redaction.
|
||||
5. Verify with `go test ./...` from `platform/`, `scripts/check-structure.sh`, and strict OpenSpec validation.
|
||||
|
||||
Rollback before dependent changes is removal of the API handler additions and this OpenSpec change. After frontend, run, or plugin changes consume these routes, rollback must be handled through a new OpenSpec change.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which authentication/session mechanism will wrap these routes first?
|
||||
- Which persistent repository implementation should replace the in-memory default?
|
||||
- Which API pagination and sorting contract should be introduced once lists can grow beyond development-scale data?
|
||||
@@ -0,0 +1,30 @@
|
||||
## Why
|
||||
|
||||
The platform backend has typed core resources and service workflows, but clients still cannot exercise them through HTTP. This change adds the first platform API surface so later frontend, run, and plugin work can depend on stable handler behavior instead of calling services directly.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add HTTP route handlers for core platform resources using the existing domain, DTO, validator, repository, and service packages.
|
||||
- Support create, list, and detail workflows for users, AI providers, game management plugins, server instances, run endpoints, jobs, artifacts, log streams, and audit events.
|
||||
- Return JSON error responses for malformed requests, validation failures, duplicates, and missing resources.
|
||||
- Preserve AI provider redaction by returning only API key references and never raw provider keys.
|
||||
- Wire the platform router to an in-memory service instance for local development while keeping handlers injectable for tests and future persistence.
|
||||
- Update route catalog documentation to reflect the implemented API paths.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `platform-api-surface`: HTTP API handlers, route wiring, request decoding, response encoding, and error behavior for core platform resources.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` only.
|
||||
- Adds platform API handler code and focused handler tests.
|
||||
- Extends DTO helpers for request-to-domain conversion and JSON error response contracts.
|
||||
- Uses only Go standard library HTTP routing and the existing in-memory core service.
|
||||
- Does not add authentication, authorization, SQL persistence, frontend behavior, run executor behavior, billing, cloud host sales, or direct plugin/run access.
|
||||
@@ -0,0 +1,82 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Core resource HTTP routes are implemented
|
||||
The platform SHALL expose HTTP JSON routes for create, list, and detail workflows for users, AI providers, game management plugins, server instances, run endpoints, jobs, artifacts, log streams, and audit events.
|
||||
|
||||
#### Scenario: Resource is created through API
|
||||
- **WHEN** a valid create request is posted to a core resource collection route
|
||||
- **THEN** the platform MUST persist the resource through `service.Core` and return `201` with the corresponding named response DTO
|
||||
|
||||
#### Scenario: Resource list is requested
|
||||
- **WHEN** a client sends `GET` to a core resource collection route
|
||||
- **THEN** the platform MUST return `200` with a named list response DTO containing resources from `service.Core`
|
||||
|
||||
#### Scenario: Resource detail is requested
|
||||
- **WHEN** a client sends `GET` to a core resource detail route with an existing resource ID
|
||||
- **THEN** the platform MUST return `200` with the corresponding named response DTO
|
||||
|
||||
### Requirement: API handlers use centralized DTO and service contracts
|
||||
The platform SHALL keep API request, response, list, and error contracts in `platform/dto` and SHALL call `service.Core` for resource workflows.
|
||||
|
||||
#### Scenario: Handler decodes request body
|
||||
- **WHEN** an API handler accepts a request body
|
||||
- **THEN** it MUST decode into a named DTO type from `platform/dto` and convert that DTO to a named domain type before calling `service.Core`
|
||||
|
||||
#### Scenario: Handler returns response body
|
||||
- **WHEN** an API handler returns a success or error response
|
||||
- **THEN** it MUST encode a named DTO response type and MUST NOT define response structs inside handler functions
|
||||
|
||||
### Requirement: API errors are stable JSON responses
|
||||
The platform SHALL return named JSON error DTOs for malformed requests, validation failures, duplicate resources, missing resources, unsupported methods, and unexpected failures.
|
||||
|
||||
#### Scenario: Invalid JSON is submitted
|
||||
- **WHEN** a client posts malformed JSON to a core resource route
|
||||
- **THEN** the platform MUST return `400` with a JSON error response
|
||||
|
||||
#### Scenario: Validation fails
|
||||
- **WHEN** a create request violates validator or service invariants
|
||||
- **THEN** the platform MUST return `400` with a JSON error response and MUST NOT persist the resource
|
||||
|
||||
#### Scenario: Duplicate resource is submitted
|
||||
- **WHEN** a create request uses an ID that already exists
|
||||
- **THEN** the platform MUST return `409` with a JSON error response
|
||||
|
||||
#### Scenario: Missing resource is requested
|
||||
- **WHEN** a client requests a resource ID that does not exist
|
||||
- **THEN** the platform MUST return `404` with a JSON error response
|
||||
|
||||
### Requirement: AI provider API preserves credential redaction
|
||||
The AI provider API SHALL return redacted provider response DTOs that include secret references only and never raw API keys.
|
||||
|
||||
#### Scenario: AI provider is created through API
|
||||
- **WHEN** a valid AI provider create request is posted
|
||||
- **THEN** the platform MUST return an `AIProviderResponse` containing `apiKeyRef` and MUST NOT include raw API key fields
|
||||
|
||||
#### Scenario: Raw AI key is submitted as key reference
|
||||
- **WHEN** an AI provider create request includes raw key material in `apiKeyRef`
|
||||
- **THEN** the platform MUST reject the request with `400` and MUST NOT persist the provider
|
||||
|
||||
### Requirement: Router is injectable and local-development ready
|
||||
The platform SHALL provide router construction that accepts a core service for tests and future persistence, and a default router that uses the in-memory core service for local development.
|
||||
|
||||
#### Scenario: Local platform process starts
|
||||
- **WHEN** `cmd/platform` creates the default router
|
||||
- **THEN** the router MUST expose `/healthz` and all implemented core API routes backed by an in-memory `service.Core`
|
||||
|
||||
#### Scenario: Tests provide a service
|
||||
- **WHEN** tests call router construction with an explicit `service.Core`
|
||||
- **THEN** handlers MUST use that service instance for all route operations
|
||||
|
||||
### Requirement: Route catalog matches implemented API surface
|
||||
The platform route catalog SHALL identify implemented core API routes and clearly distinguish deferred run transport, log ingest, artifact chunk, plugin bridge, and AI invocation behavior.
|
||||
|
||||
#### Scenario: Contributor inspects API catalog
|
||||
- **WHEN** a contributor opens `platform/api/routes.md`
|
||||
- **THEN** the file MUST list the implemented create, list, and detail routes and MUST identify deferred behavior as not implemented by this change
|
||||
|
||||
### Requirement: API handler tests verify surface behavior
|
||||
The platform SHALL include API tests covering successful create/list/detail workflows, JSON error mapping, dependency validation, duplicate handling, missing resources, and AI provider redaction.
|
||||
|
||||
#### Scenario: Platform API tests run
|
||||
- **WHEN** `go test ./...` is executed inside `platform/`
|
||||
- **THEN** tests MUST verify the implemented HTTP API behavior without external services or a database
|
||||
@@ -0,0 +1,30 @@
|
||||
## 1. DTO And Router Contracts
|
||||
|
||||
- [x] 1.1 Add named DTO list/error response contracts and request-to-domain conversion helpers for core resource create requests.
|
||||
- [x] 1.2 Add injectable platform router construction that wires health and core API routes through `service.Core` with an in-memory default.
|
||||
|
||||
## 2. Core API Handlers
|
||||
|
||||
- [x] 2.1 Implement users, AI providers, game plugins, server instances, and run endpoints create/list/detail handlers.
|
||||
- [x] 2.2 Implement jobs, artifacts, log streams, and audit events create/list/detail handlers.
|
||||
- [x] 2.3 Implement shared JSON decode, encode, method, and error mapping behavior using named DTO responses.
|
||||
- [x] 2.4 Update `platform/api/routes.md` to identify implemented routes and deferred transport/bridge behavior.
|
||||
|
||||
## 3. API Tests
|
||||
|
||||
- [x] 3.1 Add handler tests for successful create/list/detail workflows and query filters.
|
||||
- [x] 3.2 Add handler tests for malformed JSON, validation errors, duplicates, missing resources, dependency failures, and AI provider redaction.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run `go test ./...` from `platform/` and record evidence.
|
||||
- [x] 4.2 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 4.3 Run `openspec validate implement-platform-api-surface --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `go test ./api`: passed.
|
||||
- `go test ./dto`: passed.
|
||||
- `go test ./...` from `platform/`: passed.
|
||||
- `scripts/check-structure.sh`: passed.
|
||||
- `openspec validate implement-platform-api-surface --strict`: passed.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-02
|
||||
@@ -0,0 +1,79 @@
|
||||
## Context
|
||||
|
||||
`platform/` currently contains the development baseline: a Go module, config loader, health route, route catalog, and markdown contracts for platform resources. The bootstrap architecture requires fixed backend directories for domain types, DTOs, database models, repositories, services, validators, protocol contracts, routes, and shared helpers. Later changes will implement HTTP handlers, run registration, job channels, logs, artifacts, plugin registry, and frontend workflows; those changes need stable core platform types first.
|
||||
|
||||
This change stays inside `platform/` and converts the markdown resource contracts into Go packages with unit-tested in-memory behavior. It does not introduce a database driver or full API handler surface.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Define typed Go domain resources for users, game management plugins, server instances, AI providers, run endpoints, jobs, artifacts, log streams, and audit events.
|
||||
- Define DTO and database-model contracts in dedicated packages so future handlers and persistence work do not invent structs locally.
|
||||
- Add repository interfaces and an in-memory implementation for deterministic unit tests and early service composition.
|
||||
- Add services that enforce core invariants for plugin installation metadata, server creation, AI provider redaction, job idempotency, artifacts, logs, and audit.
|
||||
- Add validation helpers with precise errors for required IDs, enum values, relationships, capability compatibility, redaction, sequence cursors, and bounded summaries.
|
||||
- Update route catalog documentation with resource contract routes, while leaving handler implementation for a later API-surface change.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No authentication, sessions, role authorization engine, or password storage.
|
||||
- No SQL database, migrations, ORM, or external persistence dependency.
|
||||
- No full HTTP CRUD handlers beyond existing health behavior.
|
||||
- No run control/job/log/artifact transport implementation.
|
||||
- No plugin manifest registry implementation or plugin page bridge implementation.
|
||||
- No raw AI key exposure, direct plugin-to-run access, billing, cloud host sales, or unrelated marketplace behavior.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Domain package owns business vocabulary
|
||||
|
||||
`platform/domain` will define resource structs, enum-like string types, lifecycle constants, filter structs, and copy helpers. Services, repositories, DTOs, and models will reference this vocabulary instead of redefining resource shapes.
|
||||
|
||||
Alternative considered: defining separate shapes independently in every package. Rejected because this would recreate the drift the architecture bootstrap is trying to avoid.
|
||||
|
||||
### Decision 2: DTO and model packages are explicit projections
|
||||
|
||||
DTO structs will represent API request/response boundaries and must not include raw AI provider secrets. Model structs will represent future database tables with JSON/database tags plus `TableName()` methods. Conversion functions will make differences explicit.
|
||||
|
||||
Alternative considered: reusing domain structs directly as API and database structs. Rejected because API redaction and database mapping concerns need independent contracts.
|
||||
|
||||
### Decision 3: Repository interfaces live with the in-memory implementation
|
||||
|
||||
`platform/repo` will define `Store` and typed repository interfaces, plus an in-memory `MemoryStore`. The store will deep-copy resources on read/write and enforce duplicate IDs. This gives services a realistic boundary without committing to SQL in this change.
|
||||
|
||||
Alternative considered: package-level maps in services. Rejected because it hides persistence contracts inside orchestration logic and makes future database replacement harder.
|
||||
|
||||
### Decision 4: Services own cross-resource invariants
|
||||
|
||||
Validators will check local resource validity. Services will enforce cross-resource rules such as “server instances require an installed plugin” and “run endpoint capabilities must satisfy plugin requirements.” Job creation will use an idempotency key to return an existing job for duplicate requests.
|
||||
|
||||
Alternative considered: repositories enforcing all invariants. Rejected because repositories should guard storage integrity while service use cases should own platform behavior.
|
||||
|
||||
### Decision 5: No database or HTTP framework dependency yet
|
||||
|
||||
This change uses only the Go standard library. SQL, migrations, and API handler frameworks are deferred until changes that explicitly implement persistence and API surface behavior.
|
||||
|
||||
Alternative considered: adding SQLite or an HTTP framework now. Rejected because it would widen scope beyond the core domain foundation and complicate verification before handlers exist.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] In-memory repositories can drift from future SQL behavior. Mitigation: keep interfaces small, copy-on-read/write, and test behavior that future implementations must preserve.
|
||||
- [Risk] Domain structs may need fields added by later run/log/plugin changes. Mitigation: include the bootstrap resource fields now and allow additive changes through future OpenSpec deltas.
|
||||
- [Risk] DTO/model projections add boilerplate. Mitigation: keep conversion helpers straightforward and limited to core resources.
|
||||
- [Risk] Services may look broad before API handlers exist. Mitigation: expose focused methods only for current core workflows and leave transport-specific behavior to later changes.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add platform domain, DTO, model, validator, repository, and service code behind new unit tests.
|
||||
2. Keep existing health route behavior unchanged.
|
||||
3. Update route and resource contract documentation to reference the implemented core resources.
|
||||
4. Verify with platform unit tests, `scripts/check-structure.sh`, and strict OpenSpec validation.
|
||||
|
||||
Rollback before dependent changes is file removal for the new platform packages and this OpenSpec change. After later API or persistence changes depend on these packages, rollback must follow a new OpenSpec change.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which persistent database implementation should replace `MemoryStore` first?
|
||||
- Which authentication and authorization model should own user/session behavior?
|
||||
- Which route handlers from the core route catalog should be implemented first in `implement-platform-api-surface`?
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
The platform backend currently has architecture contracts and a health endpoint, but the core platform resources are only described in markdown. This change turns those contracts into typed, validated Go domain foundations so later API, run, frontend, and plugin work can depend on stable platform behavior.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add typed platform domain resources for users, game management plugins, server instances, AI providers, run endpoints, jobs, artifacts, log streams, and audit events.
|
||||
- Add DTO and model contracts for those resources in their required directories.
|
||||
- Add repository interfaces plus an in-memory repository implementation suitable for unit tests and early service wiring.
|
||||
- Add service interfaces and implementations for core create/list/get workflows and lifecycle-safe state changes.
|
||||
- Add validators for identity, enum values, plugin-to-server relationships, run capability compatibility, AI provider redaction constraints, job idempotency, artifact metadata, log stream cursors, and audit summaries.
|
||||
- Extend route catalog documentation with the core resource contract surface, without implementing full HTTP handlers in this change.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `platform-core-domain`: Typed backend domain, DTO, model, repository, service, validation, and route-contract foundations for core platform resources.
|
||||
|
||||
### Modified Capabilities
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` only.
|
||||
- Adds Go packages under `platform/domain`, `platform/dto`, `platform/model`, `platform/repo`, `platform/service`, and `platform/validator`.
|
||||
- Updates `platform/api/routes.md` and platform markdown contracts where needed to reflect the implemented route contract surface.
|
||||
- Adds focused platform unit tests for validators, repository behavior, service behavior, and model mappings.
|
||||
- Does not add billing, cloud host sales, plugin-to-run direct access, raw AI key exposure, or full API handler behavior.
|
||||
@@ -0,0 +1,85 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Core platform resources are typed
|
||||
The platform SHALL define typed domain resources for users, AI providers, game management plugins, server instances, run endpoints, jobs, artifacts, log streams, and audit events in the platform domain package.
|
||||
|
||||
#### Scenario: Domain resource definitions are available
|
||||
- **WHEN** platform services, repositories, DTOs, or models need a core platform resource
|
||||
- **THEN** they MUST reference named domain resource types instead of defining business structs inside handlers or functions
|
||||
|
||||
#### Scenario: Lifecycle values are centralized
|
||||
- **WHEN** code validates resource status, state, result, or provider kind values
|
||||
- **THEN** it MUST use centralized domain constants for the allowed values
|
||||
|
||||
### Requirement: API and database contracts are separated from business logic
|
||||
The platform SHALL provide named DTO and model structs for core resources in dedicated packages, and model structs SHALL expose explicit table names and database tags.
|
||||
|
||||
#### Scenario: API response contract is needed
|
||||
- **WHEN** a later API handler returns a core resource
|
||||
- **THEN** the response shape MUST be available as a named DTO and MUST NOT be declared inside the handler
|
||||
|
||||
#### Scenario: Database model contract is needed
|
||||
- **WHEN** a future migration or repository references a core resource table
|
||||
- **THEN** the table mapping MUST be available as a named model with tags and an explicit table name function
|
||||
|
||||
### Requirement: AI provider contracts redact secrets
|
||||
The platform SHALL store AI provider secret references but MUST NOT expose raw provider API keys through domain responses, DTO responses, services, or plugin-facing contracts.
|
||||
|
||||
#### Scenario: AI provider is returned by service
|
||||
- **WHEN** an AI provider is created or fetched through the core service layer
|
||||
- **THEN** the returned provider MUST include an API key reference only and MUST NOT include raw key material
|
||||
|
||||
#### Scenario: AI provider validation runs
|
||||
- **WHEN** an AI provider uses a direct or relay endpoint
|
||||
- **THEN** validation MUST require a key reference and redaction policy while rejecting raw secret values in API contract fields
|
||||
|
||||
### Requirement: Core validators enforce resource invariants
|
||||
The platform SHALL validate required IDs, display names, enum values, bounded lists, server/plugin/run relationships, job idempotency keys, artifact checksums, log cursors, and audit summaries before services persist resources.
|
||||
|
||||
#### Scenario: Invalid core resource is submitted
|
||||
- **WHEN** a resource has a missing ID, invalid enum value, missing required relationship, unsupported capability, or unbounded summary
|
||||
- **THEN** validation MUST return a clear error and the service MUST NOT persist the resource
|
||||
|
||||
#### Scenario: Server creation is requested
|
||||
- **WHEN** a server instance is created from a game management plugin
|
||||
- **THEN** validation MUST require an installed plugin, a non-deleted server state, a run endpoint, and capability compatibility
|
||||
|
||||
### Requirement: Repository contracts support deterministic core storage
|
||||
The platform SHALL expose repository interfaces for core resources and an in-memory implementation that supports create, get, list, update, and idempotent job lookup behavior.
|
||||
|
||||
#### Scenario: Duplicate resource is created
|
||||
- **WHEN** a repository create operation receives an ID that already exists
|
||||
- **THEN** it MUST return a duplicate error and MUST NOT replace the existing resource
|
||||
|
||||
#### Scenario: Stored resource is read and mutated by caller
|
||||
- **WHEN** a caller mutates a value returned by the in-memory repository
|
||||
- **THEN** the stored resource MUST remain unchanged unless an explicit update operation succeeds
|
||||
|
||||
### Requirement: Core services enforce cross-resource workflows
|
||||
The platform SHALL provide services that compose repositories and validators for core user, plugin, server instance, AI provider, run endpoint, job, artifact, log stream, and audit workflows.
|
||||
|
||||
#### Scenario: Server instance is created from an installed plugin
|
||||
- **WHEN** a service request names an installed game management plugin and an online or degraded run endpoint with all required capabilities
|
||||
- **THEN** the service MUST persist a server instance linked to that plugin and run endpoint
|
||||
|
||||
#### Scenario: Server instance creation uses invalid dependencies
|
||||
- **WHEN** a service request names a disabled or invalid plugin, missing plugin, missing run endpoint, disabled run endpoint, or run endpoint without required capabilities
|
||||
- **THEN** the service MUST reject the request and MUST NOT persist the server instance
|
||||
|
||||
#### Scenario: Duplicate job request is submitted
|
||||
- **WHEN** a job create request repeats an existing run endpoint and idempotency key pair
|
||||
- **THEN** the service MUST return the existing job instead of creating a second job
|
||||
|
||||
### Requirement: Route catalog exposes core resource contract groups
|
||||
The platform SHALL document route groups for core resources before full API handlers are implemented.
|
||||
|
||||
#### Scenario: Contributor inspects platform API contracts
|
||||
- **WHEN** a contributor opens the platform route catalog
|
||||
- **THEN** it MUST list core resource route groups and the DTO contracts those future handlers will use
|
||||
|
||||
### Requirement: Platform core unit tests verify the domain foundation
|
||||
The platform SHALL include unit tests covering validation, in-memory repository behavior, service invariants, DTO redaction, and model table mappings.
|
||||
|
||||
#### Scenario: Platform tests run
|
||||
- **WHEN** `go test ./...` is executed inside `platform/`
|
||||
- **THEN** the tests MUST verify core domain behavior without external services or a database
|
||||
@@ -0,0 +1,34 @@
|
||||
## 1. Domain Contracts
|
||||
|
||||
- [x] 1.1 Implement typed domain resources, enum constants, filters, and copy helpers for users, AI providers, game plugins, server instances, run endpoints, jobs, artifacts, log streams, and audit events.
|
||||
- [x] 1.2 Implement named DTO request/response contracts with AI provider redaction helpers for core resources.
|
||||
- [x] 1.3 Implement database model contracts with JSON/database tags, table-name mappings, and domain conversion helpers for core resources.
|
||||
|
||||
## 2. Validation And Storage
|
||||
|
||||
- [x] 2.1 Implement validator rules and tests for IDs, enum values, AI redaction constraints, plugin/server/run compatibility, job idempotency, artifacts, logs, and audit summaries.
|
||||
- [x] 2.2 Implement repository interfaces and an in-memory repository with duplicate detection, copy-on-read/write behavior, list/get/update methods, and idempotent job lookup.
|
||||
|
||||
## 3. Services And Contracts
|
||||
|
||||
- [x] 3.1 Implement service interfaces and core service methods for create/list/get workflows across users, AI providers, game plugins, run endpoints, server instances, jobs, artifacts, log streams, and audit events.
|
||||
- [x] 3.2 Enforce service-level cross-resource invariants for server creation, AI provider redaction, disabled resources, run capability compatibility, and duplicate job idempotency.
|
||||
- [x] 3.3 Update platform route/resource contract documentation to reference the implemented DTO/domain contracts without adding full HTTP handlers.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run platform unit tests with `go test ./...` from `platform/` and record evidence.
|
||||
- [x] 4.2 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 4.3 Run `openspec validate implement-platform-core-domain --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- `go test ./domain`: passed.
|
||||
- `go test ./dto`: passed.
|
||||
- `go test ./model`: passed.
|
||||
- `go test ./validator`: passed.
|
||||
- `go test ./repo`: passed.
|
||||
- `go test ./service`: passed.
|
||||
- `go test ./...` from `platform/`: passed.
|
||||
- `scripts/check-structure.sh`: passed.
|
||||
- `openspec validate implement-platform-core-domain --strict`: passed.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-06
|
||||
@@ -0,0 +1,67 @@
|
||||
## Context
|
||||
|
||||
AI provider credentials and base URLs belong to `platform/`, while plugin pages may request AI assistance only through platform-mediated capabilities. AI-suggested config changes must be reviewable before any run-side write job is dispatched. This change introduces the invocation boundary and keeps provider clients mockable so implementation and tests do not require real keys or external services.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Add AI invocation request/response contracts with plugin, server, purpose, model preference, input, and review context.
|
||||
- Enforce allowed purposes from plugin manifest metadata and platform policy.
|
||||
- Route invocation through platform-owned provider configuration and a provider client interface.
|
||||
- Return bounded recommendations, safe text, structured diff suggestions, and usage metadata.
|
||||
- Ensure config-writing suggestions remain reviewable and are not automatically dispatched to run.
|
||||
- Add tests for validation, provider selection, mock invocation, purpose denial, redaction, and bridge integration.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No real external provider network calls in tests or default local mode.
|
||||
- No raw API key exposure to plugins, platform_web, run, logs, job payloads, or API responses.
|
||||
- No automatic config write dispatch from AI output.
|
||||
- No provider billing, agent-provider marketplace, cloud host sales, or unrelated SaaS workflows.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Provider client is an interface with mock default for tests
|
||||
|
||||
The platform service owns provider selection and calls a narrow provider client interface. Tests and local verification use a deterministic fake provider client, while live provider clients can be added later behind the same interface.
|
||||
|
||||
Alternative considered: implement live OpenAI/Anthropic calls immediately. Rejected because this request must not require real keys/accounts or external paid services.
|
||||
|
||||
### Decision 2: AI purposes are mandatory
|
||||
|
||||
Every invocation request includes a purpose such as config recommendation, troubleshooting, log summary, or plugin assistant. Platform validation checks that the plugin and requested context allow that purpose before provider selection.
|
||||
|
||||
Alternative considered: infer purpose from prompt text. Rejected because permission checks need explicit reviewable inputs.
|
||||
|
||||
### Decision 3: Config outputs are recommendations, not writes
|
||||
|
||||
For config-related requests, responses may include a proposed diff or recommendation object. The caller must still use config preview/approval APIs before any run-side write occurs.
|
||||
|
||||
Alternative considered: let AI invocation directly queue config write jobs. Rejected because AI-suggested changes must be reviewable before dispatch.
|
||||
|
||||
### Decision 4: Redaction happens before persistence and response
|
||||
|
||||
Request metadata, prompts, provider errors, and responses are scanned for unsafe credential-like content before logging or returning to browser/plugin callers.
|
||||
|
||||
Alternative considered: rely on caller discipline and avoid scanning. Rejected because provider and prompt output can accidentally include sensitive-looking material.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Mock provider behavior can hide live provider quirks. Mitigation: keep provider interface small and add live integration in a separate opt-in change.
|
||||
- [Risk] Purpose checks may reject useful flows. Mitigation: add new purposes through explicit manifest and OpenSpec updates.
|
||||
- [Risk] AI output can be over-trusted by operators. Mitigation: config changes return reviewable diffs and never auto-dispatch.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add platform invocation contracts, validators, provider client interface, service, routes, and tests.
|
||||
2. Add frontend API client and plugin bridge request plumbing.
|
||||
3. Add plugin SDK/example helpers and tests.
|
||||
4. Update docs and run full verification.
|
||||
|
||||
Rollback removes invocation routes/provider interface integrations and this change's artifacts before plugin workflows depend on them.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which live provider client should be implemented first after mock-mediated invocation passes?
|
||||
- Which audit event schema should capture AI recommendation review and operator approval?
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
AI provider management can store safe provider metadata, and plugin bridge contracts can request AI assistance by purpose. The missing piece is the platform-mediated invocation path: plugins and pages need AI help for reviewable recommendations without ever receiving raw provider keys, base URL credentials, or unmanaged model access.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add platform AI invocation domain, DTO, validator, service, and API behavior for purpose-scoped requests.
|
||||
- Route requests through platform-owned provider configuration and mockable provider clients, with no real-key requirement for tests.
|
||||
- Return bounded AI recommendations, usage metadata, and reviewable config diff suggestions instead of direct run-side writes.
|
||||
- Add plugin bridge/SDK and frontend client integration for `ai.invoke` requests without exposing provider credentials.
|
||||
- Add tests proving purpose enforcement, provider redaction, unsafe prompt/payload rejection, mock provider behavior, and no raw key exposure.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `platform-mediated-ai-invocation`: Platform-owned AI invocation for plugin and console workflows with purpose validation, credential isolation, bounded outputs, and reviewable recommendations.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- Builds on `ai-provider-management` and plugin bridge capabilities without adding raw provider access to plugins or platform_web.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform/` AI invocation contracts, services, validators, APIs, and tests.
|
||||
- Affects `platform_web/` API contracts/client and plugin bridge host behavior for AI requests.
|
||||
- Affects `plugins/` SDK/example AI request helpers and tests.
|
||||
- Does not require real provider keys/accounts, external paid services, live network calls in tests, billing, cloud host sales, or direct config writes.
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: AI invocation is platform-mediated
|
||||
|
||||
The platform SHALL expose AI invocation only through platform-owned APIs and services that use stored provider metadata and never expose raw provider credentials to plugins, platform_web, run, or API responses.
|
||||
|
||||
#### Scenario: Plugin invokes allowed AI purpose
|
||||
- **WHEN** a plugin page submits an `ai.invoke` request with an allowed purpose and bounded input
|
||||
- **THEN** the platform MUST validate the purpose, select an enabled provider through platform-owned configuration, invoke a provider client, and return a redacted AI response
|
||||
|
||||
#### Scenario: Raw provider credential is never returned
|
||||
- **WHEN** any AI invocation succeeds or fails
|
||||
- **THEN** the response MUST NOT include raw API keys, provider bearer tokens, provider base URL secrets, platform auth storage, run credentials, direct sockets, or raw host paths
|
||||
|
||||
### Requirement: AI purposes and payloads are validated
|
||||
|
||||
The platform SHALL validate invocation purpose, plugin permissions, server scope, model preference, input size, context references, and unsafe credential-like content before invoking a provider client.
|
||||
|
||||
#### Scenario: Undeclared purpose is denied
|
||||
- **WHEN** a plugin requests an AI purpose not declared by its manifest metadata or current bridge page permissions
|
||||
- **THEN** the platform MUST deny the request before provider invocation
|
||||
|
||||
#### Scenario: Unsafe payload is rejected
|
||||
- **WHEN** an invocation payload includes raw key-like content, absolute host paths, direct sockets, or unbounded input
|
||||
- **THEN** the platform MUST reject the request with a safe validation error
|
||||
|
||||
### Requirement: Provider invocation is mockable and bounded
|
||||
|
||||
The platform SHALL invoke AI through a provider client interface that supports deterministic tests without real external accounts or paid services.
|
||||
|
||||
#### Scenario: Mock provider returns recommendation
|
||||
- **WHEN** tests or local mode use the mock provider client
|
||||
- **THEN** invocation MUST return deterministic safe content, usage metadata, and optional structured recommendations without network access
|
||||
|
||||
#### Scenario: Provider failure is redacted
|
||||
- **WHEN** the provider client returns an error
|
||||
- **THEN** the platform MUST return a safe error response without provider credentials or raw transport details
|
||||
|
||||
### Requirement: Config suggestions remain reviewable
|
||||
|
||||
AI-generated configuration changes SHALL be returned as recommendations or diff previews and SHALL NOT directly dispatch run-side config write jobs.
|
||||
|
||||
#### Scenario: AI suggests config edit
|
||||
- **WHEN** an invocation purpose requests config assistance
|
||||
- **THEN** the response MAY include a proposed diff or recommendation, but the platform MUST require the separate config preview/approval workflow before dispatching a write job
|
||||
|
||||
### Requirement: Frontend and plugin SDK use mediated AI contracts
|
||||
|
||||
The frontend and plugin SDK SHALL use typed AI bridge/API contracts and SHALL NOT expose provider keys or raw provider configuration to plugin code.
|
||||
|
||||
#### Scenario: Plugin SDK builds AI request
|
||||
- **WHEN** plugin code builds an AI invocation request
|
||||
- **THEN** it MUST include purpose, request ID, scoped input, and context references while excluding raw provider credentials
|
||||
|
||||
#### Scenario: Browser walkthrough verifies AI request safety
|
||||
- **WHEN** AI invocation UI behavior is claimed complete
|
||||
- **THEN** a browser walkthrough MUST verify an AI-assisted workflow renders redacted results and does not expose raw credential markers
|
||||
|
||||
### Requirement: Platform-mediated AI invocation is verified
|
||||
|
||||
The change SHALL include backend tests, frontend tests/build, plugin tests/typecheck, browser walkthrough evidence, structure validation, and strict OpenSpec validation.
|
||||
|
||||
#### Scenario: Verification commands pass
|
||||
- **WHEN** the change is complete
|
||||
- **THEN** platform tests, platform_web tests/typecheck/build, plugin tests/typecheck, `scripts/check-structure.sh`, and `openspec validate implement-platform-mediated-ai-invocation --strict` MUST pass
|
||||
@@ -0,0 +1,41 @@
|
||||
## 1. Platform AI Invocation Contracts
|
||||
|
||||
- [x] 1.1 Add domain and DTO contracts for AI invocation requests, context refs, purposes, recommendations, usage metadata, and safe errors.
|
||||
- [x] 1.2 Add validators for purpose authorization, provider IDs, model preferences, bounded input/output, context refs, and unsafe credential/path/socket content.
|
||||
- [x] 1.3 Add a platform provider client interface and deterministic mock provider implementation for tests/local verification.
|
||||
|
||||
## 2. Platform AI Invocation Service And API
|
||||
|
||||
- [x] 2.1 Add service methods that authorize purpose-scoped invocation, select enabled providers, call the provider client, redact outputs, and return typed responses.
|
||||
- [x] 2.2 Implement AI invocation route using named DTOs and service methods.
|
||||
- [x] 2.3 Ensure config-related AI responses produce reviewable recommendations/diffs and never dispatch run-side writes directly.
|
||||
- [x] 2.4 Update platform route/protocol documentation for mediated AI invocation and live-provider deferral.
|
||||
- [x] 2.5 Add platform tests for allowed invocation, undeclared purpose denial, unsafe payload rejection, provider failure redaction, config recommendation reviewability, and no raw key exposure.
|
||||
|
||||
## 3. Frontend And Plugin Integration
|
||||
|
||||
- [x] 3.1 Add centralized `platform_web/api` AI invocation types and client methods.
|
||||
- [x] 3.2 Integrate AI invocation into plugin bridge host execution flow for `ai.invoke` responses.
|
||||
- [x] 3.3 Add plugin SDK/example helpers for AI invocation request builders and safe response parsing.
|
||||
- [x] 3.4 Add frontend and plugin tests for mediated AI requests, denied purposes, redacted results, and no direct provider config exposure.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run `cd platform && go test ./...` and record evidence.
|
||||
- [x] 4.2 Run `cd platform_web && npm run typecheck && npm test && npm run build` and record evidence.
|
||||
- [x] 4.3 Run `cd plugins && npm run typecheck && npm test` and record evidence.
|
||||
- [x] 4.4 Run browser walkthrough for mediated AI invocation and record evidence.
|
||||
- [x] 4.5 Run `scripts/check-structure.sh` and record evidence.
|
||||
- [x] 4.6 Run `openspec validate implement-platform-mediated-ai-invocation --strict` and record evidence.
|
||||
|
||||
## Evidence
|
||||
|
||||
- 2026-07-06: `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./... -run TestAIInvocationAPIIsMediatedAndSafe -count=1` passed for mediated invocation, purpose denial, unsafe prompt rejection, config suggestion reviewability/no job dispatch, bridge `ai.invoke`, and no forbidden response fragments.
|
||||
- 2026-07-06: `cd platform_web && npm run typecheck` and `cd platform_web && npm test -- --run api/client.test.ts utils/pluginBridgeHost.test.ts` passed for AI invocation API types/client and bridge `ai.invoke` dispatcher behavior.
|
||||
- 2026-07-06: `cd plugins && npm run typecheck` and `cd plugins && npm test -- --run tests/manifest-validation.test.ts` passed for SDK AI invocation request/response helpers and no provider config exposure.
|
||||
- 2026-07-06: `cd platform && GOCACHE=/private/tmp/browser-go-build-cache go test ./...` passed.
|
||||
- 2026-07-06: `cd platform_web && npm run typecheck`, `cd platform_web && npm test`, and `cd platform_web && npm run build` passed.
|
||||
- 2026-07-06: `cd plugins && npm run typecheck` and `cd plugins && npm test` passed.
|
||||
- 2026-07-06: Browser walkthrough passed using a local mock platform API plus headless Chrome: logged in, opened `#/servers/server-ai-walkthrough`, switched to `插件控制`, clicked `AI 调用`, verified `AI 建议已返回`, and confirmed no forbidden credential/path/provider fragments were rendered.
|
||||
- 2026-07-06: `scripts/check-structure.sh` passed.
|
||||
- 2026-07-06: `openspec validate implement-platform-mediated-ai-invocation --strict` passed (`Change 'implement-platform-mediated-ai-invocation' is valid`; PostHog DNS flush warnings were non-fatal telemetry failures).
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user