Files
ss-tools/specs/044-dashboard-scenario-execution/contracts/openapi.yaml

318 lines
18 KiB
YAML

openapi: 3.1.0
info:
title: Scenario Execution Engine API
version: 0.1.0
description: Start and manage execution of dashboard test scenario runs (044).
paths:
/api/scenario-runs:
post:
operationId: scenarioRun.start
summary: Start a scenario run pinned to an immutable revision
security: [{ bearerAuth: [] }]
parameters:
- { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [scenario_id, revision_id, environment_id]
properties:
scenario_id: { type: string }
revision_id: { type: string }
environment_id: { type: string }
params: { type: object, description: "Launch values; server validates against 038 ParameterDefinition and persists immutable ParameterBinding[]" }
requested_target_reference: { type: object, description: "User-selected release/target; server verifies it matches the captured TargetSnapshot" }
baseline_set: { type: string }
execution_toggles: { type: object, description: "Optional evidence only (diagnostic screenshots, verbose logs, optional VLM). Mandatory steps cannot be disabled." }
responses:
"201": { description: ScenarioRun created (queued or pending_approval), content: { application/json: { schema: { $ref: "#/components/schemas/ScenarioRun" } } } }
"403": { description: Permission denied; PROD approval creates pending_approval run rather than returning 403 }
"409": { description: Stale revision or IDEMPOTENCY_KEY_REUSED with a different canonical request }
/api/scenarios/{scenario_id}/runs:
get:
operationId: scenarioRun.history
summary: Scenario run history (for 045 RunHistoryList)
security: [{ bearerAuth: [] }]
parameters: [{ name: scenario_id, in: path, required: true, schema: { type: string } }]
responses:
"200":
description: Run history
content:
application/json:
schema: { type: array, items: { $ref: "#/components/schemas/ScenarioRun" } }
/api/scenario-runs/{run_id}/result:
get:
operationId: scenarioRun.result
summary: Final result with aggregation + provenance
security: [{ bearerAuth: [] }]
parameters: [{ name: run_id, in: path, required: true, schema: { type: string } }]
responses: { "200": { description: ScenarioExecutionResult, content: { application/json: { schema: { $ref: "#/components/schemas/ScenarioExecutionResult" } } } } }
/api/scenario-runs/compare:
get:
operationId: scenarioRun.compare
summary: Compare two runs (per-step deltas, revision-diff warning)
security: [{ bearerAuth: [] }]
parameters:
- { name: a, in: query, required: true, schema: { type: string } }
- { name: b, in: query, required: true, schema: { type: string } }
responses: { "200": { description: RunComparison, content: { application/json: { schema: { $ref: "#/components/schemas/RunComparison" } } } } }
/api/scenario-runs/{run_id}/steps/{logical_step_id}/retry:
post:
operationId: scenarioRun.retryStep
summary: Retry a failed step + invalidated downstream closure
security: [{ bearerAuth: [] }]
parameters:
- { name: run_id, in: path, required: true, schema: { type: string } }
- { name: logical_step_id, in: path, required: true, schema: { type: string } }
responses:
"200": { description: Retried; downstream closure re-run }
"409": { description: Run advanced beyond step; closure re-run rejected }
/api/scenario-runs/{run_id}:
get:
operationId: scenarioRun.detail
summary: Get a run by id (recoverable)
security: [{ bearerAuth: [] }]
parameters: [{ name: run_id, in: path, required: true, schema: { type: string } }]
responses: { "200": { description: Run detail, content: { application/json: { schema: { $ref: "#/components/schemas/ScenarioRun" } } } } }
/api/scenario-runs/{run_id}/events:
get:
operationId: scenarioRun.events
summary: SSE stream of step events (replayable via Last-Event-ID)
security: [{ bearerAuth: [] }]
parameters:
- { name: run_id, in: path, required: true, schema: { type: string } }
- { name: Last-Event-ID, in: header, schema: { type: integer }, description: "sequence to replay from" }
responses:
"200":
content: { text/event-stream: { schema: { $ref: "#/components/schemas/ScenarioRunEvent" } } }
/api/scenario-runs/{run_id}/cancel:
post:
operationId: scenarioRun.cancel
summary: Cancel a run (bounded drain)
security: [{ bearerAuth: [] }]
parameters: [{ name: run_id, in: path, required: true, schema: { type: string } }]
responses: { "200": { description: Cancelled } }
/api/scenario-runs/{run_id}/resume:
post:
operationId: scenarioRun.resume
summary: Resume a paused run from resume token
security: [{ bearerAuth: [] }]
parameters: [{ name: run_id, in: path, required: true, schema: { type: string } }]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [resume_token, resume_reason]
properties:
resume_token: { type: string }
resume_reason: { type: string, enum: [worker_recovered, infrastructure_pause_resolved] }
responses: { "200": { description: Infrastructure pause resumed }, "409": { description: Cannot resume HumanCheckpoint or stale token } }
/api/scenario-runs/{run_id}/human/decision:
post:
operationId: scenarioRun.humanDecision
summary: Resolve a HumanCheckpoint (observation disposition)
security: [{ bearerAuth: [] }]
parameters: [{ name: run_id, in: path, required: true, schema: { type: string } }]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [checkpoint_id, decision_version, disposition]
properties:
checkpoint_id: { type: string }
decision_version: { type: integer }
disposition: { type: string, enum: [confirm, false_positive, pass, fail, inconclusive] }
comment: { type: string }
responses: { "200": { description: Checkpoint consumed; step outcome recorded; runner resumed internally }, "409": { description: Checkpoint already decided, expired, or version conflict } }
components:
securitySchemes:
bearerAuth: { type: http, scheme: bearer }
schemas:
ScenarioRun:
type: object
properties:
id: { type: string }
scenario_id: { type: string }
scenario_revision_id: { type: string }
environment_id: { type: string }
status: { type: string, enum: [pending_approval, queued, running, waiting_human, blocked, cancel_requested, cancelled, passed, failed, inconclusive] }
parameter_bindings: { type: array, items: { $ref: "#/components/schemas/ParameterBinding" } }
target_snapshot: { $ref: "#/components/schemas/TargetSnapshot" }
execution_principal_fingerprint: { type: string }
analytics_context_key: { type: string, description: "Server-derived immutable analytics grouping key" }
verification_program_hash: { type: string }
action_registry_version: { type: string }
step_runs: { type: array, items: { $ref: "#/components/schemas/ScenarioStepRun" } }
ScenarioStepRun:
type: object
properties:
id: { type: string }
logical_step_id: { type: string }
step_position: { type: integer }
attempt: { type: integer }
status: { type: string }
outputs: { type: object }
artifact_refs: { type: array, items: { type: string } }
error_code: { type: string, nullable: true }
step_outcome: { $ref: "#/components/schemas/StepOutcome" }
agent_evaluations: { type: array, items: { $ref: "#/components/schemas/AgentEvaluationSummary" } }
ParameterBinding:
type: object
required: [parameter_name, resolved_value, source, resolved_at]
properties:
parameter_name: { type: string }
resolved_value: {}
source: { type: string, enum: [launch_input, default, schedule, trigger] }
resolved_at: { type: string, format: date-time }
TargetSnapshot:
type: object
required: [environment_id, dashboard_fingerprint, dataset_lineage_fingerprint, captured_at]
properties:
environment_id: { type: string }
dashboard_release_id: { type: [string, "null"] }
dashboard_fingerprint: { type: string }
dataset_lineage_fingerprint: { type: string }
captured_at: { type: string, format: date-time }
ScenarioExecutionResult:
type: object
required: [run_id, status, step_counts, provenance, failures]
properties:
run_id: { type: string }
status: { type: string }
step_counts: { type: object, additionalProperties: { type: integer } }
failures: { type: array, items: { type: object } }
provenance: { type: object }
analytics_context_key: { type: string }
step_outcomes: { type: array, items: { $ref: "#/components/schemas/StepOutcome" } }
agent_evaluation_summary: { type: object }
StepOutcome:
type: object
required: [status, reason_codes, deterministic_evidence_refs]
properties:
status: { type: string, enum: [passed, failed, inconclusive, blocked, waiting_human] }
reason_codes: { type: array, items: { type: string } }
deterministic_evidence_refs: { type: array, items: { type: string } }
agent_evaluation_ids: { type: array, items: { type: string } }
decision_policy_id: { type: [string, "null"] }
decision_policy_version: { type: [string, "null"] }
AgentEvaluationSummary:
type: object
required: [evaluation_id, logical_step_id, verdict, confidence, model_id, prompt_template_version]
properties:
evaluation_id: { type: string }
logical_step_id: { type: string }
verdict: { type: string, enum: [pass, fail, inconclusive] }
confidence: { type: number, minimum: 0, maximum: 1 }
model_id: { type: string }
prompt_template_version: { type: string }
reason_codes: { type: array, items: { type: string } }
evidence_refs: { type: array, items: { type: string } }
AgentEvaluation:
allOf:
- $ref: "#/components/schemas/AgentEvaluationSummary"
- type: object
required: [scenario_run_id, attempt, provider_id, model_version, prompt_template_id, input_manifest_hash, findings, raw_response_artifact_ref, started_at, finished_at]
properties:
scenario_run_id: { type: string }
attempt: { type: integer, minimum: 1 }
provider_id: { type: string }
model_version: { type: string }
prompt_template_id: { type: string }
input_manifest_hash: { type: string }
findings: { type: array, items: { type: object } }
raw_response_artifact_ref: { type: string }
started_at: { type: string, format: date-time }
finished_at: { type: string, format: date-time }
DecisionPolicy:
type: object
required: [policy_id, version, deterministic_hard_failure, high_confidence_failure, low_confidence, disagreement, missing_evidence]
properties:
policy_id: { type: string }
version: { type: string }
deterministic_hard_failure: { type: string, enum: [failed] }
high_confidence_failure: { type: string, enum: [failed, inconclusive] }
low_confidence: { type: string, enum: [inconclusive] }
disagreement: { type: string, enum: [waiting_human, inconclusive] }
missing_evidence: { type: string, enum: [blocked, inconclusive] }
RunComparison:
type: object
required: [run_a, run_b, step_deltas, compatibility]
properties:
run_a: { type: string }
run_b: { type: string }
compatibility: { type: object }
step_deltas: { type: array, items: { type: object } }
ScenarioRunEvent:
oneOf:
- { $ref: "#/components/schemas/RunStartedEvent" }
- { $ref: "#/components/schemas/ApprovalRequiredEvent" }
- { $ref: "#/components/schemas/RunQueuedEvent" }
- { $ref: "#/components/schemas/StepStartedEvent" }
- { $ref: "#/components/schemas/StepProgressEvent" }
- { $ref: "#/components/schemas/EvidenceCreatedEvent" }
- { $ref: "#/components/schemas/AgentEvaluationStartedEvent" }
- { $ref: "#/components/schemas/AgentEvaluationCompletedEvent" }
- { $ref: "#/components/schemas/StepCompletedEvent" }
- { $ref: "#/components/schemas/CheckpointCreatedEvent" }
- { $ref: "#/components/schemas/RunCompletedEvent" }
- { $ref: "#/components/schemas/RunFailedEvent" }
- { $ref: "#/components/schemas/RunCancelledEvent" }
RunStartedEvent:
type: object
required: [id, sequence, event_type, run_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: run_started }, run_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
ApprovalRequiredEvent:
type: object
required: [id, sequence, event_type, run_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: approval_required }, run_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object, required: [approval_gate_id] } }
RunQueuedEvent:
type: object
required: [id, sequence, event_type, run_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: run_queued }, run_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
StepStartedEvent:
type: object
required: [id, sequence, event_type, run_id, logical_step_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: step_started }, run_id: { type: string }, logical_step_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
StepProgressEvent:
type: object
required: [id, sequence, event_type, run_id, logical_step_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: step_progress }, run_id: { type: string }, logical_step_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object, required: [progress] } }
EvidenceCreatedEvent:
type: object
required: [id, sequence, event_type, run_id, logical_step_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: evidence_created }, run_id: { type: string }, logical_step_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object, required: [evidence_ref] } }
AgentEvaluationStartedEvent:
type: object
required: [id, sequence, event_type, run_id, logical_step_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: agent_evaluation_started }, run_id: { type: string }, logical_step_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
AgentEvaluationCompletedEvent:
type: object
required: [id, sequence, event_type, run_id, logical_step_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: agent_evaluation_completed }, run_id: { type: string }, logical_step_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { $ref: "#/components/schemas/AgentEvaluationSummary" } }
StepCompletedEvent:
type: object
required: [id, sequence, event_type, run_id, logical_step_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: step_completed }, run_id: { type: string }, logical_step_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
CheckpointCreatedEvent:
type: object
required: [id, sequence, event_type, run_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: checkpoint_created }, run_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
RunCompletedEvent:
type: object
required: [id, sequence, event_type, run_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: run_completed }, run_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
RunFailedEvent:
type: object
required: [id, sequence, event_type, run_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: run_failed }, run_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }
RunCancelledEvent:
type: object
required: [id, sequence, event_type, run_id, occurred_at]
properties: { id: { type: string }, sequence: { type: integer }, event_type: { const: run_cancelled }, run_id: { type: string }, occurred_at: { type: string, format: date-time }, payload: { type: object } }