release orchestrator pivot, architecture and planning
This commit is contained in:
296
docs/modules/release-orchestrator/appendices/errors.md
Normal file
296
docs/modules/release-orchestrator/appendices/errors.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# API Error Codes
|
||||
|
||||
## Overview
|
||||
|
||||
All API errors follow a consistent format with error codes for programmatic handling.
|
||||
|
||||
## Error Response Format
|
||||
|
||||
```typescript
|
||||
interface ApiErrorResponse {
|
||||
success: false;
|
||||
error: {
|
||||
code: string; // Machine-readable error code
|
||||
message: string; // Human-readable message
|
||||
details?: object; // Additional context
|
||||
validationErrors?: ValidationError[];
|
||||
};
|
||||
meta: {
|
||||
requestId: string;
|
||||
timestamp: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface ValidationError {
|
||||
field: string;
|
||||
message: string;
|
||||
code: string;
|
||||
}
|
||||
```
|
||||
|
||||
## Error Code Categories
|
||||
|
||||
| Prefix | Category | HTTP Status Range |
|
||||
|--------|----------|-------------------|
|
||||
| `AUTH_` | Authentication | 401 |
|
||||
| `PERM_` | Authorization/Permission | 403 |
|
||||
| `VAL_` | Validation | 400 |
|
||||
| `RES_` | Resource | 404, 409 |
|
||||
| `ENV_` | Environment | 422 |
|
||||
| `REL_` | Release | 422 |
|
||||
| `PROM_` | Promotion | 422 |
|
||||
| `DEPLOY_` | Deployment | 422 |
|
||||
| `GATE_` | Gate | 422 |
|
||||
| `AGT_` | Agent | 422 |
|
||||
| `INT_` | Integration | 422 |
|
||||
| `WF_` | Workflow | 422 |
|
||||
| `SYS_` | System | 500 |
|
||||
|
||||
## Authentication Errors (401)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `AUTH_TOKEN_MISSING` | Authentication token required | No token provided |
|
||||
| `AUTH_TOKEN_INVALID` | Invalid authentication token | Token cannot be parsed |
|
||||
| `AUTH_TOKEN_EXPIRED` | Authentication token expired | Token has expired |
|
||||
| `AUTH_TOKEN_REVOKED` | Authentication token revoked | Token has been revoked |
|
||||
| `AUTH_AGENT_CERT_INVALID` | Invalid agent certificate | Agent mTLS cert invalid |
|
||||
| `AUTH_AGENT_CERT_EXPIRED` | Agent certificate expired | Agent cert has expired |
|
||||
| `AUTH_API_KEY_INVALID` | Invalid API key | API key not recognized |
|
||||
|
||||
## Permission Errors (403)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `PERM_DENIED` | Permission denied | Generic permission denial |
|
||||
| `PERM_RESOURCE_DENIED` | Access to resource denied | Cannot access specific resource |
|
||||
| `PERM_ACTION_DENIED` | Action not permitted | Cannot perform specific action |
|
||||
| `PERM_SCOPE_DENIED` | Outside permitted scope | Action outside user's scope |
|
||||
| `PERM_SOD_VIOLATION` | Separation of duties violation | SoD prevents action |
|
||||
| `PERM_SELF_APPROVAL` | Cannot approve own request | Self-approval not allowed |
|
||||
| `PERM_TENANT_MISMATCH` | Tenant mismatch | Resource belongs to different tenant |
|
||||
|
||||
## Validation Errors (400)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `VAL_REQUIRED_FIELD` | Required field missing | Field is required |
|
||||
| `VAL_INVALID_FORMAT` | Invalid field format | Field format incorrect |
|
||||
| `VAL_INVALID_VALUE` | Invalid field value | Value not in allowed set |
|
||||
| `VAL_TOO_LONG` | Field value too long | Exceeds max length |
|
||||
| `VAL_TOO_SHORT` | Field value too short | Below min length |
|
||||
| `VAL_INVALID_UUID` | Invalid UUID format | Not a valid UUID |
|
||||
| `VAL_INVALID_DIGEST` | Invalid digest format | Not a valid OCI digest |
|
||||
| `VAL_INVALID_SEMVER` | Invalid semver format | Not valid semantic version |
|
||||
| `VAL_INVALID_JSON` | Invalid JSON | Request body not valid JSON |
|
||||
| `VAL_SCHEMA_MISMATCH` | Schema validation failed | Doesn't match schema |
|
||||
|
||||
## Resource Errors (404, 409)
|
||||
|
||||
| Code | Message | HTTP | Description |
|
||||
|------|---------|------|-------------|
|
||||
| `RES_NOT_FOUND` | Resource not found | 404 | Generic not found |
|
||||
| `RES_ENVIRONMENT_NOT_FOUND` | Environment not found | 404 | Environment doesn't exist |
|
||||
| `RES_RELEASE_NOT_FOUND` | Release not found | 404 | Release doesn't exist |
|
||||
| `RES_PROMOTION_NOT_FOUND` | Promotion not found | 404 | Promotion doesn't exist |
|
||||
| `RES_TARGET_NOT_FOUND` | Target not found | 404 | Target doesn't exist |
|
||||
| `RES_AGENT_NOT_FOUND` | Agent not found | 404 | Agent doesn't exist |
|
||||
| `RES_CONFLICT` | Resource conflict | 409 | Resource state conflict |
|
||||
| `RES_ALREADY_EXISTS` | Resource already exists | 409 | Duplicate resource |
|
||||
| `RES_VERSION_CONFLICT` | Version conflict | 409 | Optimistic lock failure |
|
||||
|
||||
## Environment Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `ENV_FROZEN` | Environment is frozen | Deployment blocked by freeze window |
|
||||
| `ENV_FREEZE_ACTIVE` | Active freeze window | Cannot modify during freeze |
|
||||
| `ENV_INVALID_ORDER` | Invalid environment order | Order index conflict |
|
||||
| `ENV_CIRCULAR_PROMOTION` | Circular promotion path | Auto-promote creates cycle |
|
||||
| `ENV_QUOTA_EXCEEDED` | Environment quota exceeded | Max environments reached |
|
||||
|
||||
## Release Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `REL_ALREADY_FINALIZED` | Release already finalized | Cannot modify finalized release |
|
||||
| `REL_NOT_READY` | Release not ready | Release not in ready state |
|
||||
| `REL_DIGEST_MISMATCH` | Digest mismatch | Resolved digest differs |
|
||||
| `REL_TAG_NOT_FOUND` | Tag not found in registry | Cannot resolve tag |
|
||||
| `REL_COMPONENT_MISSING` | Component not found | Referenced component missing |
|
||||
| `REL_INVALID_STATUS_TRANSITION` | Invalid status transition | Status change not allowed |
|
||||
| `REL_DEPRECATED` | Release deprecated | Cannot promote deprecated release |
|
||||
|
||||
## Promotion Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `PROM_ALREADY_EXISTS` | Promotion already pending | Duplicate promotion request |
|
||||
| `PROM_NOT_PENDING` | Promotion not pending | Cannot approve/reject |
|
||||
| `PROM_ALREADY_APPROVED` | Promotion already approved | Already approved |
|
||||
| `PROM_ALREADY_REJECTED` | Promotion already rejected | Already rejected |
|
||||
| `PROM_ALREADY_CANCELLED` | Promotion already cancelled | Already cancelled |
|
||||
| `PROM_DEPLOYING` | Promotion is deploying | Cannot cancel during deploy |
|
||||
| `PROM_INVALID_STATE` | Invalid promotion state | State doesn't allow action |
|
||||
| `PROM_APPROVER_REQUIRED` | Additional approvers required | Insufficient approvals |
|
||||
| `PROM_SKIP_ENVIRONMENT` | Cannot skip environments | Must promote sequentially |
|
||||
|
||||
## Deployment Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `DEPLOY_IN_PROGRESS` | Deployment in progress | Another deployment running |
|
||||
| `DEPLOY_NO_TARGETS` | No targets available | No targets in environment |
|
||||
| `DEPLOY_TARGET_UNHEALTHY` | Target unhealthy | Target failed health check |
|
||||
| `DEPLOY_AGENT_UNAVAILABLE` | Agent unavailable | Required agent offline |
|
||||
| `DEPLOY_ARTIFACT_MISSING` | Deployment artifact missing | Required artifact not found |
|
||||
| `DEPLOY_TIMEOUT` | Deployment timeout | Exceeded timeout |
|
||||
| `DEPLOY_PULL_FAILED` | Image pull failed | Cannot pull container image |
|
||||
| `DEPLOY_DIGEST_VERIFICATION_FAILED` | Digest verification failed | Image tampered |
|
||||
| `DEPLOY_HEALTH_CHECK_FAILED` | Health check failed | Post-deploy health failed |
|
||||
| `DEPLOY_ROLLBACK_IN_PROGRESS` | Rollback in progress | Already rolling back |
|
||||
| `DEPLOY_NOTHING_TO_ROLLBACK` | Nothing to rollback | No previous deployment |
|
||||
|
||||
## Gate Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `GATE_EVALUATION_FAILED` | Gate evaluation failed | Gate cannot be evaluated |
|
||||
| `GATE_SECURITY_BLOCKED` | Blocked by security gate | Security policy violation |
|
||||
| `GATE_POLICY_BLOCKED` | Blocked by policy gate | Custom policy violation |
|
||||
| `GATE_APPROVAL_BLOCKED` | Blocked pending approval | Awaiting approval |
|
||||
| `GATE_TIMEOUT` | Gate evaluation timeout | Evaluation exceeded timeout |
|
||||
|
||||
## Agent Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `AGT_REGISTRATION_FAILED` | Agent registration failed | Cannot register agent |
|
||||
| `AGT_TOKEN_INVALID` | Invalid registration token | Bad or expired token |
|
||||
| `AGT_TOKEN_USED` | Registration token already used | One-time token reused |
|
||||
| `AGT_CERTIFICATE_FAILED` | Certificate issuance failed | Cannot issue certificate |
|
||||
| `AGT_OFFLINE` | Agent offline | Agent not responding |
|
||||
| `AGT_CAPABILITY_MISSING` | Missing capability | Agent lacks required capability |
|
||||
| `AGT_TASK_FAILED` | Task execution failed | Agent task failed |
|
||||
| `AGT_HEARTBEAT_TIMEOUT` | Heartbeat timeout | Agent heartbeat overdue |
|
||||
|
||||
## Integration Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `INT_CONNECTION_FAILED` | Connection failed | Cannot connect to integration |
|
||||
| `INT_AUTH_FAILED` | Authentication failed | Integration auth failed |
|
||||
| `INT_RATE_LIMITED` | Rate limited | Integration rate limit hit |
|
||||
| `INT_TIMEOUT` | Integration timeout | Request timeout |
|
||||
| `INT_INVALID_RESPONSE` | Invalid response | Unexpected response format |
|
||||
| `INT_RESOURCE_NOT_FOUND` | External resource not found | Registry/SCM resource missing |
|
||||
|
||||
## Workflow Errors (422)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `WF_TEMPLATE_NOT_FOUND` | Workflow template not found | Template doesn't exist |
|
||||
| `WF_TEMPLATE_INVALID` | Invalid workflow template | Template validation failed |
|
||||
| `WF_CYCLE_DETECTED` | Cycle detected in workflow | DAG contains cycle |
|
||||
| `WF_STEP_FAILED` | Workflow step failed | Step execution failed |
|
||||
| `WF_ALREADY_RUNNING` | Workflow already running | Duplicate workflow run |
|
||||
| `WF_INVALID_STATE` | Invalid workflow state | Cannot perform action |
|
||||
| `WF_EXPRESSION_ERROR` | Expression evaluation error | Bad expression |
|
||||
|
||||
## System Errors (500)
|
||||
|
||||
| Code | Message | Description |
|
||||
|------|---------|-------------|
|
||||
| `SYS_INTERNAL_ERROR` | Internal server error | Unexpected error |
|
||||
| `SYS_DATABASE_ERROR` | Database error | Database operation failed |
|
||||
| `SYS_STORAGE_ERROR` | Storage error | Storage operation failed |
|
||||
| `SYS_VAULT_ERROR` | Vault error | Secret retrieval failed |
|
||||
| `SYS_QUEUE_ERROR` | Queue error | Message queue failed |
|
||||
| `SYS_SERVICE_UNAVAILABLE` | Service unavailable | Dependency unavailable |
|
||||
| `SYS_OVERLOADED` | System overloaded | Capacity exceeded |
|
||||
|
||||
## Example Error Responses
|
||||
|
||||
### Validation Error
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": {
|
||||
"code": "VAL_REQUIRED_FIELD",
|
||||
"message": "Validation failed",
|
||||
"validationErrors": [
|
||||
{
|
||||
"field": "releaseId",
|
||||
"message": "Release ID is required",
|
||||
"code": "VAL_REQUIRED_FIELD"
|
||||
},
|
||||
{
|
||||
"field": "targetEnvironmentId",
|
||||
"message": "Invalid UUID format",
|
||||
"code": "VAL_INVALID_UUID"
|
||||
}
|
||||
]
|
||||
},
|
||||
"meta": {
|
||||
"requestId": "req-12345",
|
||||
"timestamp": "2026-01-10T14:30:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Permission Error
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": {
|
||||
"code": "PERM_SOD_VIOLATION",
|
||||
"message": "Separation of duties violation: requester cannot approve their own promotion",
|
||||
"details": {
|
||||
"promotionId": "promo-uuid",
|
||||
"requesterId": "user-uuid",
|
||||
"approverId": "user-uuid",
|
||||
"environmentId": "env-uuid",
|
||||
"requiresSoD": true
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"requestId": "req-12345",
|
||||
"timestamp": "2026-01-10T14:30:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Gate Block Error
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": {
|
||||
"code": "GATE_SECURITY_BLOCKED",
|
||||
"message": "Promotion blocked by security gate",
|
||||
"details": {
|
||||
"gateName": "security-gate",
|
||||
"releaseId": "rel-uuid",
|
||||
"targetEnvironment": "production",
|
||||
"violations": [
|
||||
{
|
||||
"type": "critical_vulnerability",
|
||||
"count": 3,
|
||||
"threshold": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"requestId": "req-12345",
|
||||
"timestamp": "2026-01-10T14:30:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [API Overview](../api/overview.md)
|
||||
- [Security Overview](../security/overview.md)
|
||||
549
docs/modules/release-orchestrator/appendices/evidence-schema.md
Normal file
549
docs/modules/release-orchestrator/appendices/evidence-schema.md
Normal file
@@ -0,0 +1,549 @@
|
||||
# Evidence Packet Schema
|
||||
|
||||
## Overview
|
||||
|
||||
Evidence packets are cryptographically signed, immutable records of deployment decisions and outcomes. They provide audit-grade proof of who did what, when, and why.
|
||||
|
||||
## Evidence Packet Types
|
||||
|
||||
| Type | Description | Generated When |
|
||||
|------|-------------|----------------|
|
||||
| `release_decision` | Promotion decision evidence | Promotion approved/rejected |
|
||||
| `deployment` | Deployment execution evidence | Deployment completes |
|
||||
| `rollback` | Rollback evidence | Rollback completes |
|
||||
| `ab_promotion` | A/B release promotion evidence | A/B promotion completes |
|
||||
|
||||
## Schema Definition
|
||||
|
||||
### Evidence Packet Structure
|
||||
|
||||
```typescript
|
||||
interface EvidencePacket {
|
||||
// Identification
|
||||
id: UUID;
|
||||
version: "1.0";
|
||||
type: EvidencePacketType;
|
||||
|
||||
// Metadata
|
||||
generatedAt: DateTime;
|
||||
generatorVersion: string;
|
||||
tenantId: UUID;
|
||||
|
||||
// Content
|
||||
content: EvidenceContent;
|
||||
|
||||
// Integrity
|
||||
contentHash: string; // SHA-256 of canonical JSON content
|
||||
signature: string; // Base64-encoded signature
|
||||
signatureAlgorithm: string; // "RS256", "ES256"
|
||||
signerKeyRef: string; // Reference to signing key
|
||||
}
|
||||
|
||||
type EvidencePacketType =
|
||||
| "release_decision"
|
||||
| "deployment"
|
||||
| "rollback"
|
||||
| "ab_promotion";
|
||||
```
|
||||
|
||||
### Evidence Content
|
||||
|
||||
```typescript
|
||||
interface EvidenceContent {
|
||||
// What was released
|
||||
release: ReleaseEvidence;
|
||||
|
||||
// Where it was released
|
||||
environment: EnvironmentEvidence;
|
||||
|
||||
// Who requested and approved
|
||||
actors: ActorEvidence;
|
||||
|
||||
// Why it was allowed
|
||||
decision: DecisionEvidence;
|
||||
|
||||
// How it was executed (deployment only)
|
||||
execution?: ExecutionEvidence;
|
||||
|
||||
// Previous state (for rollback)
|
||||
previous?: PreviousStateEvidence;
|
||||
}
|
||||
```
|
||||
|
||||
### Release Evidence
|
||||
|
||||
```typescript
|
||||
interface ReleaseEvidence {
|
||||
id: UUID;
|
||||
name: string;
|
||||
displayName: string;
|
||||
createdAt: DateTime;
|
||||
createdBy: ActorRef;
|
||||
|
||||
components: Array<{
|
||||
id: UUID;
|
||||
name: string;
|
||||
digest: string;
|
||||
semver: string;
|
||||
tag: string;
|
||||
role: "primary" | "sidecar" | "init" | "migration";
|
||||
}>;
|
||||
|
||||
sourceRef?: {
|
||||
scmIntegrationId?: UUID;
|
||||
repository?: string;
|
||||
commitSha?: string;
|
||||
branch?: string;
|
||||
ciIntegrationId?: UUID;
|
||||
buildId?: string;
|
||||
pipelineUrl?: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Environment Evidence
|
||||
|
||||
```typescript
|
||||
interface EnvironmentEvidence {
|
||||
id: UUID;
|
||||
name: string;
|
||||
displayName: string;
|
||||
orderIndex: number;
|
||||
|
||||
targets: Array<{
|
||||
id: UUID;
|
||||
name: string;
|
||||
type: string;
|
||||
healthStatus: string;
|
||||
}>;
|
||||
|
||||
configuration: {
|
||||
requiredApprovals: number;
|
||||
requireSeparationOfDuties: boolean;
|
||||
promotionPolicy?: string;
|
||||
deploymentTimeout: number;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Actor Evidence
|
||||
|
||||
```typescript
|
||||
interface ActorEvidence {
|
||||
requester: ActorRef;
|
||||
requestReason: string;
|
||||
requestedAt: DateTime;
|
||||
|
||||
approvers: Array<{
|
||||
actor: ActorRef;
|
||||
action: "approved" | "rejected";
|
||||
comment?: string;
|
||||
timestamp: DateTime;
|
||||
roles: string[];
|
||||
}>;
|
||||
|
||||
deployer?: {
|
||||
agent: AgentRef;
|
||||
triggeredBy: ActorRef;
|
||||
startedAt: DateTime;
|
||||
};
|
||||
}
|
||||
|
||||
interface ActorRef {
|
||||
id: UUID;
|
||||
type: "user" | "system" | "agent";
|
||||
name: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
interface AgentRef {
|
||||
id: UUID;
|
||||
name: string;
|
||||
version: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Decision Evidence
|
||||
|
||||
```typescript
|
||||
interface DecisionEvidence {
|
||||
promotionId: UUID;
|
||||
decision: "allow" | "block";
|
||||
decidedAt: DateTime;
|
||||
|
||||
gateResults: Array<{
|
||||
gateName: string;
|
||||
gateType: string;
|
||||
passed: boolean;
|
||||
blocking: boolean;
|
||||
message: string;
|
||||
evaluatedAt: DateTime;
|
||||
details: object;
|
||||
}>;
|
||||
|
||||
freezeWindowCheck: {
|
||||
checked: boolean;
|
||||
windowActive: boolean;
|
||||
windowId?: UUID;
|
||||
exemption?: {
|
||||
grantedBy: UUID;
|
||||
reason: string;
|
||||
};
|
||||
};
|
||||
|
||||
separationOfDuties: {
|
||||
required: boolean;
|
||||
satisfied: boolean;
|
||||
requesterIds: UUID[];
|
||||
approverIds: UUID[];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Execution Evidence
|
||||
|
||||
```typescript
|
||||
interface ExecutionEvidence {
|
||||
deploymentJobId: UUID;
|
||||
strategy: string;
|
||||
startedAt: DateTime;
|
||||
completedAt: DateTime;
|
||||
status: "succeeded" | "failed" | "rolled_back";
|
||||
|
||||
tasks: Array<{
|
||||
targetId: UUID;
|
||||
targetName: string;
|
||||
agentId: UUID;
|
||||
status: string;
|
||||
startedAt: DateTime;
|
||||
completedAt: DateTime;
|
||||
digest: string;
|
||||
stickerWritten: boolean;
|
||||
error?: string;
|
||||
}>;
|
||||
|
||||
artifacts: Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
sha256: string;
|
||||
storageRef: string;
|
||||
}>;
|
||||
|
||||
metrics: {
|
||||
totalTasks: number;
|
||||
succeededTasks: number;
|
||||
failedTasks: number;
|
||||
totalDurationSeconds: number;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Previous State Evidence
|
||||
|
||||
```typescript
|
||||
interface PreviousStateEvidence {
|
||||
releaseId: UUID;
|
||||
releaseName: string;
|
||||
deployedAt: DateTime;
|
||||
deployedBy: ActorRef;
|
||||
components: Array<{
|
||||
name: string;
|
||||
digest: string;
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
## Example Evidence Packet
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "evid-12345-uuid",
|
||||
"version": "1.0",
|
||||
"type": "deployment",
|
||||
"generatedAt": "2026-01-10T14:35:00Z",
|
||||
"generatorVersion": "stella-evidence-generator@1.5.0",
|
||||
"tenantId": "tenant-uuid",
|
||||
|
||||
"content": {
|
||||
"release": {
|
||||
"id": "rel-uuid",
|
||||
"name": "myapp-v2.3.1",
|
||||
"displayName": "MyApp v2.3.1",
|
||||
"createdAt": "2026-01-10T10:00:00Z",
|
||||
"createdBy": {
|
||||
"id": "user-uuid",
|
||||
"type": "user",
|
||||
"name": "John Doe",
|
||||
"email": "john@example.com"
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"id": "comp-api-uuid",
|
||||
"name": "api",
|
||||
"digest": "sha256:abc123def456...",
|
||||
"semver": "2.3.1",
|
||||
"tag": "v2.3.1",
|
||||
"role": "primary"
|
||||
},
|
||||
{
|
||||
"id": "comp-worker-uuid",
|
||||
"name": "worker",
|
||||
"digest": "sha256:789xyz...",
|
||||
"semver": "2.3.1",
|
||||
"tag": "v2.3.1",
|
||||
"role": "primary"
|
||||
}
|
||||
],
|
||||
"sourceRef": {
|
||||
"repository": "github.com/myorg/myapp",
|
||||
"commitSha": "abc123",
|
||||
"branch": "main",
|
||||
"buildId": "build-456"
|
||||
}
|
||||
},
|
||||
|
||||
"environment": {
|
||||
"id": "env-prod-uuid",
|
||||
"name": "production",
|
||||
"displayName": "Production",
|
||||
"orderIndex": 2,
|
||||
"targets": [
|
||||
{
|
||||
"id": "target-1-uuid",
|
||||
"name": "prod-web-01",
|
||||
"type": "compose_host",
|
||||
"healthStatus": "healthy"
|
||||
},
|
||||
{
|
||||
"id": "target-2-uuid",
|
||||
"name": "prod-web-02",
|
||||
"type": "compose_host",
|
||||
"healthStatus": "healthy"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"requiredApprovals": 2,
|
||||
"requireSeparationOfDuties": true,
|
||||
"deploymentTimeout": 600
|
||||
}
|
||||
},
|
||||
|
||||
"actors": {
|
||||
"requester": {
|
||||
"id": "user-john-uuid",
|
||||
"type": "user",
|
||||
"name": "John Doe",
|
||||
"email": "john@example.com"
|
||||
},
|
||||
"requestReason": "Release v2.3.1 with performance improvements",
|
||||
"requestedAt": "2026-01-10T12:00:00Z",
|
||||
"approvers": [
|
||||
{
|
||||
"actor": {
|
||||
"id": "user-jane-uuid",
|
||||
"type": "user",
|
||||
"name": "Jane Smith",
|
||||
"email": "jane@example.com"
|
||||
},
|
||||
"action": "approved",
|
||||
"comment": "LGTM, tests passed",
|
||||
"timestamp": "2026-01-10T13:00:00Z",
|
||||
"roles": ["release_manager"]
|
||||
},
|
||||
{
|
||||
"actor": {
|
||||
"id": "user-bob-uuid",
|
||||
"type": "user",
|
||||
"name": "Bob Johnson",
|
||||
"email": "bob@example.com"
|
||||
},
|
||||
"action": "approved",
|
||||
"comment": "Approved for production",
|
||||
"timestamp": "2026-01-10T13:30:00Z",
|
||||
"roles": ["approver"]
|
||||
}
|
||||
],
|
||||
"deployer": {
|
||||
"agent": {
|
||||
"id": "agent-prod-uuid",
|
||||
"name": "prod-agent-01",
|
||||
"version": "1.5.0"
|
||||
},
|
||||
"triggeredBy": {
|
||||
"id": "system",
|
||||
"type": "system",
|
||||
"name": "Stella Orchestrator"
|
||||
},
|
||||
"startedAt": "2026-01-10T14:00:00Z"
|
||||
}
|
||||
},
|
||||
|
||||
"decision": {
|
||||
"promotionId": "promo-uuid",
|
||||
"decision": "allow",
|
||||
"decidedAt": "2026-01-10T13:55:00Z",
|
||||
"gateResults": [
|
||||
{
|
||||
"gateName": "security-gate",
|
||||
"gateType": "security",
|
||||
"passed": true,
|
||||
"blocking": true,
|
||||
"message": "No critical or high vulnerabilities",
|
||||
"evaluatedAt": "2026-01-10T13:50:00Z",
|
||||
"details": {
|
||||
"critical": 0,
|
||||
"high": 0,
|
||||
"medium": 5,
|
||||
"low": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"gateName": "approval-gate",
|
||||
"gateType": "approval",
|
||||
"passed": true,
|
||||
"blocking": true,
|
||||
"message": "2/2 required approvals received",
|
||||
"evaluatedAt": "2026-01-10T13:55:00Z",
|
||||
"details": {
|
||||
"required": 2,
|
||||
"received": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"freezeWindowCheck": {
|
||||
"checked": true,
|
||||
"windowActive": false
|
||||
},
|
||||
"separationOfDuties": {
|
||||
"required": true,
|
||||
"satisfied": true,
|
||||
"requesterIds": ["user-john-uuid"],
|
||||
"approverIds": ["user-jane-uuid", "user-bob-uuid"]
|
||||
}
|
||||
},
|
||||
|
||||
"execution": {
|
||||
"deploymentJobId": "job-uuid",
|
||||
"strategy": "rolling",
|
||||
"startedAt": "2026-01-10T14:00:00Z",
|
||||
"completedAt": "2026-01-10T14:35:00Z",
|
||||
"status": "succeeded",
|
||||
"tasks": [
|
||||
{
|
||||
"targetId": "target-1-uuid",
|
||||
"targetName": "prod-web-01",
|
||||
"agentId": "agent-prod-uuid",
|
||||
"status": "succeeded",
|
||||
"startedAt": "2026-01-10T14:00:00Z",
|
||||
"completedAt": "2026-01-10T14:15:00Z",
|
||||
"digest": "sha256:abc123def456...",
|
||||
"stickerWritten": true
|
||||
},
|
||||
{
|
||||
"targetId": "target-2-uuid",
|
||||
"targetName": "prod-web-02",
|
||||
"agentId": "agent-prod-uuid",
|
||||
"status": "succeeded",
|
||||
"startedAt": "2026-01-10T14:20:00Z",
|
||||
"completedAt": "2026-01-10T14:35:00Z",
|
||||
"digest": "sha256:abc123def456...",
|
||||
"stickerWritten": true
|
||||
}
|
||||
],
|
||||
"artifacts": [
|
||||
{
|
||||
"name": "compose.stella.lock.yml",
|
||||
"type": "compose-lock",
|
||||
"sha256": "checksum...",
|
||||
"storageRef": "s3://artifacts/job-uuid/compose.stella.lock.yml"
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"totalTasks": 2,
|
||||
"succeededTasks": 2,
|
||||
"failedTasks": 0,
|
||||
"totalDurationSeconds": 2100
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"contentHash": "sha256:content-hash...",
|
||||
"signature": "base64-signature...",
|
||||
"signatureAlgorithm": "RS256",
|
||||
"signerKeyRef": "stella/signing/prod-key-2026"
|
||||
}
|
||||
```
|
||||
|
||||
## Signature Verification
|
||||
|
||||
```typescript
|
||||
async function verifyEvidencePacket(packet: EvidencePacket): Promise<VerificationResult> {
|
||||
// 1. Verify content hash
|
||||
const canonicalContent = canonicalize(packet.content);
|
||||
const computedHash = sha256(canonicalContent);
|
||||
|
||||
if (computedHash !== packet.contentHash) {
|
||||
return { valid: false, error: "Content hash mismatch" };
|
||||
}
|
||||
|
||||
// 2. Get signing key
|
||||
const publicKey = await getPublicKey(packet.signerKeyRef);
|
||||
|
||||
// 3. Verify signature
|
||||
const signatureValid = await verify(
|
||||
packet.signature,
|
||||
packet.contentHash,
|
||||
publicKey,
|
||||
packet.signatureAlgorithm
|
||||
);
|
||||
|
||||
if (!signatureValid) {
|
||||
return { valid: false, error: "Invalid signature" };
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
}
|
||||
```
|
||||
|
||||
## Storage
|
||||
|
||||
Evidence packets are stored in an append-only table:
|
||||
|
||||
```sql
|
||||
CREATE TABLE release.evidence_packets (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
||||
promotion_id UUID NOT NULL REFERENCES release.promotions(id),
|
||||
type TEXT NOT NULL,
|
||||
version TEXT NOT NULL DEFAULT '1.0',
|
||||
content JSONB NOT NULL,
|
||||
content_hash TEXT NOT NULL,
|
||||
signature TEXT NOT NULL,
|
||||
signature_algorithm TEXT NOT NULL,
|
||||
signer_key_ref TEXT NOT NULL,
|
||||
generated_at TIMESTAMPTZ NOT NULL,
|
||||
generator_version TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
-- Note: No updated_at - packets are immutable
|
||||
);
|
||||
|
||||
-- Prevent modifications
|
||||
REVOKE UPDATE, DELETE ON release.evidence_packets FROM app_role;
|
||||
```
|
||||
|
||||
## Export Formats
|
||||
|
||||
Evidence packets can be exported in multiple formats:
|
||||
|
||||
| Format | Use Case |
|
||||
|--------|----------|
|
||||
| JSON | API consumption, archival |
|
||||
| PDF | Human-readable compliance reports |
|
||||
| CSV | Spreadsheet analysis |
|
||||
| SLSA | SLSA provenance format |
|
||||
|
||||
## References
|
||||
|
||||
- [Security Overview](../security/overview.md)
|
||||
- [Deployment Artifacts](../deployment/artifacts.md)
|
||||
- [Audit Trail](../security/audit-trail.md)
|
||||
235
docs/modules/release-orchestrator/appendices/glossary.md
Normal file
235
docs/modules/release-orchestrator/appendices/glossary.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# Glossary
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Agent
|
||||
A software component installed on deployment targets that receives and executes deployment tasks. Agents communicate with the orchestrator via mTLS and execute deployments locally on the target.
|
||||
|
||||
### Approval
|
||||
A human decision to authorize a promotion request. Approvals may require multiple approvers and enforce separation of duties.
|
||||
|
||||
### Approval Policy
|
||||
Rules defining who can approve promotions to specific environments, including required approval counts and SoD requirements.
|
||||
|
||||
### Blue-Green Deployment
|
||||
A deployment strategy using two identical production environments. Traffic switches from "blue" (current) to "green" (new) after validation.
|
||||
|
||||
### Canary Deployment
|
||||
A deployment strategy that gradually rolls out changes to a small subset of targets before full deployment, allowing validation with real traffic.
|
||||
|
||||
### Channel
|
||||
A version stream for components (e.g., "stable", "beta", "nightly"). Each channel tracks the latest compatible version.
|
||||
|
||||
### Component
|
||||
A deployable unit mapped to a container image repository. Components have versions tracked via digest.
|
||||
|
||||
### Compose Lock
|
||||
A Docker Compose file with all image references pinned to specific digests, ensuring reproducible deployments.
|
||||
|
||||
### Connector
|
||||
A plugin that integrates Release Orchestrator with external systems (registries, CI/CD, notifications, etc.).
|
||||
|
||||
### Decision Record
|
||||
An immutable record of all gate evaluations and conditions considered when making a promotion decision.
|
||||
|
||||
### Deployment Job
|
||||
A unit of work representing the deployment of a release to an environment. Contains multiple deployment tasks.
|
||||
|
||||
### Deployment Task
|
||||
A single target-level deployment operation within a deployment job.
|
||||
|
||||
### Digest
|
||||
A cryptographic hash (SHA-256) that uniquely identifies a container image. Format: `sha256:abc123...`
|
||||
|
||||
### Drift
|
||||
A mismatch between the expected deployed version (from version sticker) and the actual running version on a target.
|
||||
|
||||
### Environment
|
||||
A logical grouping of deployment targets representing a stage in the promotion pipeline (e.g., dev, staging, production).
|
||||
|
||||
### Evidence Packet
|
||||
An immutable, cryptographically signed record of deployment decisions and outcomes for audit purposes.
|
||||
|
||||
### Freeze Window
|
||||
A time period during which deployments to an environment are blocked (e.g., holiday code freeze).
|
||||
|
||||
### Gate
|
||||
A checkpoint in the promotion workflow that must pass before deployment proceeds. Types include security gates, approval gates, and custom policy gates.
|
||||
|
||||
### Promotion
|
||||
The process of moving a release from one environment to another, subject to gates and approvals.
|
||||
|
||||
### Release
|
||||
A versioned bundle of component digests representing a deployable unit. Releases are immutable once created.
|
||||
|
||||
### Rolling Deployment
|
||||
A deployment strategy that updates targets in batches, maintaining availability throughout the process.
|
||||
|
||||
### Rollback
|
||||
The process of reverting to a previous release version when a deployment fails or causes issues.
|
||||
|
||||
### Security Gate
|
||||
An automated gate that evaluates security policies (vulnerability thresholds, compliance requirements) before allowing promotion.
|
||||
|
||||
### Separation of Duties (SoD)
|
||||
A security principle requiring that the person who requests a promotion cannot be the same person who approves it.
|
||||
|
||||
### Step
|
||||
A single unit of work within a workflow template. Steps have types (deploy, approve, notify, etc.) and can have dependencies.
|
||||
|
||||
### Target
|
||||
A specific deployment destination (host, service, container) within an environment.
|
||||
|
||||
### Tenant
|
||||
An isolated organizational unit with its own environments, releases, and configurations. Multi-tenancy ensures data isolation.
|
||||
|
||||
### Version Map
|
||||
A mapping of image tags to digests for a component, allowing tag-based references while maintaining digest-based deployments.
|
||||
|
||||
### Version Sticker
|
||||
Metadata placed on deployment targets indicating the currently deployed release and digest.
|
||||
|
||||
### Workflow
|
||||
A DAG (Directed Acyclic Graph) of steps defining the deployment process, including gates, approvals, and verification.
|
||||
|
||||
### Workflow Template
|
||||
A reusable workflow definition that can be customized for specific deployment scenarios.
|
||||
|
||||
## Module Abbreviations
|
||||
|
||||
| Abbreviation | Full Name | Description |
|
||||
|--------------|-----------|-------------|
|
||||
| INTHUB | Integration Hub | External system integration |
|
||||
| ENVMGR | Environment Manager | Environment and target management |
|
||||
| RELMAN | Release Management | Component and release management |
|
||||
| WORKFL | Workflow Engine | Workflow execution |
|
||||
| PROMOT | Promotion & Approval | Promotion and approval handling |
|
||||
| DEPLOY | Deployment Execution | Deployment orchestration |
|
||||
| AGENTS | Deployment Agents | Agent management |
|
||||
| PROGDL | Progressive Delivery | A/B and canary releases |
|
||||
| RELEVI | Release Evidence | Audit and compliance |
|
||||
| PLUGIN | Plugin Infrastructure | Plugin system |
|
||||
|
||||
## Deployment Strategies
|
||||
|
||||
| Strategy | Description |
|
||||
|----------|-------------|
|
||||
| All-at-once | Deploy to all targets simultaneously |
|
||||
| Rolling | Deploy in batches with availability |
|
||||
| Canary | Gradual rollout with metrics validation |
|
||||
| Blue-Green | Parallel environment with traffic switch |
|
||||
|
||||
## Status Values
|
||||
|
||||
### Promotion Status
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `pending` | Promotion created, not yet evaluated |
|
||||
| `pending_approval` | Waiting for human approval |
|
||||
| `approved` | Approved, ready for deployment |
|
||||
| `rejected` | Rejected by approver |
|
||||
| `deploying` | Deployment in progress |
|
||||
| `completed` | Successfully deployed |
|
||||
| `failed` | Deployment failed |
|
||||
| `cancelled` | Cancelled by user |
|
||||
|
||||
### Deployment Job Status
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `pending` | Job created, not started |
|
||||
| `preparing` | Generating artifacts |
|
||||
| `running` | Tasks executing |
|
||||
| `completing` | Verifying deployment |
|
||||
| `completed` | Successfully completed |
|
||||
| `failed` | Deployment failed |
|
||||
| `rolling_back` | Rollback in progress |
|
||||
| `rolled_back` | Rollback completed |
|
||||
|
||||
### Agent Status
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `online` | Agent connected and healthy |
|
||||
| `offline` | Agent not connected |
|
||||
| `degraded` | Agent connected but reporting issues |
|
||||
|
||||
### Target Health Status
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| `healthy` | Target responding correctly |
|
||||
| `unhealthy` | Target failing health checks |
|
||||
| `unknown` | Health status not determined |
|
||||
|
||||
## API Error Codes
|
||||
|
||||
| Code | Description |
|
||||
|------|-------------|
|
||||
| `RELEASE_NOT_FOUND` | Release ID does not exist |
|
||||
| `ENVIRONMENT_NOT_FOUND` | Environment ID does not exist |
|
||||
| `PROMOTION_BLOCKED` | Promotion blocked by gate or freeze |
|
||||
| `APPROVAL_REQUIRED` | Promotion requires approval |
|
||||
| `INSUFFICIENT_APPROVALS` | Not enough approvals |
|
||||
| `SOD_VIOLATION` | Separation of duties violated |
|
||||
| `FREEZE_WINDOW_ACTIVE` | Environment in freeze window |
|
||||
| `SECURITY_GATE_FAILED` | Security requirements not met |
|
||||
| `NO_AGENT_AVAILABLE` | No agent available for target |
|
||||
| `DEPLOYMENT_IN_PROGRESS` | Another deployment running |
|
||||
| `ROLLBACK_NOT_POSSIBLE` | No previous version to rollback to |
|
||||
|
||||
## Integration Types
|
||||
|
||||
| Type | Category | Description |
|
||||
|------|----------|-------------|
|
||||
| `docker-registry` | Registry | Docker Registry v2 |
|
||||
| `ecr` | Registry | AWS ECR |
|
||||
| `acr` | Registry | Azure Container Registry |
|
||||
| `gcr` | Registry | Google Container Registry |
|
||||
| `harbor` | Registry | Harbor Registry |
|
||||
| `gitlab-ci` | CI/CD | GitLab CI/CD |
|
||||
| `github-actions` | CI/CD | GitHub Actions |
|
||||
| `jenkins` | CI/CD | Jenkins |
|
||||
| `slack` | Notification | Slack |
|
||||
| `teams` | Notification | Microsoft Teams |
|
||||
| `email` | Notification | Email (SMTP) |
|
||||
| `hashicorp-vault` | Secrets | HashiCorp Vault |
|
||||
| `prometheus` | Metrics | Prometheus |
|
||||
|
||||
## Workflow Step Types
|
||||
|
||||
| Type | Category | Description |
|
||||
|------|----------|-------------|
|
||||
| `approval` | Control | Wait for human approval |
|
||||
| `wait` | Control | Wait for duration |
|
||||
| `condition` | Control | Branch based on condition |
|
||||
| `parallel` | Control | Execute children in parallel |
|
||||
| `security-gate` | Gate | Evaluate security policy |
|
||||
| `custom-gate` | Gate | Custom OPA policy |
|
||||
| `freeze-check` | Gate | Check freeze windows |
|
||||
| `deploy-docker` | Deploy | Deploy single container |
|
||||
| `deploy-compose` | Deploy | Deploy Compose stack |
|
||||
| `health-check` | Verify | HTTP/TCP health check |
|
||||
| `smoke-test` | Verify | Run smoke tests |
|
||||
| `notify` | Notify | Send notification |
|
||||
| `webhook` | Integration | Call external webhook |
|
||||
| `trigger-ci` | Integration | Trigger CI pipeline |
|
||||
| `rollback` | Recovery | Rollback deployment |
|
||||
|
||||
## Security Terms
|
||||
|
||||
| Term | Description |
|
||||
|------|-------------|
|
||||
| mTLS | Mutual TLS - both client and server authenticate with certificates |
|
||||
| JWT | JSON Web Token - used for API authentication |
|
||||
| RBAC | Role-Based Access Control |
|
||||
| OPA | Open Policy Agent - policy evaluation engine |
|
||||
| SoD | Separation of Duties |
|
||||
| PEP | Policy Enforcement Point |
|
||||
|
||||
## References
|
||||
|
||||
- [Design Principles](../design/principles.md)
|
||||
- [API Overview](../api/overview.md)
|
||||
- [Security Overview](../security/overview.md)
|
||||
Reference in New Issue
Block a user