Files
git.stella-ops.org/docs/api/delta-compare-openapi.yaml
StellaOps Bot 5146204f1b feat: add security sink detection patterns for JavaScript/TypeScript
- Introduced `sink-detect.js` with various security sink detection patterns categorized by type (e.g., command injection, SQL injection, file operations).
- Implemented functions to build a lookup map for fast sink detection and to match sink calls against known patterns.
- Added `package-lock.json` for dependency management.
2025-12-22 23:21:21 +02:00

1031 lines
25 KiB
YAML

openapi: 3.1.0
info:
title: StellaOps Delta Compare API
description: |
REST API for comparing scan snapshots, baseline selection, actionable recommendations,
counterfactual analysis, and evidence/proof bundles.
Sprint: SPRINT_4200_0002_0006
version: 1.0.0
license:
name: AGPL-3.0-or-later
url: https://www.gnu.org/licenses/agpl-3.0.html
servers:
- url: /v1
description: API v1
security:
- bearerAuth: []
tags:
- name: Delta Compare
description: Compare scan snapshots
- name: Baselines
description: Baseline selection and rationale
- name: Actionables
description: Actionable remediation recommendations
- name: Counterfactuals
description: Counterfactual policy analysis
- name: Evidence
description: Evidence and proof bundles for comparisons
paths:
# Delta Compare Endpoints
/delta-compare/compute:
post:
operationId: computeDeltaCompare
summary: Compute a delta comparison between two snapshots
tags:
- Delta Compare
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeltaCompareRequest'
responses:
'200':
description: Delta comparison result
content:
application/json:
schema:
$ref: '#/components/schemas/DeltaCompareResult'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/delta-compare/{comparisonId}:
get:
operationId: getDeltaComparison
summary: Get a previously computed delta comparison
tags:
- Delta Compare
parameters:
- $ref: '#/components/parameters/comparisonId'
responses:
'200':
description: Delta comparison result
content:
application/json:
schema:
$ref: '#/components/schemas/DeltaCompareResult'
'404':
$ref: '#/components/responses/NotFound'
/delta-compare/{comparisonId}/summary:
get:
operationId: getDeltaSummary
summary: Get summary statistics for a comparison
tags:
- Delta Compare
parameters:
- $ref: '#/components/parameters/comparisonId'
responses:
'200':
description: Delta summary
content:
application/json:
schema:
$ref: '#/components/schemas/DeltaSummary'
'404':
$ref: '#/components/responses/NotFound'
/delta-compare/{comparisonId}/can-ship:
get:
operationId: checkCanShip
summary: Check if target can ship relative to base
tags:
- Delta Compare
parameters:
- $ref: '#/components/parameters/comparisonId'
responses:
'200':
description: Can-ship assessment
content:
application/json:
schema:
$ref: '#/components/schemas/CanShipResponse'
'404':
$ref: '#/components/responses/NotFound'
/delta-compare/{comparisonId}/verdict:
get:
operationId: getDeltaVerdict
summary: Get policy verdict for the comparison
tags:
- Delta Compare
parameters:
- $ref: '#/components/parameters/comparisonId'
responses:
'200':
description: Delta verdict
content:
application/json:
schema:
$ref: '#/components/schemas/DeltaVerdictResponse'
'404':
$ref: '#/components/responses/NotFound'
# Baseline Endpoints
/baselines/recommendations/{artifactDigest}:
get:
operationId: getBaselineRecommendations
summary: Get baseline recommendations for an artifact
tags:
- Baselines
parameters:
- name: artifactDigest
in: path
required: true
schema:
type: string
description: Artifact digest
- name: limit
in: query
schema:
type: integer
default: 10
maximum: 100
responses:
'200':
description: Baseline recommendations
content:
application/json:
schema:
$ref: '#/components/schemas/BaselineRecommendationsResponse'
'404':
$ref: '#/components/responses/NotFound'
/baselines/rationale/{baseDigest}/{headDigest}:
get:
operationId: getBaselineRationale
summary: Get rationale for baseline selection
tags:
- Baselines
parameters:
- name: baseDigest
in: path
required: true
schema:
type: string
- name: headDigest
in: path
required: true
schema:
type: string
responses:
'200':
description: Baseline rationale
content:
application/json:
schema:
$ref: '#/components/schemas/BaselineRationaleResponse'
'404':
$ref: '#/components/responses/NotFound'
# Actionables Endpoints
/actionables/delta/{deltaId}:
get:
operationId: getActionablesForDelta
summary: Get actionable recommendations for a delta comparison
tags:
- Actionables
parameters:
- name: deltaId
in: path
required: true
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: Actionables list
content:
application/json:
schema:
$ref: '#/components/schemas/ActionablesResponse'
'404':
$ref: '#/components/responses/NotFound'
/actionables/by-priority/{priority}:
get:
operationId: getActionablesByPriority
summary: Get actionables filtered by priority
tags:
- Actionables
parameters:
- name: priority
in: path
required: true
schema:
type: string
enum: [critical, high, medium, low]
- name: deltaId
in: query
schema:
type: string
description: Optional delta ID to filter by
- name: limit
in: query
schema:
type: integer
default: 50
responses:
'200':
description: Actionables list
content:
application/json:
schema:
$ref: '#/components/schemas/ActionablesResponse'
/actionables/by-type/{actionType}:
get:
operationId: getActionablesByType
summary: Get actionables filtered by action type
tags:
- Actionables
parameters:
- name: actionType
in: path
required: true
schema:
type: string
enum: [upgrade, patch, replace, configure, accept_risk, investigate]
- name: limit
in: query
schema:
type: integer
default: 50
responses:
'200':
description: Actionables list
content:
application/json:
schema:
$ref: '#/components/schemas/ActionablesResponse'
# Counterfactual Endpoints
/counterfactuals/compute:
post:
operationId: computeCounterfactual
summary: Compute counterfactual policy analysis
tags:
- Counterfactuals
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CounterfactualRequest'
responses:
'200':
description: Counterfactual result
content:
application/json:
schema:
$ref: '#/components/schemas/CounterfactualResponse'
'400':
$ref: '#/components/responses/BadRequest'
/counterfactuals/finding/{findingId}:
get:
operationId: getCounterfactualForFinding
summary: Get counterfactual analysis for a specific finding
tags:
- Counterfactuals
parameters:
- name: findingId
in: path
required: true
schema:
type: string
responses:
'200':
description: Counterfactual for finding
content:
application/json:
schema:
$ref: '#/components/schemas/FindingCounterfactualResponse'
'404':
$ref: '#/components/responses/NotFound'
/counterfactuals/scan/{scanId}/summary:
get:
operationId: getScanCounterfactualSummary
summary: Get counterfactual summary for entire scan
tags:
- Counterfactuals
parameters:
- name: scanId
in: path
required: true
schema:
type: string
responses:
'200':
description: Scan counterfactual summary
content:
application/json:
schema:
$ref: '#/components/schemas/ScanCounterfactualSummary'
'404':
$ref: '#/components/responses/NotFound'
# Evidence Endpoints
/delta-evidence/{comparisonId}:
get:
operationId: getDeltaEvidence
summary: Get evidence bundle for a delta comparison
tags:
- Evidence
parameters:
- $ref: '#/components/parameters/comparisonId'
responses:
'200':
description: Delta evidence bundle
content:
application/json:
schema:
$ref: '#/components/schemas/DeltaEvidenceResponse'
'404':
$ref: '#/components/responses/NotFound'
/delta-evidence/finding/{findingId}:
get:
operationId: getFindingEvidence
summary: Get evidence for a specific finding
tags:
- Evidence
parameters:
- name: findingId
in: path
required: true
schema:
type: string
responses:
'200':
description: Finding evidence
content:
application/json:
schema:
$ref: '#/components/schemas/FindingEvidenceResponse'
'404':
$ref: '#/components/responses/NotFound'
/delta-evidence/{comparisonId}/proof-bundle:
get:
operationId: getDeltaProofBundle
summary: Download proof bundle as tar.gz
tags:
- Evidence
parameters:
- $ref: '#/components/parameters/comparisonId'
responses:
'200':
description: Proof bundle file
content:
application/gzip:
schema:
type: string
format: binary
'404':
$ref: '#/components/responses/NotFound'
/delta-evidence/{comparisonId}/attestations:
get:
operationId: getDeltaAttestations
summary: Get attestation chain for comparison
tags:
- Evidence
parameters:
- $ref: '#/components/parameters/comparisonId'
responses:
'200':
description: Attestation chain
content:
application/json:
schema:
$ref: '#/components/schemas/AttestationChainResponse'
'404':
$ref: '#/components/responses/NotFound'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
comparisonId:
name: comparisonId
in: path
required: true
schema:
type: string
description: Delta comparison identifier
responses:
BadRequest:
description: Bad request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
Unauthorized:
description: Unauthorized
NotFound:
description: Resource not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
schemas:
# Delta Compare Schemas
DeltaCompareRequest:
type: object
required:
- baseDigest
- targetDigest
properties:
baseDigest:
type: string
description: Base snapshot digest (the 'before' state)
targetDigest:
type: string
description: Target snapshot digest (the 'after' state)
includeUnchanged:
type: boolean
default: false
description: Include findings that are unchanged
severityFilter:
type: string
enum: [critical, high, medium, low]
description: Filter by minimum severity
DeltaCompareResult:
type: object
required:
- comparisonId
- baseDigest
- targetDigest
- riskDirection
- summary
- changes
properties:
comparisonId:
type: string
baseDigest:
type: string
targetDigest:
type: string
riskDirection:
type: string
enum: [improved, degraded, unchanged]
verdictChanged:
type: boolean
baseVerdict:
type: string
targetVerdict:
type: string
summary:
$ref: '#/components/schemas/DeltaSummary'
changes:
type: array
items:
$ref: '#/components/schemas/FindingChange'
computedAt:
type: string
format: date-time
DeltaSummary:
type: object
required:
- canShip
- riskDirection
- summary
properties:
canShip:
type: boolean
riskDirection:
type: string
enum: [improved, degraded, unchanged]
netBlockingChange:
type: integer
added:
type: integer
removed:
type: integer
modified:
type: integer
unchanged:
type: integer
criticalAdded:
type: integer
criticalRemoved:
type: integer
highAdded:
type: integer
highRemoved:
type: integer
mediumAdded:
type: integer
mediumRemoved:
type: integer
lowAdded:
type: integer
lowRemoved:
type: integer
summary:
type: string
FindingChange:
type: object
required:
- findingId
- changeType
- severity
properties:
findingId:
type: string
vulnId:
type: string
purl:
type: string
changeType:
type: string
enum: [added, removed, modified, unchanged]
severity:
type: string
enum: [critical, high, medium, low, info]
previousSeverity:
type: string
enum: [critical, high, medium, low, info]
isBlocking:
type: boolean
wasBlocking:
type: boolean
CanShipResponse:
type: object
required:
- comparisonId
- canShip
- reason
properties:
comparisonId:
type: string
canShip:
type: boolean
reason:
type: string
blockingFindings:
type: integer
newBlockingFindings:
type: integer
DeltaVerdictResponse:
type: object
required:
- comparisonId
- baseVerdict
- targetVerdict
properties:
comparisonId:
type: string
baseVerdict:
type: string
targetVerdict:
type: string
verdictChanged:
type: boolean
direction:
type: string
enum: [improved, degraded, unchanged]
policyViolations:
type: array
items:
type: string
# Baseline Schemas
BaselineRecommendationsResponse:
type: object
required:
- artifactDigest
- recommendations
properties:
artifactDigest:
type: string
recommendations:
type: array
items:
$ref: '#/components/schemas/BaselineRecommendation'
totalCount:
type: integer
BaselineRecommendation:
type: object
required:
- digest
- score
- reason
properties:
digest:
type: string
score:
type: number
format: double
reason:
type: string
scanDate:
type: string
format: date-time
findingCount:
type: integer
criticalCount:
type: integer
highCount:
type: integer
BaselineRationaleResponse:
type: object
required:
- baseDigest
- headDigest
- rationale
properties:
baseDigest:
type: string
headDigest:
type: string
rationale:
type: string
score:
type: number
format: double
factors:
type: array
items:
$ref: '#/components/schemas/RationaleFactor'
RationaleFactor:
type: object
required:
- name
- weight
- value
properties:
name:
type: string
weight:
type: number
format: double
value:
type: number
format: double
description:
type: string
# Actionables Schemas
ActionablesResponse:
type: object
required:
- actionables
- totalCount
properties:
actionables:
type: array
items:
$ref: '#/components/schemas/Actionable'
totalCount:
type: integer
criticalCount:
type: integer
highCount:
type: integer
Actionable:
type: object
required:
- id
- priority
- actionType
- summary
properties:
id:
type: string
findingId:
type: string
vulnId:
type: string
purl:
type: string
priority:
type: string
enum: [critical, high, medium, low]
actionType:
type: string
enum: [upgrade, patch, replace, configure, accept_risk, investigate]
summary:
type: string
details:
type: string
targetVersion:
type: string
description: Recommended version to upgrade to
effort:
type: string
enum: [trivial, low, medium, high, complex]
confidence:
type: number
format: double
minimum: 0
maximum: 1
# Counterfactual Schemas
CounterfactualRequest:
type: object
required:
- scanId
- scenarios
properties:
scanId:
type: string
findingId:
type: string
description: Optional - analyze specific finding only
scenarios:
type: array
items:
$ref: '#/components/schemas/CounterfactualScenario'
minItems: 1
maxItems: 10
CounterfactualScenario:
type: object
required:
- id
- changes
properties:
id:
type: string
description:
type: string
changes:
type: array
items:
$ref: '#/components/schemas/PolicyChange'
PolicyChange:
type: object
required:
- type
properties:
type:
type: string
enum: [add_vex, remove_vex, change_severity_threshold, add_exception, remove_exception]
vulnId:
type: string
purl:
type: string
vexStatement:
type: string
enum: [not_affected, affected, fixed, under_investigation]
justification:
type: string
threshold:
type: string
enum: [critical, high, medium, low]
CounterfactualResponse:
type: object
required:
- scanId
- scenarios
properties:
scanId:
type: string
findingId:
type: string
scenarios:
type: array
items:
$ref: '#/components/schemas/CounterfactualResult'
CounterfactualResult:
type: object
required:
- scenarioId
- originalVerdict
- newVerdict
- impactSummary
properties:
scenarioId:
type: string
originalVerdict:
type: string
newVerdict:
type: string
verdictChanged:
type: boolean
impactSummary:
type: string
findingsAffected:
type: integer
blockingFindingsRemoved:
type: integer
blockingFindingsAdded:
type: integer
FindingCounterfactualResponse:
type: object
required:
- findingId
- currentStatus
- scenarios
properties:
findingId:
type: string
vulnId:
type: string
purl:
type: string
currentStatus:
type: string
isBlocking:
type: boolean
scenarios:
type: array
items:
$ref: '#/components/schemas/FindingScenarioResult'
FindingScenarioResult:
type: object
required:
- scenario
- wouldBeBlocking
- impactDescription
properties:
scenario:
type: string
wouldBeBlocking:
type: boolean
newStatus:
type: string
impactDescription:
type: string
ScanCounterfactualSummary:
type: object
required:
- scanId
- totalFindings
- blockingFindings
properties:
scanId:
type: string
totalFindings:
type: integer
blockingFindings:
type: integer
wouldPassWithVex:
type: integer
description: Findings that would pass if VEX statements were added
wouldPassWithException:
type: integer
description: Findings that would pass if exceptions were added
topRecommendations:
type: array
items:
type: string
# Evidence Schemas
DeltaEvidenceResponse:
type: object
required:
- comparisonId
- baseEvidence
- targetEvidence
properties:
comparisonId:
type: string
baseEvidence:
$ref: '#/components/schemas/SnapshotEvidence'
targetEvidence:
$ref: '#/components/schemas/SnapshotEvidence'
deltaHash:
type: string
SnapshotEvidence:
type: object
required:
- digest
properties:
digest:
type: string
sbomHash:
type: string
vulnHash:
type: string
policyHash:
type: string
scanDate:
type: string
format: date-time
FindingEvidenceResponse:
type: object
required:
- findingId
properties:
findingId:
type: string
vulnId:
type: string
purl:
type: string
reachability:
$ref: '#/components/schemas/EvidenceSection'
vex:
$ref: '#/components/schemas/EvidenceSection'
advisory:
$ref: '#/components/schemas/EvidenceSection'
EvidenceSection:
type: object
properties:
data:
type: object
hash:
type: string
source:
type: string
AttestationChainResponse:
type: object
required:
- comparisonId
- attestations
properties:
comparisonId:
type: string
attestations:
type: array
items:
$ref: '#/components/schemas/Attestation'
chainValid:
type: boolean
rootAttestation:
type: string
Attestation:
type: object
required:
- id
- type
- subject
- createdAt
properties:
id:
type: string
type:
type: string
subject:
type: string
predicateType:
type: string
createdAt:
type: string
format: date-time
signature:
type: string
isValid:
type: boolean
ProblemDetails:
type: object
properties:
type:
type: string
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string