Files
git.stella-ops.org/docs/api/evidence-decision-api.openapi.yaml

705 lines
18 KiB
YAML

openapi: 3.1.0
info:
title: StellaOps Evidence & Decision API
description: |
REST API for evidence retrieval and decision recording.
Sprint: SPRINT_3602_0001_0001
Updated: SPRINT_20260112_005_BE_evidence_card_api (EVPCARD-BE-002)
version: 1.1.0
license:
name: BUSL-1.1
url: https://spdx.org/licenses/BUSL-1.1.html
servers:
- url: /v1
description: API v1
security:
- bearerAuth: []
paths:
/alerts:
get:
operationId: listAlerts
summary: List alerts with filtering and pagination
tags:
- Alerts
parameters:
- name: band
in: query
schema:
type: string
enum: [critical, high, medium, low, info]
- name: severity
in: query
schema:
type: string
- name: status
in: query
schema:
type: string
enum: [open, acknowledged, resolved, suppressed]
- name: artifactId
in: query
schema:
type: string
- name: vulnId
in: query
schema:
type: string
- name: componentPurl
in: query
schema:
type: string
- name: limit
in: query
schema:
type: integer
default: 50
maximum: 500
- name: offset
in: query
schema:
type: integer
default: 0
responses:
'200':
description: Alert list
content:
application/json:
schema:
$ref: '#/components/schemas/AlertListResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/alerts/{alertId}:
get:
operationId: getAlert
summary: Get alert details
tags:
- Alerts
parameters:
- $ref: '#/components/parameters/alertId'
responses:
'200':
description: Alert details
content:
application/json:
schema:
$ref: '#/components/schemas/AlertSummary'
'404':
$ref: '#/components/responses/NotFound'
/alerts/{alertId}/evidence:
get:
operationId: getAlertEvidence
summary: Get evidence bundle for an alert
tags:
- Evidence
parameters:
- $ref: '#/components/parameters/alertId'
responses:
'200':
description: Evidence payload
content:
application/json:
schema:
$ref: '#/components/schemas/EvidencePayloadResponse'
'404':
$ref: '#/components/responses/NotFound'
/alerts/{alertId}/decisions:
post:
operationId: recordDecision
summary: Record a decision for an alert
tags:
- Decisions
parameters:
- $ref: '#/components/parameters/alertId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DecisionRequest'
responses:
'201':
description: Decision recorded
content:
application/json:
schema:
$ref: '#/components/schemas/DecisionResponse'
'404':
$ref: '#/components/responses/NotFound'
'400':
$ref: '#/components/responses/BadRequest'
/alerts/{alertId}/audit:
get:
operationId: getAlertAudit
summary: Get audit timeline for an alert
tags:
- Audit
parameters:
- $ref: '#/components/parameters/alertId'
responses:
'200':
description: Audit timeline
content:
application/json:
schema:
$ref: '#/components/schemas/AuditTimelineResponse'
'404':
$ref: '#/components/responses/NotFound'
/alerts/{alertId}/bundle:
get:
operationId: downloadAlertBundle
summary: Download evidence bundle as tar.gz
tags:
- Bundles
parameters:
- $ref: '#/components/parameters/alertId'
responses:
'200':
description: Evidence bundle file
content:
application/gzip:
schema:
type: string
format: binary
'404':
$ref: '#/components/responses/NotFound'
/alerts/{alertId}/bundle/verify:
post:
operationId: verifyAlertBundle
summary: Verify evidence bundle integrity
tags:
- Bundles
parameters:
- $ref: '#/components/parameters/alertId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/BundleVerificationRequest'
responses:
'200':
description: Verification result
content:
application/json:
schema:
$ref: '#/components/schemas/BundleVerificationResponse'
'404':
$ref: '#/components/responses/NotFound'
# Sprint: SPRINT_20260112_005_BE_evidence_card_api (EVPCARD-BE-002)
/evidence-packs/{packId}/export:
get:
operationId: exportEvidencePack
summary: Export evidence pack in various formats
description: |
Exports an evidence pack in the specified format. Supports JSON, signed JSON,
Markdown, HTML, PDF, and evidence-card formats.
**Evidence Card formats** (v1.1):
- `evidence-card`: Full evidence card with SBOM excerpt, DSSE envelope, and Rekor receipt
- `card-compact`: Compact evidence card without full SBOM
tags:
- EvidencePacks
parameters:
- name: packId
in: path
required: true
schema:
type: string
description: Evidence pack identifier
- name: format
in: query
required: false
schema:
type: string
enum: [json, signedjson, markdown, md, html, pdf, evidence-card, evidencecard, card, card-compact, evidencecardcompact]
default: json
description: |
Export format. Format aliases:
- `evidence-card`, `evidencecard`, `card` → Evidence Card
- `card-compact`, `evidencecardcompact` → Compact Evidence Card
responses:
'200':
description: Exported evidence pack
headers:
X-Evidence-Pack-Id:
schema:
type: string
description: Evidence pack identifier
X-Content-Digest:
schema:
type: string
description: SHA-256 content digest of the pack
X-Evidence-Card-Version:
schema:
type: string
description: Evidence card schema version (only for evidence-card formats)
X-Rekor-Log-Index:
schema:
type: integer
format: int64
description: Rekor transparency log index (only for evidence-card formats with Rekor receipt)
content:
application/json:
schema:
$ref: '#/components/schemas/EvidencePackExport'
application/vnd.stellaops.evidence-card+json:
schema:
$ref: '#/components/schemas/EvidenceCard'
text/markdown:
schema:
type: string
text/html:
schema:
type: string
application/pdf:
schema:
type: string
format: binary
'404':
$ref: '#/components/responses/NotFound'
'401':
$ref: '#/components/responses/Unauthorized'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
alertId:
name: alertId
in: path
required: true
schema:
type: string
description: Alert identifier
responses:
BadRequest:
description: Bad request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
Unauthorized:
description: Unauthorized
NotFound:
description: Resource not found
schemas:
AlertListResponse:
type: object
required:
- items
- total_count
properties:
items:
type: array
items:
$ref: '#/components/schemas/AlertSummary'
total_count:
type: integer
next_page_token:
type: string
AlertSummary:
type: object
required:
- alert_id
- artifact_id
- vuln_id
- severity
- band
- status
- created_at
properties:
alert_id:
type: string
artifact_id:
type: string
vuln_id:
type: string
component_purl:
type: string
severity:
type: string
band:
type: string
enum: [critical, high, medium, low, info]
status:
type: string
enum: [open, acknowledged, resolved, suppressed]
score:
type: number
format: double
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
decision_count:
type: integer
EvidencePayloadResponse:
type: object
required:
- alert_id
properties:
alert_id:
type: string
reachability:
$ref: '#/components/schemas/EvidenceSection'
callstack:
$ref: '#/components/schemas/EvidenceSection'
vex:
$ref: '#/components/schemas/EvidenceSection'
EvidenceSection:
type: object
properties:
data:
type: object
hash:
type: string
source:
type: string
DecisionRequest:
type: object
required:
- decision
- rationale
properties:
decision:
type: string
enum: [accept_risk, mitigate, suppress, escalate]
rationale:
type: string
minLength: 10
maxLength: 2000
justification_code:
type: string
metadata:
type: object
DecisionResponse:
type: object
required:
- decision_id
- alert_id
- decision
- recorded_at
properties:
decision_id:
type: string
alert_id:
type: string
decision:
type: string
rationale:
type: string
recorded_at:
type: string
format: date-time
recorded_by:
type: string
replay_token:
type: string
AuditTimelineResponse:
type: object
required:
- alert_id
- events
- total_count
properties:
alert_id:
type: string
events:
type: array
items:
$ref: '#/components/schemas/AuditEvent'
total_count:
type: integer
AuditEvent:
type: object
required:
- event_id
- event_type
- timestamp
properties:
event_id:
type: string
event_type:
type: string
timestamp:
type: string
format: date-time
actor:
type: string
details:
type: object
replay_token:
type: string
BundleVerificationRequest:
type: object
required:
- bundle_hash
properties:
bundle_hash:
type: string
description: SHA-256 hash of the bundle
signature:
type: string
description: Optional DSSE signature
BundleVerificationResponse:
type: object
required:
- alert_id
- is_valid
- verified_at
properties:
alert_id:
type: string
is_valid:
type: boolean
verified_at:
type: string
format: date-time
signature_valid:
type: boolean
hash_valid:
type: boolean
chain_valid:
type: boolean
errors:
type: array
items:
type: string
ProblemDetails:
type: object
properties:
type:
type: string
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string
# Sprint: SPRINT_20260112_005_BE_evidence_card_api (EVPCARD-BE-002)
EvidencePackExport:
type: object
required:
- pack_id
- format
- content_type
- file_name
properties:
pack_id:
type: string
description: Evidence pack identifier
format:
type: string
enum: [json, signedjson, markdown, html, pdf, evidence-card, evidence-card-compact]
description: Export format used
content_type:
type: string
description: MIME content type
file_name:
type: string
description: Suggested filename for download
content_digest:
type: string
description: SHA-256 digest of the content
EvidenceCard:
type: object
description: |
Single-file evidence card packaging SBOM excerpt, DSSE envelope, and Rekor receipt.
Designed for offline verification and audit trail.
required:
- card_id
- version
- pack_id
- created_at
- subject
- envelope
properties:
card_id:
type: string
description: Unique evidence card identifier
version:
type: string
description: Evidence card schema version (e.g., "1.0.0")
pack_id:
type: string
description: Source evidence pack identifier
created_at:
type: string
format: date-time
description: Card creation timestamp (ISO 8601 UTC)
subject:
$ref: '#/components/schemas/EvidenceCardSubject'
envelope:
$ref: '#/components/schemas/DsseEnvelope'
sbom_excerpt:
$ref: '#/components/schemas/SbomExcerpt'
rekor_receipt:
$ref: '#/components/schemas/RekorReceipt'
content_digest:
type: string
description: SHA-256 digest of canonical card content
EvidenceCardSubject:
type: object
required:
- type
properties:
type:
type: string
enum: [finding, cve, component, image, policy, custom]
finding_id:
type: string
cve_id:
type: string
component:
type: string
description: Component PURL
image_digest:
type: string
DsseEnvelope:
type: object
description: Dead Simple Signing Envelope (DSSE) per https://github.com/secure-systems-lab/dsse
required:
- payload_type
- payload
- signatures
properties:
payload_type:
type: string
description: Media type of the payload
payload:
type: string
format: byte
description: Base64-encoded payload
signatures:
type: array
items:
$ref: '#/components/schemas/DsseSignature'
DsseSignature:
type: object
required:
- sig
properties:
keyid:
type: string
description: Key identifier
sig:
type: string
format: byte
description: Base64-encoded signature
SbomExcerpt:
type: object
description: Relevant excerpt from the SBOM for the evidence subject
properties:
format:
type: string
enum: [spdx-2.2, spdx-2.3, cyclonedx-1.5, cyclonedx-1.6]
component_name:
type: string
component_version:
type: string
component_purl:
type: string
licenses:
type: array
items:
type: string
vulnerabilities:
type: array
items:
type: string
RekorReceipt:
type: object
description: Sigstore Rekor transparency log receipt for offline verification
required:
- log_index
- log_id
- integrated_time
properties:
log_index:
type: integer
format: int64
description: Rekor log index
log_id:
type: string
description: Rekor log ID (base64-encoded SHA-256 of public key)
integrated_time:
type: integer
format: int64
description: Unix timestamp when entry was integrated
inclusion_proof:
$ref: '#/components/schemas/InclusionProof'
inclusion_promise:
$ref: '#/components/schemas/SignedEntryTimestamp'
InclusionProof:
type: object
description: Merkle tree inclusion proof for log entry
properties:
log_index:
type: integer
format: int64
root_hash:
type: string
format: byte
tree_size:
type: integer
format: int64
hashes:
type: array
items:
type: string
format: byte
SignedEntryTimestamp:
type: object
description: Signed Entry Timestamp (SET) from Rekor
properties:
log_id:
type: string
format: byte
integrated_time:
type: integer
format: int64
signature:
type: string
format: byte