fix: 调试发布run
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-21
|
||||
@@ -0,0 +1,66 @@
|
||||
## Context
|
||||
|
||||
There are two local run checkouts: `/Users/tasia/Desktop/code/browser/run` and `/Users/tasia/Desktop/code/run`. Both point at `git.npc0.com:admin343/run.git`, but neither should be treated as the final generated runtime artifact. The current-directory checkout is an ignored editable source input for convenience and project-size control. Local debug must copy or upload that source into an ignored closed build bucket before any build-capable worker uses it. The sibling checkout has unrelated dirty changes and should not be required by this workflow.
|
||||
|
||||
Platform already queues `distribution.build` jobs and exposes safe browser download routes only after the build artifact is available. The run worker already has a real build path that fetches secret-bearing build input through a leased job channel, copies an approved build source, builds a target executable, packages it with config, uploads it through the artifact channel, and returns `artifact://<id>` as the terminal job result. This change closes the remaining gaps around source snapshotting, closed build bucket scoping, local smoke proof, and concurrency evidence.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Make local debug use the run checkout under this repository root as editable source input only.
|
||||
- Snapshot that source into an ignored closed build bucket before the bootstrap worker starts or any generated run distribution is built.
|
||||
- Build and start the local bootstrap worker from the bucket snapshot instead of `go run`-ing `browser/run` directly.
|
||||
- Keep run as a separate Git repository and keep browser from tracking run source files.
|
||||
- Build run packages in plugin/job-scoped isolated directories below the closed bucket so multiple servers for the same plugin cannot overwrite each other's source, config, archive, upload, or result.
|
||||
- Prove download works after build completion by opening the latest run distribution reference and reading artifact content chunks.
|
||||
- Report the exact configuration surface needed to run and verify the flow.
|
||||
|
||||
**Non-Goals:**
|
||||
- Do not move run source into browser's tracked source tree.
|
||||
- Do not delete or mutate `/Users/tasia/Desktop/code/run`; only stop using it as the default local debug target.
|
||||
- Do not add arbitrary shell execution, cloud hosting, billing, SaaS marketplace flows, plugin raw credentials, or direct sockets.
|
||||
- Do not implement production signing/KMS or rollout rings.
|
||||
- Do not require a live Windows host for local acceptance; local smoke can cross-compile Windows packages and verify the artifact archive.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Local debug separates editable source from build buckets
|
||||
|
||||
`scripts/local-debug-env.sh` will introduce `RUN_SOURCE_DIR` as the editable source checkout, defaulting to `$LOCAL_DEBUG_ROOT_DIR/run`. The legacy `RUN_REPO_DIR` environment variable remains an alias for source selection for compatibility, but it is not the build or execution artifact path.
|
||||
|
||||
The scripts will snapshot `RUN_SOURCE_DIR` into `RUN_BUILD_SOURCE_ROOT`, defaulting under `$LOCAL_DEBUG_ROOT/run/build-buckets/source/current`. Local debug will build `RUN_BOOTSTRAP_BIN` from that snapshot, then start the bootstrap worker binary. Platform-dispatched `distribution.build` jobs will copy from the bucket snapshot into plugin/job workspaces, never from the editable checkout.
|
||||
|
||||
Alternative considered: set `RUN_BUILD_SOURCE_ROOT=$RUN_SOURCE_DIR` and run from `browser/run`. Rejected because it conflates source input with build/runtime artifacts and allows the editable tree to become the effective execution directory.
|
||||
|
||||
### Decision 2: Build workspaces are plugin/job-scoped
|
||||
|
||||
The run worker will create distribution build workspaces under `RUN_WORKSPACE_ROOT/distribution-builds/<pluginId>/<jobId>`. The plugin dimension keeps same-plugin build queues inspectable and ready for per-plugin scheduling, while the job dimension prevents two servers or two idempotency keys from sharing mutable files. Artifact IDs and build job IDs remain Platform-derived and server-scoped.
|
||||
|
||||
Alternative considered: one directory per server. Rejected because multiple builds for the same plugin should queue and isolate by job, not mutate a long-lived per-server build tree.
|
||||
|
||||
### Decision 3: Download proof is mandatory after build success
|
||||
|
||||
Local smoke should keep the existing action availability check, but when `generate-run` is available it must generate a run package, wait for the build job to succeed, open `/run/download`, read content chunks, verify size/checksum metadata, and reject forbidden fragments. A build-capable run endpoint that cannot produce a downloadable artifact is a failing smoke.
|
||||
|
||||
### Decision 4: `/Users/tasia/Desktop/code/run` remains optional
|
||||
|
||||
The sibling checkout is not required for this workflow once local debug snapshots from `browser/run` by default. It can remain for manual comparison or be removed by the user later, but this change will not delete it, mutate it, or depend on it.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Running `go mod download` during local smoke may need network if caches are cold. Mitigation: tests exercise build logic without network where possible; full smoke may require pre-cached modules or an approved network-capable environment.
|
||||
- [Risk] `RUN_MAX_JOBS>1` does not by itself make the current worker execute multiple jobs at once if its main loop is synchronous. Mitigation: workspace isolation is still required and tested directly; worker parallelism can remain a future scheduler improvement.
|
||||
- [Risk] Cross-compiling Windows packages on macOS validates packaging but not Windows service activation. Mitigation: local acceptance checks archive content and platform artifact flow; OS-native activation remains a target-environment proof.
|
||||
- [Risk] Two run checkouts can confuse operators. Mitigation: local debug prints the editable source, bucket snapshot, bootstrap binary, and final handoff documents the optional sibling checkout clearly.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Update local debug defaults to snapshot `browser/run` into `.local-debug` and pass the snapshot as `RUN_BUILD_SOURCE_ROOT`.
|
||||
2. Harden run distribution build workspace naming and add concurrency/isolation tests in the run checkout.
|
||||
3. Extend local smoke to download and checksum the generated run artifact.
|
||||
4. Run OpenSpec validation, structure checks, focused Platform tests, focused run tests, and smoke/script syntax checks.
|
||||
5. Rollback by pointing `RUN_SOURCE_DIR`/`RUN_REPO_DIR` at another checkout and disabling the new smoke assertions; generated artifacts remain ordinary platform artifacts.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Whether to keep `/Users/tasia/Desktop/code/run` as a personal scratch checkout is an operator workspace decision; it is not required by local debug after this change.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
The run build/download flow is split across Platform, platform_web, local debug scripts, and the independent run checkout. The editable run source may live at `browser/run` for convenience, but that directory must be treated as source input only. Local debug must snapshot or upload that source into an ignored, closed build bucket, let Platform dispatch `distribution.build`, build from the bucket, and prove the generated artifact can be downloaded and executed/updated without using the editable source tree as the runtime artifact.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Treat `run/` under this repository root as the editable independent run source checkout for local debug, while keeping it ignored by the browser repository and still owned by `git@git.npc0.com:admin343/run.git`.
|
||||
- Snapshot the editable run source into a closed ignored local build bucket before starting build-capable local debug flows; `RUN_BUILD_SOURCE_ROOT` must point at that bucket snapshot, not the editable checkout.
|
||||
- Build the local bootstrap run worker from the bucket snapshot instead of executing `browser/run` in place; generated run packages remain Platform-dispatched `distribution.build` artifacts.
|
||||
- Harden run distribution build workspaces so build output is isolated by plugin and job, not by server-wide mutable directories or editable source folders.
|
||||
- Add tests that prove two servers for the same plugin can generate separate run distributions without artifact/config/key/result cross-talk.
|
||||
- Upgrade local smoke proof so `scum-alpha` run generation is mandatory when the run endpoint advertises `distribution.build`, then download the generated artifact and verify safe metadata.
|
||||
- Document every configuration value operators must provide or may tune for local debug and run distribution builds.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `run-build-download-flow`: Covers local-debug source snapshotting, closed build buckets, plugin/job-scoped run package builds, browser-safe run artifact downloads, and same-plugin multi-server build isolation.
|
||||
|
||||
### Modified Capabilities
|
||||
- `run-distribution-and-client-managers`: Completed implementation must use the current-directory run checkout only as source input and prove generated run artifacts are downloadable.
|
||||
- `artifact-transfer-channel`: Completed implementation must prove browser downloads and run artifact uploads remain chunked, checksummed, and free of leaked host paths or secrets.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected roots: `scripts/`, `platform/`, `platform_web/`, and the ignored independent checkout at `run/`.
|
||||
- Affected local configuration: `RUN_SOURCE_DIR`/legacy `RUN_REPO_DIR`, `RUN_BUILD_BUCKET_ROOT`, `RUN_BUILD_SOURCE_ROOT`, `RUN_BOOTSTRAP_BIN`, `RUN_WORKSPACE_ROOT`, `RUN_SPOOL_ROOT`, `RUN_MAX_JOBS`, `RUN_PLATFORM_URL`, `RUN_ENDPOINT_ID`, platform storage/artifact paths, and bootstrap credentials.
|
||||
- Verification requires structure checks, Platform tests, run tests from `run/`, frontend tests where touched, OpenSpec validation, and local debug smoke evidence.
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Local debug snapshots run source into a closed build bucket
|
||||
The system SHALL default local debug run source input to the independent `run/` checkout under the browser repository root when that checkout exists, SHALL keep that checkout outside browser Git tracking, and SHALL snapshot that source into an ignored closed build bucket before build-capable local debug execution.
|
||||
|
||||
#### Scenario: Default run source snapshot resolution
|
||||
- **WHEN** local debug scripts start the run worker without an explicit `RUN_SOURCE_DIR` or legacy `RUN_REPO_DIR`
|
||||
- **THEN** they use `<browser-root>/run` as editable source input, copy it into `RUN_BUILD_SOURCE_ROOT` under an ignored local build bucket, and start the local bootstrap worker from a binary built from that snapshot
|
||||
|
||||
#### Scenario: Sibling checkout is optional
|
||||
- **WHEN** `/Users/tasia/Desktop/code/run` exists or does not exist
|
||||
- **THEN** local debug behavior does not depend on that sibling checkout unless `RUN_SOURCE_DIR` or legacy `RUN_REPO_DIR` is explicitly overridden
|
||||
|
||||
### Requirement: Run distribution builds are plugin and job isolated
|
||||
The run worker SHALL build generated run and client-manager distributions in a closed workspace scoped by plugin ID and job ID, and SHALL NOT use a mutable per-server build directory or editable source checkout for source, config, archive, upload, or terminal result state.
|
||||
|
||||
#### Scenario: Same plugin builds for multiple servers
|
||||
- **WHEN** two `distribution.build` jobs for different servers but the same plugin run concurrently or back-to-back
|
||||
- **THEN** each job writes to a distinct plugin/job workspace and uploads only its assigned artifact ID
|
||||
|
||||
#### Scenario: Build package config isolation
|
||||
- **WHEN** a run distribution archive is produced
|
||||
- **THEN** its config belongs to the job's server instance, plugin, endpoint, target, key generation, and auth key without leaking those secret values through API or UI responses
|
||||
|
||||
### Requirement: Generated run artifacts are downloadable after build success
|
||||
The system SHALL make a generated run distribution downloadable only after the build job succeeds and the referenced artifact is available, checksummed, and owned by the build job.
|
||||
|
||||
#### Scenario: Download latest generated run
|
||||
- **WHEN** a server has an available run distribution
|
||||
- **THEN** `/api/v1/server-instances/{id}/run/download` returns a browser-safe artifact reference and `/api/v1/artifacts/{artifactId}/content` returns bounded byte ranges with checksum headers
|
||||
|
||||
#### Scenario: No synthetic success before artifact upload
|
||||
- **WHEN** a distribution build result is reported before the artifact upload is available
|
||||
- **THEN** Platform rejects the terminal success and the distribution remains non-downloadable
|
||||
|
||||
### Requirement: Local smoke proves run build and download
|
||||
The local debug smoke SHALL fail when a build-capable run endpoint cannot complete run generation and artifact download for the SCUM fixture.
|
||||
|
||||
#### Scenario: Build-capable endpoint smoke
|
||||
- **WHEN** `scum-alpha` exposes `generate-run` as available
|
||||
- **THEN** smoke generates the run package, waits for the build job to succeed, opens the latest download reference, reads the artifact content, verifies size/checksum metadata, and rejects forbidden fragments
|
||||
|
||||
#### Scenario: Build-unavailable endpoint smoke
|
||||
- **WHEN** the endpoint does not advertise `distribution.build`
|
||||
- **THEN** smoke records that generation is unavailable without claiming a fake run artifact was built
|
||||
@@ -0,0 +1,33 @@
|
||||
## Prompt Boundaries
|
||||
|
||||
- [x] 0.1 Positive prompt (正向提示词): complete the first-party 服务器管理 run generation/download flow so `game.scum` servers can build, download, and safely reuse generated run artifacts with per-server keys and auditable jobs.
|
||||
- [x] 0.2 Directional prompt (方向提示词): preserve Platform-owned authorization, current platform_web visual style, `browser/run` as an ignored independent checkout, plugin/job-scoped run build workspaces, and verification through `scripts/check-structure.sh`, focused Go tests, OpenSpec validation, and local debug smoke.
|
||||
- [x] 0.3 Boundary prompt (任务边界): do not add billing, cloud host sales, arbitrary shell execution, raw key exposure, direct plugin transports, tracked browser/run source, or destructive changes to `/Users/tasia/Desktop/code/run`.
|
||||
|
||||
## 1. Local Debug Source Snapshot And Build Bucket
|
||||
|
||||
- [x] 1.1 Add `RUN_SOURCE_DIR` (legacy alias `RUN_REPO_DIR`) for editable source input and keep `/Users/tasia/Desktop/code/run` optional.
|
||||
- [x] 1.2 Snapshot `RUN_SOURCE_DIR` into `RUN_BUILD_SOURCE_ROOT` under `RUN_BUILD_BUCKET_ROOT` before local debug build-capable execution.
|
||||
- [x] 1.3 Build and start the local bootstrap run worker from the bucket snapshot instead of directly executing `browser/run`.
|
||||
- [x] 1.4 Make smoke evidence include the resolved source, bucket, snapshot, bootstrap binary, workspace, spool, and queue configuration.
|
||||
|
||||
## 2. Run Build Isolation
|
||||
|
||||
- [x] 2.1 Scope run distribution build workspaces by plugin ID and job ID.
|
||||
- [x] 2.2 Add run tests proving two same-plugin server builds produce distinct workspaces, artifact IDs, and package configs.
|
||||
- [x] 2.3 Confirm generated archive packaging still includes the executable and config for Linux/tar.gz and Windows/zip targets where locally testable.
|
||||
|
||||
## 3. Download And Smoke Proof
|
||||
|
||||
- [x] 3.1 Extend local smoke to open the latest run download reference after build success.
|
||||
- [x] 3.2 Read generated run artifact content in chunks and verify total size plus checksum metadata.
|
||||
- [x] 3.3 Keep forbidden-fragment checks over distribution, job, artifact, download reference, and chunk evidence.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Run `openspec validate complete-run-build-download-flow --strict`.
|
||||
- [x] 4.2 Run `scripts/check-structure.sh`.
|
||||
- [x] 4.3 Run focused Platform distribution/artifact tests.
|
||||
- [x] 4.4 Run focused `run/` distribution build tests.
|
||||
- [x] 4.5 Run `bash -n scripts/local-debug-smoke.sh scripts/local-debug-start.sh scripts/local-debug-env.sh`.
|
||||
- [x] 4.6 Run local debug smoke or record any environment blocker precisely.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-21
|
||||
@@ -0,0 +1,35 @@
|
||||
## Context
|
||||
|
||||
Server deletion currently reuses the archive path and already restricts the action to the instance owner or a platform administrator. What it does not do is re-check the caller's password before removing the server from active use, which leaves a destructive action one click away once a session is active.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Require a password confirmation before server deletion is accepted.
|
||||
- Preserve the existing owner/platform-admin authorization rule.
|
||||
- Keep the current soft-delete behavior that marks the server instance deleted and preserves history.
|
||||
|
||||
**Non-Goals:**
|
||||
- Implementing hard delete or permanent record erasure.
|
||||
- Changing unrelated server lifecycle permissions.
|
||||
- Adding a new authentication system or password reset flow.
|
||||
|
||||
## Decisions
|
||||
|
||||
- Keep the existing `DELETE /api/v1/server-instances/{id}` route and extend it with a JSON body containing the current password. This avoids inventing a parallel delete endpoint and keeps the UI and API aligned.
|
||||
- Verify deletion authorization in the service layer, not only in the frontend. The request must still be rejected even if the browser skips the confirmation UI.
|
||||
- Reuse the current session user's stored password hash and existing `verifyPassword` helper. No new credential store or token exchange is needed.
|
||||
- Return a generic forbidden response when the password confirmation fails. The UI can present that as a password-confirmation failure without exposing hash or account details.
|
||||
- Surface deletion from the server list card's "运行操作" popover in a "危险操作" group instead of placing it inside the detail metadata panel. Runtime actions remain permission-gated, while eligible creators/owners and platform admins can still reach the delete confirmation.
|
||||
- Update the user-facing copy from "归档" to "删除" so the destructive intent is clear wherever the action is exposed.
|
||||
|
||||
Alternatives considered:
|
||||
- Separate confirm endpoint: rejected because it adds another round trip without changing the security model.
|
||||
- Query-string password: rejected because sensitive data should not live in the URL.
|
||||
- Hard delete: rejected because the platform already models server removal as a deleted state with retained history.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Sending a password in the request body increases sensitivity of the delete call. → The request already runs over authenticated HTTPS; the frontend must avoid persisting the value beyond the dialog.
|
||||
- [Risk] The UI and API could drift if one side keeps "archive" wording or if the delete entry reappears in details. → Keep the confirmation dialog and API call site in the list runtime action flow together.
|
||||
- [Risk] Password confirmation may feel redundant to power users. → Keep the rule limited to destructive deletion only, not to normal lifecycle operations.
|
||||
@@ -0,0 +1,23 @@
|
||||
## Why
|
||||
|
||||
Server deletion currently trusts role and ownership alone, which is too loose for a destructive action. The UI also lets users trigger deletion without re-entering their password, so a stolen session or stray click can remove a server too easily.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Require server delete to be explicitly confirmed with the current user password.
|
||||
- Allow deletion only for the server creator/owner or a platform administrator.
|
||||
- Keep the existing archive/delete flow, but expose the destructive action from the server list runtime actions with an intentional password confirmation.
|
||||
- Return a clear authorization or password error when the confirmation fails.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `server-deletion`: deletion authorization and password confirmation for server instances.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
## Impact
|
||||
|
||||
- `platform/` delete handler, service authorization, and password verification logic.
|
||||
- `platform_web/` server list runtime-action delete confirmation dialog and API client request payload.
|
||||
- Automated tests covering authorization, password failure, and successful deletion.
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Authorized server deletion
|
||||
The system SHALL allow a server instance to be deleted only when the authenticated user is the instance owner or a platform administrator.
|
||||
|
||||
#### Scenario: Owner deletes a server
|
||||
- **WHEN** the instance owner submits a delete request for their server
|
||||
- **THEN** the system SHALL accept the request if all other delete checks pass
|
||||
|
||||
#### Scenario: Non-owner cannot delete
|
||||
- **WHEN** an authenticated user who is neither the owner nor a platform administrator submits a delete request
|
||||
- **THEN** the system SHALL reject the request with forbidden access
|
||||
|
||||
### Requirement: Password confirmation for deletion
|
||||
The system SHALL require the authenticated user to provide their current account password with every server delete request and SHALL reject the request if the password is missing or does not match the current session user.
|
||||
|
||||
#### Scenario: Password mismatch
|
||||
- **WHEN** the authenticated user submits the delete request with an incorrect password
|
||||
- **THEN** the system SHALL reject the request with forbidden access
|
||||
|
||||
#### Scenario: Password required
|
||||
- **WHEN** the authenticated user submits the delete request without a password
|
||||
- **THEN** the system SHALL reject the request as invalid input or forbidden access
|
||||
|
||||
### Requirement: Safe server removal state
|
||||
The system SHALL continue to reject deletion when the server instance is running or installing, and SHALL otherwise mark the server instance as deleted while preserving historical records.
|
||||
|
||||
#### Scenario: Running server cannot be deleted
|
||||
- **WHEN** a delete request targets a running server instance
|
||||
- **THEN** the system SHALL reject the request and keep the server instance intact
|
||||
|
||||
#### Scenario: Successful deletion marks deleted state
|
||||
- **WHEN** a valid delete request targets a stopped or ready server instance
|
||||
- **THEN** the system SHALL mark the server instance as deleted and return the updated instance
|
||||
@@ -0,0 +1,20 @@
|
||||
## 1. Backend delete confirmation
|
||||
|
||||
- [x] 1.1 Add a server delete request DTO and extend the service/API contract to accept the current session password on delete.
|
||||
- [x] 1.2 Verify the current session password in the server deletion flow after owner/admin authorization and keep the existing deleted-state behavior.
|
||||
- [x] 1.3 Update API handler docs and backend tests for owner/admin success, password failure, and unsafe-state rejection.
|
||||
|
||||
## 2. Frontend delete flow
|
||||
|
||||
- [x] 2.1 Update the server detail delete confirmation dialog to collect a password and submit it with the delete request.
|
||||
- [x] 2.2 Rename the user-facing action copy from archive to delete where the destructive action is exposed.
|
||||
- [x] 2.3 Update the API client, contracts, and frontend tests for the new delete payload and confirmation state.
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Run the structure check and focused backend/frontend tests for the delete flow.
|
||||
|
||||
## 4. Follow-up UI placement
|
||||
|
||||
- [x] 4.1 Move the delete confirmation entry from server detail metadata to the server list runtime action popover.
|
||||
- [x] 4.2 Update frontend tests and verification for the new delete entry placement.
|
||||
Reference in New Issue
Block a user