add release orchestrator docs and sprints gaps fills
This commit is contained in:
274
docs/modules/release-orchestrator/api/agents.md
Normal file
274
docs/modules/release-orchestrator/api/agents.md
Normal file
@@ -0,0 +1,274 @@
|
||||
# Agent APIs
|
||||
|
||||
> API endpoints for agent registration, lifecycle management, and task coordination.
|
||||
|
||||
**Status:** Planned (not yet implemented)
|
||||
**Source:** [Architecture Advisory Section 6.3.2](../../../product/advisories/09-Jan-2026%20-%20Stella%20Ops%20Orchestrator%20Architecture.md)
|
||||
**Related Modules:** [Agents Module](../modules/agents.md), [Agent Security](../security/agent-security.md)
|
||||
|
||||
## Overview
|
||||
|
||||
The Agent API provides endpoints for registering deployment agents, managing their lifecycle, and coordinating task execution. Agents use mTLS for secure communication after initial registration.
|
||||
|
||||
---
|
||||
|
||||
## Registration Endpoints
|
||||
|
||||
### Register Agent
|
||||
|
||||
**Endpoint:** `POST /api/v1/agents/register`
|
||||
|
||||
Registers a new agent with the orchestrator. Requires a one-time registration token.
|
||||
|
||||
**Headers:**
|
||||
```
|
||||
X-Agent-Token: {registration-token}
|
||||
```
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "agent-prod-01",
|
||||
"version": "1.0.0",
|
||||
"capabilities": ["docker", "compose"],
|
||||
"labels": {
|
||||
"datacenter": "us-east-1",
|
||||
"role": "deployment"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"agentId": "uuid",
|
||||
"token": "jwt-token-for-subsequent-requests",
|
||||
"config": {
|
||||
"heartbeatInterval": 30,
|
||||
"taskPollInterval": 5,
|
||||
"logLevel": "info"
|
||||
},
|
||||
"certificate": {
|
||||
"cert": "-----BEGIN CERTIFICATE-----...",
|
||||
"key": "-----BEGIN PRIVATE KEY-----...",
|
||||
"ca": "-----BEGIN CERTIFICATE-----...",
|
||||
"expiresAt": "2026-01-11T14:23:45Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Registration token is single-use and expires after 24 hours
|
||||
- After registration, agent must use mTLS for all subsequent requests
|
||||
- Certificate is short-lived (24h) and must be renewed via heartbeat
|
||||
|
||||
---
|
||||
|
||||
## Lifecycle Endpoints
|
||||
|
||||
### List Agents
|
||||
|
||||
**Endpoint:** `GET /api/v1/agents`
|
||||
|
||||
**Query Parameters:**
|
||||
- `status` (string): Filter by status (`online`, `offline`, `degraded`)
|
||||
- `capability` (string): Filter by capability (`docker`, `compose`, `ssh`, `winrm`, `ecs`, `nomad`)
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "agent-prod-01",
|
||||
"version": "1.0.0",
|
||||
"status": "online",
|
||||
"capabilities": ["docker", "compose"],
|
||||
"lastHeartbeat": "2026-01-10T14:23:45Z",
|
||||
"resourceUsage": {
|
||||
"cpu": 15.5,
|
||||
"memory": 45.2
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Get Agent
|
||||
|
||||
**Endpoint:** `GET /api/v1/agents/{id}`
|
||||
|
||||
**Response:** `200 OK` - Full agent details including assigned targets
|
||||
|
||||
### Update Agent
|
||||
|
||||
**Endpoint:** `PUT /api/v1/agents/{id}`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"labels": {
|
||||
"datacenter": "us-west-2"
|
||||
},
|
||||
"capabilities": ["docker", "compose", "ssh"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK` - Updated agent
|
||||
|
||||
### Delete Agent
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/agents/{id}`
|
||||
|
||||
Revokes agent credentials and removes registration.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{ "deleted": true }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Heartbeat Endpoints
|
||||
|
||||
### Send Heartbeat
|
||||
|
||||
**Endpoint:** `POST /api/v1/agents/{id}/heartbeat`
|
||||
|
||||
Agents must send heartbeats at the configured interval to maintain online status and receive pending tasks.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"resourceUsage": {
|
||||
"cpu": 15.5,
|
||||
"memory": 45.2,
|
||||
"disk": 60.0
|
||||
},
|
||||
"capabilities": ["docker", "compose"],
|
||||
"runningTasks": 2
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"taskId": "uuid",
|
||||
"taskType": "docker.pull",
|
||||
"payload": {
|
||||
"image": "myapp",
|
||||
"tag": "v2.3.1",
|
||||
"digest": "sha256:abc123..."
|
||||
},
|
||||
"credentials": {
|
||||
"registry.username": "user",
|
||||
"registry.password": "token"
|
||||
},
|
||||
"timeout": 300
|
||||
}
|
||||
],
|
||||
"certificateRenewal": {
|
||||
"cert": "-----BEGIN CERTIFICATE-----...",
|
||||
"expiresAt": "2026-01-11T14:23:45Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Certificate renewal is included when current certificate is within 1 hour of expiration
|
||||
- Tasks array contains pending work for the agent
|
||||
- Missing heartbeats for 3 intervals marks agent as `offline`
|
||||
|
||||
---
|
||||
|
||||
## Task Endpoints
|
||||
|
||||
### Complete Task
|
||||
|
||||
**Endpoint:** `POST /api/v1/agents/{id}/tasks/{taskId}/complete`
|
||||
|
||||
Reports task completion status back to the orchestrator.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"result": {
|
||||
"imageId": "sha256:abc123...",
|
||||
"containerId": "container-uuid"
|
||||
},
|
||||
"logs": [
|
||||
{ "timestamp": "2026-01-10T14:23:45Z", "level": "info", "message": "Pulling image..." },
|
||||
{ "timestamp": "2026-01-10T14:23:50Z", "level": "info", "message": "Image pulled successfully" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{ "acknowledged": true }
|
||||
```
|
||||
|
||||
### Get Pending Tasks
|
||||
|
||||
**Endpoint:** `GET /api/v1/agents/{id}/tasks`
|
||||
|
||||
Alternative to heartbeat for polling pending tasks.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"taskId": "uuid",
|
||||
"taskType": "docker.run",
|
||||
"priority": 10,
|
||||
"createdAt": "2026-01-10T14:20:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## WebSocket Endpoints
|
||||
|
||||
### Task Stream
|
||||
|
||||
**Endpoint:** `WS /api/v1/agents/{id}/task-stream`
|
||||
|
||||
Real-time task assignment stream for agents.
|
||||
|
||||
**Messages (Server to Agent):**
|
||||
```json
|
||||
{ "type": "task_assigned", "task": { "taskId": "uuid", "taskType": "docker.pull", ... } }
|
||||
{ "type": "task_cancelled", "taskId": "uuid" }
|
||||
```
|
||||
|
||||
**Messages (Agent to Server):**
|
||||
```json
|
||||
{ "type": "task_progress", "taskId": "uuid", "progress": 50, "message": "Pulling layer 3/5" }
|
||||
{ "type": "task_log", "taskId": "uuid", "level": "info", "message": "..." }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Status Code | Description |
|
||||
|-------------|-------------|
|
||||
| `401` | Invalid or expired registration token |
|
||||
| `403` | Agent not authorized for this operation |
|
||||
| `404` | Agent not found |
|
||||
| `409` | Agent name already registered |
|
||||
| `503` | Agent offline or unreachable |
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Environments API](environments.md)
|
||||
- [Agents Module](../modules/agents.md)
|
||||
- [Agent Security](../security/agent-security.md)
|
||||
- [WebSocket APIs](websockets.md)
|
||||
289
docs/modules/release-orchestrator/api/environments.md
Normal file
289
docs/modules/release-orchestrator/api/environments.md
Normal file
@@ -0,0 +1,289 @@
|
||||
# Environment Management APIs
|
||||
|
||||
> API endpoints for managing environments, targets, agents, freeze windows, and inventory.
|
||||
|
||||
**Status:** Planned (not yet implemented)
|
||||
**Source:** [Architecture Advisory Section 6.3.2](../../../product/advisories/09-Jan-2026%20-%20Stella%20Ops%20Orchestrator%20Architecture.md)
|
||||
**Related Modules:** [Environment Manager](../modules/environment-manager.md), [Agents](../modules/agents.md)
|
||||
|
||||
## Overview
|
||||
|
||||
The Environment Management API provides CRUD operations for environments, target groups, deployment targets, agents, freeze windows, and inventory synchronization. All endpoints require authentication and respect tenant isolation via Row-Level Security.
|
||||
|
||||
---
|
||||
|
||||
## Environment Endpoints
|
||||
|
||||
### Create Environment
|
||||
|
||||
**Endpoint:** `POST /api/v1/environments`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "production",
|
||||
"displayName": "Production",
|
||||
"orderIndex": 3,
|
||||
"config": {
|
||||
"deploymentTimeout": 600,
|
||||
"healthCheckInterval": 30
|
||||
},
|
||||
"requiredApprovals": 2,
|
||||
"requireSod": true,
|
||||
"promotionPolicy": "default"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "production",
|
||||
"displayName": "Production",
|
||||
"orderIndex": 3,
|
||||
"isProduction": true,
|
||||
"requiredApprovals": 2,
|
||||
"requireSeparationOfDuties": true,
|
||||
"createdAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
### List Environments
|
||||
|
||||
**Endpoint:** `GET /api/v1/environments`
|
||||
|
||||
**Query Parameters:**
|
||||
- `includeState` (boolean): Include current release state
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "development",
|
||||
"displayName": "Development",
|
||||
"orderIndex": 1,
|
||||
"currentRelease": {
|
||||
"id": "release-uuid",
|
||||
"name": "myapp-v2.3.1",
|
||||
"deployedAt": "2026-01-09T10:00:00Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Get Environment
|
||||
|
||||
**Endpoint:** `GET /api/v1/environments/{id}`
|
||||
|
||||
**Response:** `200 OK` - Full environment details
|
||||
|
||||
### Update Environment
|
||||
|
||||
**Endpoint:** `PUT /api/v1/environments/{id}`
|
||||
|
||||
**Request:** Partial environment object
|
||||
|
||||
**Response:** `200 OK` - Updated environment
|
||||
|
||||
### Delete Environment
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/environments/{id}`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{ "deleted": true }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Freeze Window Endpoints
|
||||
|
||||
### Create Freeze Window
|
||||
|
||||
**Endpoint:** `POST /api/v1/environments/{envId}/freeze-windows`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"start": "2026-01-15T00:00:00Z",
|
||||
"end": "2026-01-20T00:00:00Z",
|
||||
"reason": "Holiday freeze",
|
||||
"exceptions": ["user-uuid-1", "user-uuid-2"]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"environmentId": "env-uuid",
|
||||
"start": "2026-01-15T00:00:00Z",
|
||||
"end": "2026-01-20T00:00:00Z",
|
||||
"reason": "Holiday freeze",
|
||||
"createdBy": "user-uuid"
|
||||
}
|
||||
```
|
||||
|
||||
### List Freeze Windows
|
||||
|
||||
**Endpoint:** `GET /api/v1/environments/{envId}/freeze-windows`
|
||||
|
||||
**Query Parameters:**
|
||||
- `active` (boolean): Filter to active freeze windows only
|
||||
|
||||
**Response:** `200 OK` - Array of freeze windows
|
||||
|
||||
### Delete Freeze Window
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/environments/{envId}/freeze-windows/{windowId}`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{ "deleted": true }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Target Group Endpoints
|
||||
|
||||
### Create Target Group
|
||||
|
||||
**Endpoint:** `POST /api/v1/environments/{envId}/target-groups`
|
||||
|
||||
### List Target Groups
|
||||
|
||||
**Endpoint:** `GET /api/v1/environments/{envId}/target-groups`
|
||||
|
||||
### Get Target Group
|
||||
|
||||
**Endpoint:** `GET /api/v1/target-groups/{id}`
|
||||
|
||||
### Update Target Group
|
||||
|
||||
**Endpoint:** `PUT /api/v1/target-groups/{id}`
|
||||
|
||||
### Delete Target Group
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/target-groups/{id}`
|
||||
|
||||
---
|
||||
|
||||
## Target Endpoints
|
||||
|
||||
### Create Target
|
||||
|
||||
**Endpoint:** `POST /api/v1/targets`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"environmentId": "env-uuid",
|
||||
"targetGroupId": "group-uuid",
|
||||
"name": "prod-web-01",
|
||||
"targetType": "docker_host",
|
||||
"connection": {
|
||||
"host": "192.168.1.100",
|
||||
"port": 2375,
|
||||
"tlsEnabled": true
|
||||
},
|
||||
"labels": {
|
||||
"role": "web",
|
||||
"datacenter": "us-east-1"
|
||||
},
|
||||
"deploymentDirectory": "/opt/deployments"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "prod-web-01",
|
||||
"targetType": "docker_host",
|
||||
"healthStatus": "unknown",
|
||||
"createdAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
### List Targets
|
||||
|
||||
**Endpoint:** `GET /api/v1/targets`
|
||||
|
||||
**Query Parameters:**
|
||||
- `environmentId` (UUID): Filter by environment
|
||||
- `targetType` (string): Filter by type (`docker_host`, `compose_host`, `ecs_service`, `nomad_job`)
|
||||
- `labels` (JSON): Filter by labels
|
||||
- `healthStatus` (string): Filter by health status
|
||||
|
||||
**Response:** `200 OK` - Array of targets
|
||||
|
||||
### Get Target
|
||||
|
||||
**Endpoint:** `GET /api/v1/targets/{id}`
|
||||
|
||||
### Update Target
|
||||
|
||||
**Endpoint:** `PUT /api/v1/targets/{id}`
|
||||
|
||||
### Delete Target
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/targets/{id}`
|
||||
|
||||
### Trigger Health Check
|
||||
|
||||
**Endpoint:** `POST /api/v1/targets/{id}/health-check`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"message": "Docker daemon responding",
|
||||
"checkedAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Get Version Sticker
|
||||
|
||||
**Endpoint:** `GET /api/v1/targets/{id}/sticker`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"releaseId": "uuid",
|
||||
"releaseName": "myapp-v2.3.1",
|
||||
"components": [
|
||||
{
|
||||
"componentId": "uuid",
|
||||
"componentName": "api",
|
||||
"digest": "sha256:abc123..."
|
||||
}
|
||||
],
|
||||
"deployedAt": "2026-01-09T10:00:00Z",
|
||||
"deployedBy": "user-uuid"
|
||||
}
|
||||
```
|
||||
|
||||
### Check Drift
|
||||
|
||||
**Endpoint:** `GET /api/v1/targets/{id}/drift`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"hasDrift": true,
|
||||
"expected": { "releaseId": "uuid", "digest": "sha256:abc..." },
|
||||
"actual": { "digest": "sha256:def..." },
|
||||
"differences": [
|
||||
{ "component": "api", "expected": "sha256:abc...", "actual": "sha256:def..." }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Agents API](agents.md)
|
||||
- [Environment Manager Module](../modules/environment-manager.md)
|
||||
- [Agent Security](../security/agent-security.md)
|
||||
317
docs/modules/release-orchestrator/api/promotions.md
Normal file
317
docs/modules/release-orchestrator/api/promotions.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# Promotion & Approval APIs
|
||||
|
||||
> API endpoints for managing promotions, approvals, and gate evaluations.
|
||||
|
||||
**Status:** Planned (not yet implemented)
|
||||
**Source:** [Architecture Advisory Section 6.3.5](../../../product/advisories/09-Jan-2026%20-%20Stella%20Ops%20Orchestrator%20Architecture.md)
|
||||
**Related Modules:** [Promotion Manager Module](../modules/promotion-manager.md), [Workflow Promotion](../workflow/promotion.md)
|
||||
|
||||
## Overview
|
||||
|
||||
The Promotion API provides endpoints for requesting release promotions between environments, managing approvals, and evaluating promotion gates. Promotions enforce separation of duties (SoD) and require configured approvals before deployment proceeds.
|
||||
|
||||
---
|
||||
|
||||
## Promotion Endpoints
|
||||
|
||||
### Create Promotion Request
|
||||
|
||||
**Endpoint:** `POST /api/v1/promotions`
|
||||
|
||||
Initiates a promotion request for a release to a target environment.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"releaseId": "uuid",
|
||||
"targetEnvironmentId": "uuid",
|
||||
"reason": "Deploying v2.3.1 with critical bug fix"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"releaseId": "uuid",
|
||||
"releaseName": "myapp-v2.3.1",
|
||||
"sourceEnvironmentId": "uuid",
|
||||
"sourceEnvironmentName": "Staging",
|
||||
"targetEnvironmentId": "uuid",
|
||||
"targetEnvironmentName": "Production",
|
||||
"status": "pending",
|
||||
"requestedBy": "user-uuid",
|
||||
"requestedAt": "2026-01-10T14:23:45Z",
|
||||
"reason": "Deploying v2.3.1 with critical bug fix"
|
||||
}
|
||||
```
|
||||
|
||||
**Status Flow:**
|
||||
```
|
||||
pending -> awaiting_approval -> approved -> deploying -> deployed
|
||||
-> rejected
|
||||
-> cancelled
|
||||
-> failed
|
||||
-> rolled_back
|
||||
```
|
||||
|
||||
### List Promotions
|
||||
|
||||
**Endpoint:** `GET /api/v1/promotions`
|
||||
|
||||
**Query Parameters:**
|
||||
- `status` (string): Filter by status
|
||||
- `releaseId` (UUID): Filter by release
|
||||
- `environmentId` (UUID): Filter by target environment
|
||||
- `page` (number): Page number
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"releaseName": "myapp-v2.3.1",
|
||||
"targetEnvironmentName": "Production",
|
||||
"status": "awaiting_approval",
|
||||
"requestedAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
],
|
||||
"meta": { "page": 1, "totalCount": 25 }
|
||||
}
|
||||
```
|
||||
|
||||
### Get Promotion
|
||||
|
||||
**Endpoint:** `GET /api/v1/promotions/{id}`
|
||||
|
||||
**Response:** `200 OK` - Full promotion with decision record and approvals
|
||||
|
||||
### Approve Promotion
|
||||
|
||||
**Endpoint:** `POST /api/v1/promotions/{id}/approve`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"comment": "Approved after reviewing security scan results"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"status": "approved",
|
||||
"approvalCount": 2,
|
||||
"requiredApprovals": 2,
|
||||
"decidedAt": "2026-01-10T14:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Separation of Duties (SoD): The user who requested the promotion cannot approve it if `requireSod` is enabled on the environment
|
||||
- Multi-party approval: Promotion proceeds when `approvalCount >= requiredApprovals`
|
||||
|
||||
### Reject Promotion
|
||||
|
||||
**Endpoint:** `POST /api/v1/promotions/{id}/reject`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"reason": "Security vulnerabilities not addressed"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK` - Updated promotion with `status: rejected`
|
||||
|
||||
### Cancel Promotion
|
||||
|
||||
**Endpoint:** `POST /api/v1/promotions/{id}/cancel`
|
||||
|
||||
Cancels a pending or awaiting_approval promotion.
|
||||
|
||||
**Response:** `200 OK` - Updated promotion with `status: cancelled`
|
||||
|
||||
---
|
||||
|
||||
## Decision & Evidence Endpoints
|
||||
|
||||
### Get Decision Record
|
||||
|
||||
**Endpoint:** `GET /api/v1/promotions/{id}/decision`
|
||||
|
||||
Returns the full decision record including gate evaluations.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"promotionId": "uuid",
|
||||
"decision": "allow",
|
||||
"decidedAt": "2026-01-10T14:30:00Z",
|
||||
"gates": [
|
||||
{
|
||||
"gateName": "security-gate",
|
||||
"passed": true,
|
||||
"details": {
|
||||
"criticalCount": 0,
|
||||
"highCount": 3,
|
||||
"maxCritical": 0,
|
||||
"maxHigh": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"gateName": "freeze-window-gate",
|
||||
"passed": true,
|
||||
"details": {
|
||||
"activeFreezeWindow": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"approvals": [
|
||||
{
|
||||
"approverId": "uuid",
|
||||
"approverName": "John Doe",
|
||||
"decision": "approved",
|
||||
"comment": "LGTM",
|
||||
"approvedAt": "2026-01-10T14:28:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Get Approvals
|
||||
|
||||
**Endpoint:** `GET /api/v1/promotions/{id}/approvals`
|
||||
|
||||
**Response:** `200 OK` - Array of approval records
|
||||
|
||||
### Get Evidence Packet
|
||||
|
||||
**Endpoint:** `GET /api/v1/promotions/{id}/evidence`
|
||||
|
||||
Returns the signed evidence packet for the promotion decision.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"type": "release_decision",
|
||||
"version": "1.0",
|
||||
"content": { ... },
|
||||
"contentHash": "sha256:abc...",
|
||||
"signature": "base64-signature",
|
||||
"signatureAlgorithm": "ECDSA-P256-SHA256",
|
||||
"signerKeyRef": "key-id",
|
||||
"generatedAt": "2026-01-10T14:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gate Preview Endpoints
|
||||
|
||||
### Preview Gate Evaluation
|
||||
|
||||
**Endpoint:** `POST /api/v1/promotions/preview-gates`
|
||||
|
||||
Evaluates gates without creating a promotion (dry run).
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"releaseId": "uuid",
|
||||
"targetEnvironmentId": "uuid"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"wouldPass": false,
|
||||
"gates": [
|
||||
{
|
||||
"gateName": "security-gate",
|
||||
"passed": false,
|
||||
"blocking": true,
|
||||
"message": "3 critical vulnerabilities exceed threshold (max: 0)"
|
||||
},
|
||||
{
|
||||
"gateName": "freeze-window-gate",
|
||||
"passed": true,
|
||||
"blocking": false,
|
||||
"message": "No active freeze window"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Approval Policy Endpoints
|
||||
|
||||
### Create Approval Policy
|
||||
|
||||
**Endpoint:** `POST /api/v1/approval-policies`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "production-policy",
|
||||
"environmentId": "uuid",
|
||||
"requiredApprovals": 2,
|
||||
"approverGroups": ["release-managers", "sre-team"],
|
||||
"requireSeparationOfDuties": true,
|
||||
"autoExpireHours": 24
|
||||
}
|
||||
```
|
||||
|
||||
### List Approval Policies
|
||||
|
||||
**Endpoint:** `GET /api/v1/approval-policies`
|
||||
|
||||
### Get Approval Policy
|
||||
|
||||
**Endpoint:** `GET /api/v1/approval-policies/{id}`
|
||||
|
||||
### Update Approval Policy
|
||||
|
||||
**Endpoint:** `PUT /api/v1/approval-policies/{id}`
|
||||
|
||||
### Delete Approval Policy
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/approval-policies/{id}`
|
||||
|
||||
---
|
||||
|
||||
## Current User Endpoints
|
||||
|
||||
### Get My Pending Approvals
|
||||
|
||||
**Endpoint:** `GET /api/v1/my/pending-approvals`
|
||||
|
||||
Returns promotions awaiting approval from the current user.
|
||||
|
||||
**Response:** `200 OK` - Array of promotions
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Status Code | Description |
|
||||
|-------------|-------------|
|
||||
| `400` | Invalid promotion request |
|
||||
| `403` | User cannot approve (SoD violation or not in approver list) |
|
||||
| `404` | Promotion not found |
|
||||
| `409` | Promotion already decided |
|
||||
| `422` | Gate evaluation failed |
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Workflows API](workflows.md)
|
||||
- [Releases API](releases.md)
|
||||
- [Promotion Manager Module](../modules/promotion-manager.md)
|
||||
- [Security Gates](../modules/promotion-manager.md#security-gate)
|
||||
345
docs/modules/release-orchestrator/api/releases.md
Normal file
345
docs/modules/release-orchestrator/api/releases.md
Normal file
@@ -0,0 +1,345 @@
|
||||
# Release Management APIs
|
||||
|
||||
> API endpoints for managing components, versions, and release bundles.
|
||||
|
||||
**Status:** Planned (not yet implemented)
|
||||
**Source:** [Architecture Advisory Section 6.3.3](../../../product/advisories/09-Jan-2026%20-%20Stella%20Ops%20Orchestrator%20Architecture.md)
|
||||
**Related Modules:** [Release Manager Module](../modules/release-manager.md), [Integration Hub](../modules/integration-hub.md)
|
||||
|
||||
## Overview
|
||||
|
||||
The Release Management API provides endpoints for managing container components, version tracking, and release bundle creation. All releases are identified by immutable OCI digests, ensuring cryptographic verification throughout the deployment pipeline.
|
||||
|
||||
> **Design Principle:** Release identity is established via digest, not tag. Tags are human-friendly aliases; digests are the source of truth.
|
||||
|
||||
---
|
||||
|
||||
## Component Endpoints
|
||||
|
||||
### Create Component
|
||||
|
||||
**Endpoint:** `POST /api/v1/components`
|
||||
|
||||
Registers a new container component for release management.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "api",
|
||||
"displayName": "API Service",
|
||||
"imageRepository": "myorg/api",
|
||||
"registryIntegrationId": "uuid",
|
||||
"versioningStrategy": "semver",
|
||||
"defaultChannel": "stable"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "api",
|
||||
"displayName": "API Service",
|
||||
"imageRepository": "myorg/api",
|
||||
"registryIntegrationId": "uuid",
|
||||
"versioningStrategy": "semver",
|
||||
"createdAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
### List Components
|
||||
|
||||
**Endpoint:** `GET /api/v1/components`
|
||||
|
||||
**Response:** `200 OK` - Array of components
|
||||
|
||||
### Get Component
|
||||
|
||||
**Endpoint:** `GET /api/v1/components/{id}`
|
||||
|
||||
### Update Component
|
||||
|
||||
**Endpoint:** `PUT /api/v1/components/{id}`
|
||||
|
||||
### Delete Component
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/components/{id}`
|
||||
|
||||
### Sync Versions
|
||||
|
||||
**Endpoint:** `POST /api/v1/components/{id}/sync-versions`
|
||||
|
||||
Triggers a refresh of available versions from the container registry.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"forceRefresh": true
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"synced": 15,
|
||||
"versions": [
|
||||
{
|
||||
"tag": "v2.3.1",
|
||||
"digest": "sha256:abc123...",
|
||||
"semver": "2.3.1",
|
||||
"channel": "stable",
|
||||
"pushedAt": "2026-01-09T10:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### List Component Versions
|
||||
|
||||
**Endpoint:** `GET /api/v1/components/{id}/versions`
|
||||
|
||||
**Query Parameters:**
|
||||
- `channel` (string): Filter by channel (`stable`, `beta`, `rc`)
|
||||
- `limit` (number): Maximum versions to return
|
||||
|
||||
**Response:** `200 OK` - Array of version maps
|
||||
|
||||
---
|
||||
|
||||
## Version Map Endpoints
|
||||
|
||||
### Create Version Map
|
||||
|
||||
**Endpoint:** `POST /api/v1/version-maps`
|
||||
|
||||
Manually assign a semver and channel to a tag/digest.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"componentId": "uuid",
|
||||
"tag": "v2.3.1",
|
||||
"semver": "2.3.1",
|
||||
"channel": "stable"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
|
||||
### List Version Maps
|
||||
|
||||
**Endpoint:** `GET /api/v1/version-maps`
|
||||
|
||||
**Query Parameters:**
|
||||
- `componentId` (UUID): Filter by component
|
||||
- `channel` (string): Filter by channel
|
||||
|
||||
---
|
||||
|
||||
## Release Endpoints
|
||||
|
||||
### Create Release
|
||||
|
||||
**Endpoint:** `POST /api/v1/releases`
|
||||
|
||||
Creates a new release bundle with specified component versions.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "myapp-v2.3.1",
|
||||
"displayName": "My App 2.3.1",
|
||||
"components": [
|
||||
{ "componentId": "uuid", "version": "2.3.1" },
|
||||
{ "componentId": "uuid", "digest": "sha256:def456..." },
|
||||
{ "componentId": "uuid", "channel": "stable" }
|
||||
],
|
||||
"sourceRef": {
|
||||
"scmIntegrationId": "uuid",
|
||||
"repository": "myorg/myapp",
|
||||
"branch": "main",
|
||||
"commitSha": "abc123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "myapp-v2.3.1",
|
||||
"displayName": "My App 2.3.1",
|
||||
"status": "draft",
|
||||
"components": [
|
||||
{
|
||||
"componentId": "uuid",
|
||||
"componentName": "api",
|
||||
"version": "2.3.1",
|
||||
"digest": "sha256:abc123...",
|
||||
"channel": "stable"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-01-10T14:23:45Z",
|
||||
"createdBy": "user-uuid"
|
||||
}
|
||||
```
|
||||
|
||||
### Create Release from Latest
|
||||
|
||||
**Endpoint:** `POST /api/v1/releases/from-latest`
|
||||
|
||||
Convenience endpoint to create a release from the latest versions of all (or specified) components.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "myapp-latest",
|
||||
"channel": "stable",
|
||||
"componentIds": ["uuid1", "uuid2"],
|
||||
"pinFrom": {
|
||||
"environmentId": "uuid"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created` - Release with resolved digests
|
||||
|
||||
### List Releases
|
||||
|
||||
**Endpoint:** `GET /api/v1/releases`
|
||||
|
||||
**Query Parameters:**
|
||||
- `status` (string): Filter by status (`draft`, `ready`, `promoting`, `deployed`, `deprecated`)
|
||||
- `componentId` (UUID): Filter by component inclusion
|
||||
- `page` (number): Page number
|
||||
- `pageSize` (number): Items per page
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "myapp-v2.3.1",
|
||||
"status": "deployed",
|
||||
"componentCount": 3,
|
||||
"createdAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"pageSize": 20,
|
||||
"totalCount": 150,
|
||||
"totalPages": 8
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get Release
|
||||
|
||||
**Endpoint:** `GET /api/v1/releases/{id}`
|
||||
|
||||
**Response:** `200 OK` - Full release with component details
|
||||
|
||||
### Update Release
|
||||
|
||||
**Endpoint:** `PUT /api/v1/releases/{id}`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"displayName": "Updated Display Name",
|
||||
"metadata": { "key": "value" },
|
||||
"status": "ready"
|
||||
}
|
||||
```
|
||||
|
||||
### Delete Release
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/releases/{id}`
|
||||
|
||||
### Get Release State
|
||||
|
||||
**Endpoint:** `GET /api/v1/releases/{id}/state`
|
||||
|
||||
Returns the deployment state of a release across environments.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"environments": [
|
||||
{
|
||||
"environmentId": "uuid",
|
||||
"environmentName": "Development",
|
||||
"status": "deployed",
|
||||
"deployedAt": "2026-01-09T10:00:00Z"
|
||||
},
|
||||
{
|
||||
"environmentId": "uuid",
|
||||
"environmentName": "Staging",
|
||||
"status": "deployed",
|
||||
"deployedAt": "2026-01-10T08:00:00Z"
|
||||
},
|
||||
{
|
||||
"environmentId": "uuid",
|
||||
"environmentName": "Production",
|
||||
"status": "not_deployed"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Deprecate Release
|
||||
|
||||
**Endpoint:** `POST /api/v1/releases/{id}/deprecate`
|
||||
|
||||
Marks a release as deprecated, preventing new promotions.
|
||||
|
||||
**Response:** `200 OK` - Updated release with `status: deprecated`
|
||||
|
||||
### Compare Releases
|
||||
|
||||
**Endpoint:** `GET /api/v1/releases/{id}/compare/{otherId}`
|
||||
|
||||
Compares two releases to identify component differences.
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"added": [
|
||||
{ "componentId": "uuid", "componentName": "worker" }
|
||||
],
|
||||
"removed": [
|
||||
{ "componentId": "uuid", "componentName": "legacy-service" }
|
||||
],
|
||||
"changed": [
|
||||
{
|
||||
"component": "api",
|
||||
"fromVersion": "2.3.0",
|
||||
"toVersion": "2.3.1",
|
||||
"fromDigest": "sha256:old...",
|
||||
"toDigest": "sha256:new..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Status Code | Description |
|
||||
|-------------|-------------|
|
||||
| `400` | Invalid release configuration |
|
||||
| `404` | Release or component not found |
|
||||
| `409` | Release name already exists |
|
||||
| `422` | Cannot resolve component version |
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Promotions API](promotions.md)
|
||||
- [Release Manager Module](../modules/release-manager.md)
|
||||
- [Integration Hub](../modules/integration-hub.md)
|
||||
- [Design Principles](../design/principles.md)
|
||||
374
docs/modules/release-orchestrator/api/websockets.md
Normal file
374
docs/modules/release-orchestrator/api/websockets.md
Normal file
@@ -0,0 +1,374 @@
|
||||
# Real-Time APIs (WebSocket/SSE)
|
||||
|
||||
> WebSocket and Server-Sent Events endpoints for real-time updates.
|
||||
|
||||
**Status:** Planned (not yet implemented)
|
||||
**Source:** [Architecture Advisory Section 6.4](../../../product/advisories/09-Jan-2026%20-%20Stella%20Ops%20Orchestrator%20Architecture.md)
|
||||
**Related Modules:** [Workflow Execution](../workflow/execution.md), [UI Dashboard](../ui/dashboard.md)
|
||||
|
||||
## Overview
|
||||
|
||||
The Release Orchestrator provides real-time streaming endpoints for workflow runs, deployment progress, agent tasks, and dashboard metrics. These endpoints support both WebSocket connections and Server-Sent Events (SSE) for browser compatibility.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
All WebSocket and SSE connections require authentication via JWT token:
|
||||
|
||||
**WebSocket:** Token in query parameter or first message
|
||||
```
|
||||
ws://api/v1/workflow-runs/{id}/stream?token=jwt-token
|
||||
```
|
||||
|
||||
**SSE:** Token in Authorization header
|
||||
```
|
||||
GET /api/v1/dashboard/stream
|
||||
Authorization: Bearer jwt-token
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow Run Stream
|
||||
|
||||
**Endpoint:** `WS /api/v1/workflow-runs/{id}/stream`
|
||||
|
||||
Streams real-time updates for a workflow run including step progress and logs.
|
||||
|
||||
### Message Types (Server to Client)
|
||||
|
||||
**Step Started:**
|
||||
```json
|
||||
{
|
||||
"type": "step_started",
|
||||
"nodeId": "security-check",
|
||||
"stepType": "security-gate",
|
||||
"timestamp": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Step Progress:**
|
||||
```json
|
||||
{
|
||||
"type": "step_progress",
|
||||
"nodeId": "deploy",
|
||||
"progress": 50,
|
||||
"message": "Deploying to target 3/6"
|
||||
}
|
||||
```
|
||||
|
||||
**Step Log:**
|
||||
```json
|
||||
{
|
||||
"type": "step_log",
|
||||
"nodeId": "deploy",
|
||||
"line": "Pulling image sha256:abc123...",
|
||||
"level": "info",
|
||||
"timestamp": "2026-01-10T14:23:50Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Step Completed:**
|
||||
```json
|
||||
{
|
||||
"type": "step_completed",
|
||||
"nodeId": "security-check",
|
||||
"status": "succeeded",
|
||||
"outputs": {
|
||||
"criticalCount": 0,
|
||||
"highCount": 3
|
||||
},
|
||||
"duration": 5.2,
|
||||
"timestamp": "2026-01-10T14:23:50Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Workflow Completed:**
|
||||
```json
|
||||
{
|
||||
"type": "workflow_completed",
|
||||
"status": "succeeded",
|
||||
"duration": 125.5,
|
||||
"outputs": {
|
||||
"deploymentId": "uuid"
|
||||
},
|
||||
"timestamp": "2026-01-10T14:25:50Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment Job Stream
|
||||
|
||||
**Endpoint:** `WS /api/v1/deployment-jobs/{id}/stream`
|
||||
|
||||
Streams real-time updates for deployment job execution.
|
||||
|
||||
### Message Types (Server to Client)
|
||||
|
||||
**Task Started:**
|
||||
```json
|
||||
{
|
||||
"type": "task_started",
|
||||
"taskId": "uuid",
|
||||
"targetId": "uuid",
|
||||
"targetName": "prod-web-01",
|
||||
"taskType": "docker.pull",
|
||||
"timestamp": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Task Progress:**
|
||||
```json
|
||||
{
|
||||
"type": "task_progress",
|
||||
"taskId": "uuid",
|
||||
"progress": 75,
|
||||
"message": "Pulling layer 4/5"
|
||||
}
|
||||
```
|
||||
|
||||
**Task Log:**
|
||||
```json
|
||||
{
|
||||
"type": "task_log",
|
||||
"taskId": "uuid",
|
||||
"line": "Container started successfully",
|
||||
"level": "info"
|
||||
}
|
||||
```
|
||||
|
||||
**Task Completed:**
|
||||
```json
|
||||
{
|
||||
"type": "task_completed",
|
||||
"taskId": "uuid",
|
||||
"targetId": "uuid",
|
||||
"status": "succeeded",
|
||||
"duration": 45.2,
|
||||
"result": {
|
||||
"containerId": "abc123",
|
||||
"digest": "sha256:..."
|
||||
},
|
||||
"timestamp": "2026-01-10T14:24:30Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Job Completed:**
|
||||
```json
|
||||
{
|
||||
"type": "job_completed",
|
||||
"status": "succeeded",
|
||||
"targetsDeployed": 4,
|
||||
"targetsFailed": 0,
|
||||
"duration": 180.5,
|
||||
"timestamp": "2026-01-10T14:26:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Agent Task Stream
|
||||
|
||||
**Endpoint:** `WS /api/v1/agents/{id}/task-stream`
|
||||
|
||||
Bidirectional stream for agent task assignment and progress reporting.
|
||||
|
||||
### Message Types (Server to Agent)
|
||||
|
||||
**Task Assigned:**
|
||||
```json
|
||||
{
|
||||
"type": "task_assigned",
|
||||
"task": {
|
||||
"taskId": "uuid",
|
||||
"taskType": "docker.pull",
|
||||
"payload": {
|
||||
"image": "myapp",
|
||||
"digest": "sha256:abc123..."
|
||||
},
|
||||
"credentials": {
|
||||
"registry.username": "user",
|
||||
"registry.password": "token"
|
||||
},
|
||||
"timeout": 300
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Task Cancelled:**
|
||||
```json
|
||||
{
|
||||
"type": "task_cancelled",
|
||||
"taskId": "uuid",
|
||||
"reason": "Deployment cancelled by user"
|
||||
}
|
||||
```
|
||||
|
||||
### Message Types (Agent to Server)
|
||||
|
||||
**Task Progress:**
|
||||
```json
|
||||
{
|
||||
"type": "task_progress",
|
||||
"taskId": "uuid",
|
||||
"progress": 50,
|
||||
"message": "Pulling image layer 3/5"
|
||||
}
|
||||
```
|
||||
|
||||
**Task Log:**
|
||||
```json
|
||||
{
|
||||
"type": "task_log",
|
||||
"taskId": "uuid",
|
||||
"level": "info",
|
||||
"message": "Image layer downloaded: sha256:def456..."
|
||||
}
|
||||
```
|
||||
|
||||
**Task Completed:**
|
||||
```json
|
||||
{
|
||||
"type": "task_completed",
|
||||
"taskId": "uuid",
|
||||
"success": true,
|
||||
"result": {
|
||||
"imageId": "sha256:abc123..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dashboard Metrics Stream
|
||||
|
||||
**Endpoint:** `WS /api/v1/dashboard/stream`
|
||||
|
||||
Streams real-time dashboard metrics and alerts.
|
||||
|
||||
### Message Types (Server to Client)
|
||||
|
||||
**Metric Update:**
|
||||
```json
|
||||
{
|
||||
"type": "metric_update",
|
||||
"metrics": {
|
||||
"pipelineStatus": [
|
||||
{ "environmentId": "uuid", "name": "Production", "health": "healthy" }
|
||||
],
|
||||
"pendingApprovals": 3,
|
||||
"activeDeployments": 1,
|
||||
"recentReleases": 12,
|
||||
"systemHealth": {
|
||||
"agentsOnline": 8,
|
||||
"agentsTotal": 10,
|
||||
"queueDepth": 5
|
||||
}
|
||||
},
|
||||
"timestamp": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Alert:**
|
||||
```json
|
||||
{
|
||||
"type": "alert",
|
||||
"alert": {
|
||||
"id": "uuid",
|
||||
"severity": "warning",
|
||||
"title": "Deployment Failed",
|
||||
"message": "Deployment to Production failed: health check timeout",
|
||||
"resourceType": "deployment",
|
||||
"resourceId": "uuid",
|
||||
"timestamp": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Promotion Update:**
|
||||
```json
|
||||
{
|
||||
"type": "promotion_update",
|
||||
"promotion": {
|
||||
"id": "uuid",
|
||||
"releaseName": "myapp-v2.3.1",
|
||||
"targetEnvironment": "Production",
|
||||
"status": "awaiting_approval",
|
||||
"requestedBy": "John Doe"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Connection Management
|
||||
|
||||
### Reconnection
|
||||
|
||||
Clients should implement exponential backoff reconnection:
|
||||
|
||||
```javascript
|
||||
const connect = (retryCount = 0) => {
|
||||
const ws = new WebSocket(url);
|
||||
|
||||
ws.onclose = () => {
|
||||
const delay = Math.min(1000 * Math.pow(2, retryCount), 30000);
|
||||
setTimeout(() => connect(retryCount + 1), delay);
|
||||
};
|
||||
|
||||
ws.onopen = () => {
|
||||
retryCount = 0;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Heartbeat
|
||||
|
||||
WebSocket connections receive periodic heartbeat messages:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "heartbeat",
|
||||
"timestamp": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
Clients should respond with:
|
||||
```json
|
||||
{
|
||||
"type": "pong"
|
||||
}
|
||||
```
|
||||
|
||||
Connections without pong response within 30 seconds are terminated.
|
||||
|
||||
---
|
||||
|
||||
## Error Messages
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "error",
|
||||
"code": "unauthorized",
|
||||
"message": "Token expired",
|
||||
"timestamp": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
| Error Code | Description |
|
||||
|------------|-------------|
|
||||
| `unauthorized` | Invalid or expired token |
|
||||
| `forbidden` | No access to resource |
|
||||
| `not_found` | Resource not found |
|
||||
| `rate_limited` | Too many connections |
|
||||
| `internal_error` | Server error |
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [Workflows API](workflows.md)
|
||||
- [Agents API](agents.md)
|
||||
- [UI Dashboard](../ui/dashboard.md)
|
||||
- [Workflow Execution](../workflow/execution.md)
|
||||
354
docs/modules/release-orchestrator/api/workflows.md
Normal file
354
docs/modules/release-orchestrator/api/workflows.md
Normal file
@@ -0,0 +1,354 @@
|
||||
# Workflow APIs
|
||||
|
||||
> API endpoints for managing workflow templates, step registry, and workflow runs.
|
||||
|
||||
**Status:** Planned (not yet implemented)
|
||||
**Source:** [Architecture Advisory Section 6.3.4](../../../product/advisories/09-Jan-2026%20-%20Stella%20Ops%20Orchestrator%20Architecture.md)
|
||||
**Related Modules:** [Workflow Engine Module](../modules/workflow-engine.md), [Workflow Templates](../workflow/templates.md)
|
||||
|
||||
## Overview
|
||||
|
||||
The Workflow API provides endpoints for managing workflow templates (DAG definitions), discovering available step types, and executing workflow runs. Workflows are directed acyclic graphs (DAGs) of steps that orchestrate promotions, deployments, and other automation tasks.
|
||||
|
||||
---
|
||||
|
||||
## Workflow Template Endpoints
|
||||
|
||||
### Create Workflow Template
|
||||
|
||||
**Endpoint:** `POST /api/v1/workflow-templates`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"name": "standard-promotion",
|
||||
"displayName": "Standard Promotion Workflow",
|
||||
"description": "Default workflow for promoting releases",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "security-check",
|
||||
"type": "security-gate",
|
||||
"name": "Security Check",
|
||||
"config": {
|
||||
"maxCritical": 0,
|
||||
"maxHigh": 5
|
||||
},
|
||||
"position": { "x": 100, "y": 100 }
|
||||
},
|
||||
{
|
||||
"id": "approval",
|
||||
"type": "approval",
|
||||
"name": "Manager Approval",
|
||||
"config": {
|
||||
"approvers": ["manager-group"],
|
||||
"minApprovals": 1
|
||||
},
|
||||
"position": { "x": 300, "y": 100 }
|
||||
},
|
||||
{
|
||||
"id": "deploy",
|
||||
"type": "deploy",
|
||||
"name": "Deploy to Target",
|
||||
"config": {
|
||||
"strategy": "rolling",
|
||||
"batchSize": "25%"
|
||||
},
|
||||
"position": { "x": 500, "y": 100 }
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{ "from": "security-check", "to": "approval" },
|
||||
{ "from": "approval", "to": "deploy" }
|
||||
],
|
||||
"inputs": [
|
||||
{ "name": "releaseId", "type": "uuid", "required": true },
|
||||
{ "name": "environmentId", "type": "uuid", "required": true }
|
||||
],
|
||||
"outputs": [
|
||||
{ "name": "deploymentId", "type": "uuid" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"name": "standard-promotion",
|
||||
"displayName": "Standard Promotion Workflow",
|
||||
"version": 1,
|
||||
"nodeCount": 3,
|
||||
"isActive": true,
|
||||
"createdAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
### List Workflow Templates
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-templates`
|
||||
|
||||
**Query Parameters:**
|
||||
- `includeBuiltin` (boolean): Include system-provided templates
|
||||
- `tags` (string): Filter by tags
|
||||
|
||||
**Response:** `200 OK` - Array of workflow templates
|
||||
|
||||
### Get Workflow Template
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-templates/{id}`
|
||||
|
||||
**Response:** `200 OK` - Full template with nodes and edges
|
||||
|
||||
### Update Workflow Template
|
||||
|
||||
**Endpoint:** `PUT /api/v1/workflow-templates/{id}`
|
||||
|
||||
Creates a new version of the template.
|
||||
|
||||
**Request:** Partial or full template definition
|
||||
|
||||
**Response:** `200 OK` - New version of template
|
||||
|
||||
### Delete Workflow Template
|
||||
|
||||
**Endpoint:** `DELETE /api/v1/workflow-templates/{id}`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{ "deleted": true }
|
||||
```
|
||||
|
||||
### Validate Workflow Template
|
||||
|
||||
**Endpoint:** `POST /api/v1/workflow-templates/{id}/validate`
|
||||
|
||||
Validates a template with sample inputs.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"inputs": {
|
||||
"releaseId": "sample-uuid",
|
||||
"environmentId": "sample-uuid"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"valid": true,
|
||||
"errors": []
|
||||
}
|
||||
```
|
||||
|
||||
Or on validation failure:
|
||||
```json
|
||||
{
|
||||
"valid": false,
|
||||
"errors": [
|
||||
{ "nodeId": "deploy", "field": "config.strategy", "message": "Invalid strategy: unknown" },
|
||||
{ "type": "dag", "message": "Cycle detected: node-a -> node-b -> node-a" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step Registry Endpoints
|
||||
|
||||
### List Step Types
|
||||
|
||||
**Endpoint:** `GET /api/v1/step-types`
|
||||
|
||||
Lists all available step types from core and plugins.
|
||||
|
||||
**Query Parameters:**
|
||||
- `category` (string): Filter by category (`deployment`, `gate`, `notification`, `utility`)
|
||||
- `provider` (string): Filter by provider (`builtin`, `plugin-id`)
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "script",
|
||||
"displayName": "Script",
|
||||
"description": "Execute shell script on target",
|
||||
"category": "utility",
|
||||
"provider": "builtin",
|
||||
"configSchema": { ... }
|
||||
},
|
||||
{
|
||||
"type": "security-gate",
|
||||
"displayName": "Security Gate",
|
||||
"description": "Check vulnerability thresholds",
|
||||
"category": "gate",
|
||||
"provider": "builtin",
|
||||
"configSchema": { ... }
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Get Step Type
|
||||
|
||||
**Endpoint:** `GET /api/v1/step-types/{type}`
|
||||
|
||||
**Response:** `200 OK` - Full step type with configuration schema
|
||||
|
||||
---
|
||||
|
||||
## Workflow Run Endpoints
|
||||
|
||||
### Start Workflow Run
|
||||
|
||||
**Endpoint:** `POST /api/v1/workflow-runs`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"templateId": "uuid",
|
||||
"context": {
|
||||
"releaseId": "uuid",
|
||||
"environmentId": "uuid",
|
||||
"variables": {
|
||||
"deploymentTimeout": 600
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"templateId": "uuid",
|
||||
"templateVersion": 1,
|
||||
"status": "running",
|
||||
"startedAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
```
|
||||
|
||||
### List Workflow Runs
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-runs`
|
||||
|
||||
**Query Parameters:**
|
||||
- `status` (string): Filter by status (`pending`, `running`, `succeeded`, `failed`, `cancelled`)
|
||||
- `templateId` (UUID): Filter by template
|
||||
- `page` (number): Page number
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"templateName": "standard-promotion",
|
||||
"status": "running",
|
||||
"progress": 66,
|
||||
"startedAt": "2026-01-10T14:23:45Z"
|
||||
}
|
||||
],
|
||||
"meta": { "page": 1, "totalCount": 50 }
|
||||
}
|
||||
```
|
||||
|
||||
### Get Workflow Run
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-runs/{id}`
|
||||
|
||||
**Response:** `200 OK` - Full run with step statuses
|
||||
|
||||
### Pause Workflow Run
|
||||
|
||||
**Endpoint:** `POST /api/v1/workflow-runs/{id}/pause`
|
||||
|
||||
Pauses a running workflow at the next step boundary.
|
||||
|
||||
**Response:** `200 OK` - Updated workflow run
|
||||
|
||||
### Resume Workflow Run
|
||||
|
||||
**Endpoint:** `POST /api/v1/workflow-runs/{id}/resume`
|
||||
|
||||
Resumes a paused workflow.
|
||||
|
||||
**Response:** `200 OK` - Updated workflow run
|
||||
|
||||
### Cancel Workflow Run
|
||||
|
||||
**Endpoint:** `POST /api/v1/workflow-runs/{id}/cancel`
|
||||
|
||||
Cancels a running or paused workflow.
|
||||
|
||||
**Response:** `200 OK` - Updated workflow run
|
||||
|
||||
### List Step Runs
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-runs/{id}/steps`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
[
|
||||
{
|
||||
"nodeId": "security-check",
|
||||
"stepType": "security-gate",
|
||||
"status": "succeeded",
|
||||
"startedAt": "2026-01-10T14:23:45Z",
|
||||
"completedAt": "2026-01-10T14:23:50Z"
|
||||
},
|
||||
{
|
||||
"nodeId": "approval",
|
||||
"stepType": "approval",
|
||||
"status": "running",
|
||||
"startedAt": "2026-01-10T14:23:50Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Get Step Run
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-runs/{id}/steps/{nodeId}`
|
||||
|
||||
**Response:** `200 OK` - Step run with logs
|
||||
|
||||
### Get Step Logs
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-runs/{id}/steps/{nodeId}/logs`
|
||||
|
||||
**Query Parameters:**
|
||||
- `follow` (boolean): Stream logs in real-time via SSE
|
||||
|
||||
**Response:** `200 OK` - Log content or SSE stream
|
||||
|
||||
### List Step Artifacts
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-runs/{id}/steps/{nodeId}/artifacts`
|
||||
|
||||
**Response:** `200 OK` - Array of artifacts
|
||||
|
||||
### Download Artifact
|
||||
|
||||
**Endpoint:** `GET /api/v1/workflow-runs/{id}/steps/{nodeId}/artifacts/{artifactId}`
|
||||
|
||||
**Response:** Binary download
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Status Code | Description |
|
||||
|-------------|-------------|
|
||||
| `400` | Invalid workflow template |
|
||||
| `404` | Template or run not found |
|
||||
| `409` | Workflow already running |
|
||||
| `422` | DAG validation failed |
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [WebSocket APIs](websockets.md) - Real-time workflow updates
|
||||
- [Workflow Engine Module](../modules/workflow-engine.md)
|
||||
- [Workflow Templates](../workflow/templates.md)
|
||||
- [Workflow Execution](../workflow/execution.md)
|
||||
Reference in New Issue
Block a user