separate server run bindings from deployment targets
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-25
|
||||
@@ -0,0 +1,59 @@
|
||||
## Context
|
||||
|
||||
`ServerInstance.RunEndpointID` currently points at a global endpoint selected while creating the server. That endpoint both executes the initial install/build jobs and is later treated as the endpoint for a generated, server-scoped Run. The type has no server ownership, registration accepts any endpoint ID after validating only the component key, and reset revokes the shared endpoint session. The browser consequently asks for a Run before the server-specific Run exists.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Keep a server bound to exactly one dedicated Run endpoint after registration.
|
||||
- Preserve an explicit deployment target for target OS, architecture, and trusted build work without treating it as the server Run.
|
||||
- Make draft creation, reserved endpoint identity, Run registration, deployment, replacement, and revocation stateful and auditable.
|
||||
- Prevent authenticated Run binaries from claiming another server endpoint or jobs.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Adding host provisioning, SSH, a second executor source tree, or browser access to host paths and credentials.
|
||||
- Migrating already-active legacy server endpoints automatically; they remain readable and are handled through an explicit future migration.
|
||||
- Changing plugin runtime-profile, channel isolation, or artifact confidentiality rules.
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Store deployment target and dedicated Run separately
|
||||
|
||||
`ServerInstance` gains `DeploymentTargetID` while `RunEndpointID` is reserved for the dedicated endpoint. A server draft can have a target but no Run endpoint. The target must be an online compatible endpoint with `distribution.build`; it is used only to build the dedicated Run package. Lifecycle deployment and subsequent runtime work require the dedicated endpoint.
|
||||
|
||||
This avoids overloading an existing field. Reusing `RunEndpointID` with a role enum would leave historical jobs and control sessions ambiguous.
|
||||
|
||||
### 2. Reserve deterministic endpoint ownership before package generation
|
||||
|
||||
The dedicated Run endpoint ID is deterministic (`server-run-<server instance id>`). Package generation persists that reserved identity. A component-authenticated hello must use this identity, name the same server and Run component, and is rejected if the endpoint belongs to another server. Control registration records the ownership only after all checks pass.
|
||||
|
||||
This avoids a browser-chosen endpoint ID and permits Run to self-register without exposing a registration credential separate from the component key.
|
||||
|
||||
### 3. Draft first; deployment is explicit
|
||||
|
||||
The create workflow always creates a `draft`; choosing a deployment target does not queue installation. After a Run package is generated, downloaded, and registers online, the operator explicitly deploys the definition. This removes the bootstrap loop and keeps all execution behind an authenticated Run.
|
||||
|
||||
### 4. Use a focused additive migration
|
||||
|
||||
The new fields are additive. Legacy instances with a populated `RunEndpointID` and no `DeploymentTargetID` keep their existing behavior through a compatibility branch. New server workflow requests use the new draft path. A later migration can opt legacy records into exclusive ownership only after operational review.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [A build target must already exist] → The UI calls it a deployment target and explains that it is a trusted build worker, not the dedicated Run.
|
||||
- [Legacy endpoints can be shared] → New exclusive ownership checks apply only to newly reserved endpoints; legacy records are not silently broken.
|
||||
- [Registration failure leaves a package unusable] → The server remains a recoverable draft with a redacted reason and can regenerate/reset the Run key.
|
||||
- [Run repository must adopt the identity] → Document the revised hello contract and gate deployment until matching registration occurs.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add additive domain/model/DTO fields and persistence compatibility.
|
||||
2. Create new servers as target-bound drafts and generate packages through their deployment target.
|
||||
3. Require reserved identity checks at component hello and only dispatch deployment to the dedicated endpoint.
|
||||
4. Update the independent Run implementation to send the reserved endpoint ID, then enable the new workflow in environments that have it.
|
||||
5. Roll back by leaving new servers as drafts; no browser or platform fallback executes work directly on a target host.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- The independent Run repository must consume the returned/reserved endpoint identity before an end-to-end real-machine rollout.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
The current server workflow uses one `RunEndpoint` both as a pre-existing worker that builds and installs software and as the server-scoped Run binary generated after creation. This creates a bootstrap loop, permits multiple servers to share one endpoint despite the intended one-server/one-Run model, and leaves component registration insufficiently bound to its server.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a server-scoped Run binding with an explicit lifecycle from draft, through target selection and Run registration, to deployment.
|
||||
- **BREAKING** Separate a deployment target from the dedicated Run endpoint that controls one server; a selected target no longer immediately dispatches installation.
|
||||
- Require a generated Run to register with the endpoint identity reserved for its server before deployment or runtime jobs can be dispatched.
|
||||
- Reject endpoint reuse, mismatched component registration, and cross-server job access; revoke only the Run bound to the affected server.
|
||||
- Update the server creation workflow to save a draft, describe the selected target accurately, and guide the operator through Run generation, registration, and deployment.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `server-scoped-run-binding`: Securely reserve, register, validate, replace, and revoke one dedicated Run endpoint for a server instance.
|
||||
- `server-run-bootstrap-workflow`: Create a server as a draft and progress it through deployment-target selection, dedicated Run registration, and explicit deployment.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- None.
|
||||
|
||||
## Impact
|
||||
|
||||
- `platform/`: domain, DTOs, models/repositories, services, control registration, lifecycle dispatch, distribution build selection, validation, API documentation, and tests.
|
||||
- `platform_web/`: API types, server creation/deployment workflow, Run builder status and focused tests.
|
||||
- `run/`: independent repository coordination is required for the revised registration identity; this repository will only update its public contract.
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Server creation is a draft-to-deployment workflow
|
||||
The management console SHALL create a server definition as a draft, even when a deployment target is selected. It MUST NOT dispatch installation until the dedicated Run has registered and the operator explicitly deploys.
|
||||
|
||||
#### Scenario: Create with a deployment target
|
||||
- **WHEN** an operator selects a compatible deployment target and confirms server creation
|
||||
- **THEN** the console reports a saved draft and guides the operator to generate and register the dedicated Run
|
||||
|
||||
#### Scenario: Deploy before Run registration
|
||||
- **WHEN** an operator tries to deploy a draft before its dedicated Run is online
|
||||
- **THEN** the platform rejects the request with a safe registration-required reason and dispatches no job
|
||||
|
||||
### Requirement: The console distinguishes target from dedicated Run
|
||||
The console SHALL label the initial selection as a deployment target and SHALL explain that it is a trusted build target, not the server's dedicated Run.
|
||||
|
||||
#### Scenario: Review server creation
|
||||
- **WHEN** an operator reviews a new server definition
|
||||
- **THEN** the review identifies the deployment target and says that a dedicated Run must be generated and registered before deployment
|
||||
@@ -0,0 +1,30 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: A dedicated Run endpoint is exclusively bound to one server
|
||||
The platform SHALL reserve one dedicated Run endpoint identity for each newly created server and SHALL reject attempts to bind that identity to another server. The deployment target SHALL be stored separately from the dedicated endpoint.
|
||||
|
||||
#### Scenario: A target is selected for a new server
|
||||
- **WHEN** an operator creates a server with a compatible deployment target
|
||||
- **THEN** the platform saves the target and a reserved dedicated Run identity on a draft without dispatching an install job
|
||||
|
||||
#### Scenario: A dedicated endpoint is reused
|
||||
- **WHEN** a caller attempts to register or bind a dedicated endpoint reserved for another server
|
||||
- **THEN** the platform rejects the request without changing either server binding or control session
|
||||
|
||||
### Requirement: Component hello is constrained to its server binding
|
||||
The platform SHALL accept a component-authenticated Run hello only when the server ID, component kind, current key generation, and reserved endpoint ID all match the server binding.
|
||||
|
||||
#### Scenario: A generated Run registers correctly
|
||||
- **WHEN** a generated Run presents the current key and its reserved endpoint identity
|
||||
- **THEN** the platform records the endpoint online and allows server-scoped work to be dispatched
|
||||
|
||||
#### Scenario: A generated Run claims another endpoint
|
||||
- **WHEN** a generated Run presents a valid key but an endpoint identity that is not reserved for its server
|
||||
- **THEN** the platform rejects the hello and does not replace any endpoint session
|
||||
|
||||
### Requirement: Revocation affects only the bound dedicated Run
|
||||
The platform SHALL revoke a Run control session only when the endpoint is exclusively bound to the server whose Run key is reset.
|
||||
|
||||
#### Scenario: Reset a dedicated Run key
|
||||
- **WHEN** an operator resets a server Run key
|
||||
- **THEN** the platform revokes that server's dedicated Run session and leaves unrelated server endpoints unchanged
|
||||
@@ -0,0 +1,20 @@
|
||||
## 1. Server binding contract
|
||||
|
||||
- [x] 1.1 Add deployment-target and dedicated-Run ownership fields to domain, persistence, DTO, and safe server projections.
|
||||
- [x] 1.2 Validate exclusive dedicated endpoint ownership and draft/deployment state transitions.
|
||||
|
||||
## 2. Secure lifecycle and control behavior
|
||||
|
||||
- [x] 2.1 Create target-bound drafts, reserve their dedicated Run identity, and dispatch deployment only to a registered dedicated Run.
|
||||
- [x] 2.2 Build Run distributions through the deployment target while recording the reserved dedicated endpoint identity.
|
||||
- [x] 2.3 Constrain component hello and revocation to the matching server-owned endpoint.
|
||||
|
||||
## 3. Management console workflow
|
||||
|
||||
- [x] 3.1 Update API types and the creation workflow to label deployment targets and save target-bound drafts.
|
||||
- [x] 3.2 Guide draft operators through dedicated Run registration before deployment and update focused UI tests.
|
||||
|
||||
## 4. Verification
|
||||
|
||||
- [x] 4.1 Add backend tests for exclusive ownership, registration mismatch rejection, scoped revocation, and draft deployment gating.
|
||||
- [x] 4.2 Run formatting, focused tests, full structural validation, strict OpenSpec validation, and build/type checks.
|
||||
Reference in New Issue
Block a user