Files
git.stella-ops.org/docs/api/taskrunner-openapi.yaml
StellaOps Bot f6c22854a4
Some checks failed
AOC Guard CI / aoc-verify (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
mock-dev-release / package-mock-release (push) Has been cancelled
feat(api): Add Policy Registry API specification
- Introduced OpenAPI specification for the StellaOps Policy Registry API, covering endpoints for verification policies, policy packs, snapshots, violations, overrides, sealed mode operations, and advisory staleness tracking.
- Defined schemas, parameters, and responses for comprehensive API documentation.

chore(scanner): Add global usings for scanner analyzers

- Created GlobalUsings.cs to simplify namespace usage across analyzer libraries.

feat(scanner): Implement Surface Service Collection Extensions

- Added SurfaceServiceCollectionExtensions for dependency injection registration of surface analysis services.
- Included methods for adding surface analysis, surface collectors, and entry point collectors to the service collection.
2025-12-06 20:52:23 +02:00

887 lines
28 KiB
YAML

# OpenAPI 3.1 specification for StellaOps TaskRunner WebService
openapi: 3.1.0
info:
title: StellaOps TaskRunner API
version: 0.1.0-draft
description: |
Contract for TaskRunner service covering pack runs, simulations, logs, artifacts, and approvals.
Uses the platform error envelope and tenant header `X-StellaOps-Tenant`.
## Streaming Endpoints
The `/runs/{runId}/logs` endpoint returns logs in NDJSON (Newline Delimited JSON) format
for efficient streaming. Each line is a complete JSON object.
## Control Flow Steps
TaskPacks support the following step kinds:
- **run**: Execute an action using a builtin or custom executor
- **parallel**: Execute child steps concurrently with optional maxParallel limit
- **map**: Iterate over items and execute a template step for each
- **loop**: Iterate with items expression, range, or static list
- **conditional**: Branch based on condition expressions
- **gate.approval**: Require manual approval before proceeding
- **gate.policy**: Evaluate policy and optionally require override approval
servers:
- url: https://taskrunner.stellaops.example.com
description: Production
- url: https://taskrunner.dev.stellaops.example.com
description: Development
security:
- oauth2: [taskrunner.viewer]
- oauth2: [taskrunner.operator]
- oauth2: [taskrunner.admin]
paths:
/v1/task-runner/simulations:
post:
summary: Simulate a task pack
description: |
Validates a task pack manifest, creates an execution plan, and simulates the run
without actually executing any steps. Returns the simulation result showing which
steps would execute, which are skipped, and which require approvals.
operationId: simulateTaskPack
tags: [Simulations]
parameters:
- $ref: '#/components/parameters/Tenant'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SimulationRequest'
examples:
basic-simulation:
summary: Basic simulation request
value:
manifest: |
apiVersion: stellaops.io/pack.v1
kind: TaskPack
metadata:
name: scan-deploy
version: 1.0.0
spec:
inputs:
- name: target
type: string
required: true
sandbox:
mode: sealed
egressAllowlist: []
cpuLimitMillicores: 100
memoryLimitMiB: 128
quotaSeconds: 60
slo:
runP95Seconds: 300
approvalP95Seconds: 900
maxQueueDepth: 100
steps:
- id: scan
run:
uses: builtin:scanner
with:
target: "{{ inputs.target }}"
inputs:
target: "registry.example.com/app:v1.2.3"
responses:
'200':
description: Simulation completed
content:
application/json:
schema:
$ref: '#/components/schemas/SimulationResponse'
examples:
simulation-result:
value:
planHash: "sha256:a1b2c3d4e5f6..."
failurePolicy:
maxAttempts: 1
backoffSeconds: 0
continueOnError: false
steps:
- id: scan
templateId: scan
kind: Run
enabled: true
status: Pending
uses: "builtin:scanner"
children: []
outputs: []
hasPendingApprovals: false
'400':
description: Invalid manifest or inputs
content:
application/json:
schema:
$ref: '#/components/schemas/PlanErrorResponse'
default:
$ref: '#/components/responses/Error'
/v1/task-runner/runs:
post:
summary: Create a pack run
description: |
Creates a new pack run from a task pack manifest. The run is scheduled for execution
and will proceed through its steps. If approval gates are present, the run will pause
at those gates until approvals are granted.
operationId: createPackRun
tags: [Runs]
parameters:
- $ref: '#/components/parameters/Tenant'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateRunRequest'
examples:
create-run:
summary: Create a new run
value:
runId: "run-20251206-001"
manifest: |
apiVersion: stellaops.io/pack.v1
kind: TaskPack
metadata:
name: deploy-app
version: 2.0.0
spec:
sandbox:
mode: sealed
egressAllowlist: []
cpuLimitMillicores: 200
memoryLimitMiB: 256
quotaSeconds: 120
slo:
runP95Seconds: 600
approvalP95Seconds: 1800
maxQueueDepth: 50
approvals:
- id: security-review
grants: [packs.approve]
steps:
- id: build
run:
uses: builtin:build
- id: approval
gate:
approval:
id: security-review
message: "Security review required before deploy"
- id: deploy
run:
uses: builtin:deploy
tenantId: "tenant-prod"
responses:
'201':
description: Run created
headers:
Location:
description: URL of the created run
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/RunStateResponse'
'400':
description: Invalid manifest or inputs
content:
application/json:
schema:
$ref: '#/components/schemas/PlanErrorResponse'
'409':
description: Run ID already exists
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
default:
$ref: '#/components/responses/Error'
/v1/task-runner/runs/{runId}:
get:
summary: Get run state
description: |
Returns the current state of a pack run, including status of all steps,
failure policy, and timing information.
operationId: getRunState
tags: [Runs]
parameters:
- $ref: '#/components/parameters/Tenant'
- $ref: '#/components/parameters/RunId'
responses:
'200':
description: Run state
content:
application/json:
schema:
$ref: '#/components/schemas/RunStateResponse'
examples:
running:
summary: Run in progress
value:
runId: "run-20251206-001"
planHash: "sha256:a1b2c3d4..."
failurePolicy:
maxAttempts: 2
backoffSeconds: 30
continueOnError: false
createdAt: "2025-12-06T10:00:00Z"
updatedAt: "2025-12-06T10:05:00Z"
steps:
- stepId: build
kind: Run
enabled: true
continueOnError: false
status: Succeeded
attempts: 1
lastTransitionAt: "2025-12-06T10:02:00Z"
- stepId: approval
kind: GateApproval
enabled: true
continueOnError: false
approvalId: security-review
gateMessage: "Security review required before deploy"
status: Pending
attempts: 0
statusReason: "awaiting-approval"
- stepId: deploy
kind: Run
enabled: true
continueOnError: false
status: Pending
attempts: 0
'404':
description: Run not found
default:
$ref: '#/components/responses/Error'
/v1/task-runner/runs/{runId}/logs:
get:
summary: Stream run logs
description: |
Returns run logs as a stream of NDJSON (Newline Delimited JSON) entries.
Each line is a complete JSON object representing a log entry with timestamp,
level, event type, message, and optional metadata.
**Content-Type**: `application/x-ndjson`
operationId: streamRunLogs
tags: [Logs]
parameters:
- $ref: '#/components/parameters/Tenant'
- $ref: '#/components/parameters/RunId'
responses:
'200':
description: Log stream
content:
application/x-ndjson:
schema:
$ref: '#/components/schemas/RunLogEntry'
examples:
log-stream:
summary: Sample NDJSON log stream
value: |
{"timestamp":"2025-12-06T10:00:00Z","level":"info","eventType":"run.created","message":"Run created via API.","metadata":{"planHash":"sha256:a1b2c3d4...","requestedAt":"2025-12-06T10:00:00Z"}}
{"timestamp":"2025-12-06T10:00:01Z","level":"info","eventType":"step.started","message":"Starting step: build","stepId":"build"}
{"timestamp":"2025-12-06T10:02:00Z","level":"info","eventType":"step.completed","message":"Step completed: build","stepId":"build","metadata":{"duration":"119s"}}
{"timestamp":"2025-12-06T10:02:01Z","level":"warn","eventType":"gate.awaiting","message":"Awaiting approval: security-review","stepId":"approval"}
'404':
description: Run not found
default:
$ref: '#/components/responses/Error'
/v1/task-runner/runs/{runId}/artifacts:
get:
summary: List run artifacts
description: |
Returns a list of artifacts captured during the run, including file outputs,
evidence bundles, and expression-evaluated results.
operationId: listRunArtifacts
tags: [Artifacts]
parameters:
- $ref: '#/components/parameters/Tenant'
- $ref: '#/components/parameters/RunId'
responses:
'200':
description: Artifact list
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/RunArtifact'
examples:
artifacts:
value:
- name: scan-report
type: file
sourcePath: "/output/scan-report.json"
storedPath: "runs/run-20251206-001/artifacts/scan-report.json"
status: captured
capturedAt: "2025-12-06T10:02:00Z"
- name: evidence-bundle
type: object
status: captured
capturedAt: "2025-12-06T10:02:00Z"
expressionJson: '{"sha256":"abc123...","attestations":[...]}'
'404':
description: Run not found
default:
$ref: '#/components/responses/Error'
/v1/task-runner/runs/{runId}/approvals/{approvalId}:
post:
summary: Apply approval decision
description: |
Applies an approval decision (approved, rejected, or expired) to a pending
approval gate. The planHash must match to prevent approving a stale plan.
If approved, the run will resume execution. If rejected, the run will fail
at the gate step.
operationId: applyApprovalDecision
tags: [Approvals]
parameters:
- $ref: '#/components/parameters/Tenant'
- $ref: '#/components/parameters/RunId'
- $ref: '#/components/parameters/ApprovalId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ApprovalDecisionRequest'
examples:
approve:
summary: Approve the gate
value:
decision: approved
planHash: "sha256:a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef"
actorId: "user:alice@example.com"
summary: "Reviewed and approved for production deployment"
reject:
summary: Reject the gate
value:
decision: rejected
planHash: "sha256:a1b2c3d4e5f678901234567890abcdef1234567890abcdef1234567890abcdef"
actorId: "user:bob@example.com"
summary: "Security scan found critical vulnerabilities"
responses:
'200':
description: Decision applied
content:
application/json:
schema:
$ref: '#/components/schemas/ApprovalDecisionResponse'
examples:
approved:
value:
status: approved
resumed: true
'400':
description: Invalid decision or planHash format
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
'404':
description: Run or approval not found
'409':
description: Plan hash mismatch
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
default:
$ref: '#/components/responses/Error'
/v1/task-runner/runs/{runId}/cancel:
post:
summary: Cancel a run
description: |
Requests cancellation of a run. Remaining pending steps will be marked as
skipped. Steps that have already succeeded or been skipped are not affected.
operationId: cancelRun
tags: [Runs]
parameters:
- $ref: '#/components/parameters/Tenant'
- $ref: '#/components/parameters/RunId'
responses:
'202':
description: Cancellation accepted
headers:
Location:
description: URL of the run
schema:
type: string
content:
application/json:
schema:
type: object
properties:
status:
type: string
enum: [cancelled]
'404':
description: Run not found
default:
$ref: '#/components/responses/Error'
/.well-known/openapi:
get:
summary: Get OpenAPI metadata
description: |
Returns metadata about the OpenAPI specification including the spec URL,
ETag for caching, and a signature for verification.
operationId: getOpenApiMetadata
tags: [Metadata]
responses:
'200':
description: OpenAPI metadata
headers:
ETag:
description: Spec version ETag
schema:
type: string
X-Signature:
description: Spec signature for verification
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/OpenApiMetadata'
examples:
metadata:
value:
specUrl: "/openapi"
version: "0.1.0-draft"
buildVersion: "20251206.1"
etag: '"abc123"'
signature: "sha256:def456..."
components:
securitySchemes:
oauth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://auth.stellaops.example.com/oauth/token
scopes:
taskrunner.viewer: Read-only access to runs and logs
taskrunner.operator: Create runs and apply approvals
taskrunner.admin: Full administrative access
parameters:
Tenant:
name: X-StellaOps-Tenant
in: header
required: false
description: Tenant slug (optional for single-tenant deployments)
schema:
type: string
RunId:
name: runId
in: path
required: true
description: Unique run identifier
schema:
type: string
pattern: '^[a-zA-Z0-9_-]+$'
ApprovalId:
name: approvalId
in: path
required: true
description: Approval gate identifier (from task pack approvals section)
schema:
type: string
responses:
Error:
description: Standard error envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorEnvelope'
examples:
internal-error:
value:
error:
code: internal_error
message: "An unexpected error occurred"
traceId: "f62f3c2b9c8e4c53"
schemas:
ErrorEnvelope:
type: object
required: [error]
properties:
error:
type: object
required: [code, message]
properties:
code:
type: string
description: Machine-readable error code
message:
type: string
description: Human-readable error message
traceId:
type: string
description: Trace ID for debugging
SimulationRequest:
type: object
required: [manifest]
properties:
manifest:
type: string
description: Task pack manifest in YAML format
inputs:
type: object
additionalProperties: true
description: Input values to provide to the task pack
SimulationResponse:
type: object
required: [planHash, failurePolicy, steps, outputs, hasPendingApprovals]
properties:
planHash:
type: string
description: SHA-256 hash of the execution plan
pattern: '^sha256:[a-f0-9]{64}$'
failurePolicy:
$ref: '#/components/schemas/FailurePolicy'
steps:
type: array
items:
$ref: '#/components/schemas/SimulationStep'
outputs:
type: array
items:
$ref: '#/components/schemas/SimulationOutput'
hasPendingApprovals:
type: boolean
description: Whether the plan contains approval gates
SimulationStep:
type: object
required: [id, templateId, kind, enabled, status, children]
properties:
id:
type: string
templateId:
type: string
kind:
type: string
enum: [Run, GateApproval, GatePolicy, Parallel, Map, Loop, Conditional, Unknown]
enabled:
type: boolean
status:
type: string
enum: [Pending, Skipped, RequiresApproval, RequiresPolicy, WillIterate, WillBranch]
statusReason:
type: string
uses:
type: string
description: Executor reference for run steps
approvalId:
type: string
gateMessage:
type: string
maxParallel:
type: integer
continueOnError:
type: boolean
children:
type: array
items:
$ref: '#/components/schemas/SimulationStep'
loopInfo:
$ref: '#/components/schemas/LoopInfo'
conditionalInfo:
$ref: '#/components/schemas/ConditionalInfo'
policyInfo:
$ref: '#/components/schemas/PolicyInfo'
LoopInfo:
type: object
description: Loop step simulation details
properties:
itemsExpression:
type: string
iterator:
type: string
index:
type: string
maxIterations:
type: integer
aggregationMode:
type: string
enum: [collect, merge, last, first, none]
ConditionalInfo:
type: object
description: Conditional step simulation details
properties:
branches:
type: array
items:
type: object
properties:
condition:
type: string
stepCount:
type: integer
elseStepCount:
type: integer
outputUnion:
type: boolean
PolicyInfo:
type: object
description: Policy gate simulation details
properties:
policyId:
type: string
policyVersion:
type: string
failureAction:
type: string
enum: [abort, warn, requestOverride, branch]
retryCount:
type: integer
SimulationOutput:
type: object
required: [name, type, requiresRuntimeValue]
properties:
name:
type: string
type:
type: string
requiresRuntimeValue:
type: boolean
pathExpression:
type: string
valueExpression:
type: string
CreateRunRequest:
type: object
required: [manifest]
properties:
runId:
type: string
description: Optional custom run ID (auto-generated if not provided)
manifest:
type: string
description: Task pack manifest in YAML format
inputs:
type: object
additionalProperties: true
description: Input values to provide to the task pack
tenantId:
type: string
description: Tenant identifier
RunStateResponse:
type: object
required: [runId, planHash, failurePolicy, createdAt, updatedAt, steps]
properties:
runId:
type: string
planHash:
type: string
pattern: '^sha256:[a-f0-9]{64}$'
failurePolicy:
$ref: '#/components/schemas/FailurePolicy'
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
steps:
type: array
items:
$ref: '#/components/schemas/RunStateStep'
RunStateStep:
type: object
required: [stepId, kind, enabled, continueOnError, status, attempts]
properties:
stepId:
type: string
kind:
type: string
enum: [Run, GateApproval, GatePolicy, Parallel, Map, Loop, Conditional, Unknown]
enabled:
type: boolean
continueOnError:
type: boolean
maxParallel:
type: integer
approvalId:
type: string
gateMessage:
type: string
status:
type: string
enum: [Pending, Running, Succeeded, Failed, Skipped]
attempts:
type: integer
lastTransitionAt:
type: string
format: date-time
nextAttemptAt:
type: string
format: date-time
statusReason:
type: string
FailurePolicy:
type: object
required: [maxAttempts, backoffSeconds, continueOnError]
properties:
maxAttempts:
type: integer
minimum: 1
backoffSeconds:
type: integer
minimum: 0
continueOnError:
type: boolean
RunLogEntry:
type: object
required: [timestamp, level, eventType, message]
description: |
Log entry returned in NDJSON stream. Each entry is a single JSON object
followed by a newline character.
properties:
timestamp:
type: string
format: date-time
level:
type: string
enum: [debug, info, warn, error]
eventType:
type: string
description: |
Event type identifier, e.g.:
- run.created, run.started, run.completed, run.failed, run.cancelled
- step.started, step.completed, step.failed, step.skipped
- gate.awaiting, gate.approved, gate.rejected
- run.schedule-failed, run.cancel-requested
message:
type: string
stepId:
type: string
metadata:
type: object
additionalProperties:
type: string
RunArtifact:
type: object
required: [name, type, status]
properties:
name:
type: string
type:
type: string
enum: [file, object]
sourcePath:
type: string
storedPath:
type: string
status:
type: string
enum: [pending, captured, failed]
notes:
type: string
capturedAt:
type: string
format: date-time
expressionJson:
type: string
description: JSON string of evaluated expression result for object outputs
ApprovalDecisionRequest:
type: object
required: [decision, planHash]
properties:
decision:
type: string
enum: [approved, rejected, expired]
planHash:
type: string
pattern: '^sha256:[a-f0-9]{64}$'
description: Plan hash to verify against (must match current run plan)
actorId:
type: string
description: Identifier of the approver (e.g., user:alice@example.com)
summary:
type: string
description: Optional comment explaining the decision
ApprovalDecisionResponse:
type: object
required: [status, resumed]
properties:
status:
type: string
enum: [approved, rejected, expired]
resumed:
type: boolean
description: Whether the run was resumed (true for approved decisions)
PlanErrorResponse:
type: object
required: [errors]
properties:
errors:
type: array
items:
type: object
required: [path, message]
properties:
path:
type: string
description: JSON path to the error location
message:
type: string
OpenApiMetadata:
type: object
required: [specUrl, version, etag]
properties:
specUrl:
type: string
description: URL to fetch the full OpenAPI spec
version:
type: string
description: API version
buildVersion:
type: string
description: Build version identifier
etag:
type: string
description: ETag for caching
signature:
type: string
description: Signature for spec verification
tags:
- name: Simulations
description: Task pack simulation without execution
- name: Runs
description: Pack run lifecycle management
- name: Logs
description: Run log streaming
- name: Artifacts
description: Run artifact management
- name: Approvals
description: Approval gate decisions
- name: Metadata
description: Service metadata and discovery