doctor enhancements, setup, enhancements, ui functionality and design consolidation and , test projects fixes , product advisory attestation/rekor and delta verfications enhancements
This commit is contained in:
343
docs/api/artifact-store-api.yaml
Normal file
343
docs/api/artifact-store-api.yaml
Normal file
@@ -0,0 +1,343 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Stella Ops Artifact Store API
|
||||
description: |
|
||||
Unified artifact storage API with bom-ref support.
|
||||
|
||||
Sprint: SPRINT_20260118_017_Evidence_artifact_store_unification (AS-005, AS-007)
|
||||
|
||||
## Overview
|
||||
|
||||
The Artifact Store API provides unified storage and retrieval of evidence artifacts
|
||||
(SBOMs, VEX, DSSE envelopes, Rekor proofs) using a bom-ref based path convention.
|
||||
|
||||
## Path Convention
|
||||
|
||||
Artifacts are stored at: `/artifacts/{bom-ref-encoded}/{serialNumber}/{artifactId}.json`
|
||||
|
||||
Where:
|
||||
- `bom-ref-encoded`: URL-safe base64 encoded PURL
|
||||
- `serialNumber`: CycloneDX serial number (URN UUID)
|
||||
- `artifactId`: Unique artifact identifier
|
||||
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: Stella Ops Team
|
||||
license:
|
||||
name: AGPL-3.0-or-later
|
||||
|
||||
servers:
|
||||
- url: /api/v1
|
||||
description: API v1
|
||||
|
||||
tags:
|
||||
- name: Artifacts
|
||||
description: Artifact storage and retrieval operations
|
||||
- name: Evidence
|
||||
description: Evidence submission operations
|
||||
|
||||
paths:
|
||||
/evidence:
|
||||
post:
|
||||
operationId: submitEvidence
|
||||
tags: [Evidence]
|
||||
summary: Submit evidence artifact
|
||||
description: |
|
||||
Ingests DSSE envelopes with SBOM references and stores in unified ArtifactStore.
|
||||
Extracts and validates bom_ref and cyclonedx_serial from the envelope.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/EvidenceSubmissionRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: Evidence stored successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ArtifactMetadata'
|
||||
'400':
|
||||
description: Invalid request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'409':
|
||||
description: Artifact already exists
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ArtifactMetadata'
|
||||
|
||||
/artifacts:
|
||||
get:
|
||||
operationId: listArtifacts
|
||||
tags: [Artifacts]
|
||||
summary: List artifacts by bom-ref
|
||||
description: |
|
||||
Returns paginated list of artifacts for a given bom-ref.
|
||||
Supports filtering by serial_number and time range.
|
||||
parameters:
|
||||
- name: bom_ref
|
||||
in: query
|
||||
required: true
|
||||
description: Package URL or component reference
|
||||
schema:
|
||||
type: string
|
||||
example: "pkg:docker/acme/api@sha256:abc123"
|
||||
- name: serial_number
|
||||
in: query
|
||||
required: false
|
||||
description: CycloneDX serial number filter
|
||||
schema:
|
||||
type: string
|
||||
example: "urn:uuid:12345678-1234-1234-1234-123456789012"
|
||||
- name: from
|
||||
in: query
|
||||
required: false
|
||||
description: Start date filter (ISO 8601)
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
- name: to
|
||||
in: query
|
||||
required: false
|
||||
description: End date filter (ISO 8601)
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
description: Maximum results per page (default 50, max 1000)
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 1000
|
||||
default: 50
|
||||
- name: continuation_token
|
||||
in: query
|
||||
required: false
|
||||
description: Token for pagination
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Artifacts retrieved successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ArtifactListResponse'
|
||||
|
||||
/artifacts/{artifact_id}:
|
||||
get:
|
||||
operationId: getArtifact
|
||||
tags: [Artifacts]
|
||||
summary: Get artifact by ID
|
||||
description: Returns artifact metadata and optionally content
|
||||
parameters:
|
||||
- name: artifact_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: include_content
|
||||
in: query
|
||||
required: false
|
||||
description: Include artifact content in response
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
responses:
|
||||
'200':
|
||||
description: Artifact retrieved
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ArtifactResponse'
|
||||
'404':
|
||||
description: Artifact not found
|
||||
|
||||
delete:
|
||||
operationId: deleteArtifact
|
||||
tags: [Artifacts]
|
||||
summary: Delete artifact (soft delete)
|
||||
description: Marks artifact as deleted without removing from storage
|
||||
parameters:
|
||||
- name: artifact_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'204':
|
||||
description: Artifact deleted
|
||||
'404':
|
||||
description: Artifact not found
|
||||
|
||||
/artifacts/{artifact_id}/content:
|
||||
get:
|
||||
operationId: getArtifactContent
|
||||
tags: [Artifacts]
|
||||
summary: Get artifact content
|
||||
description: Returns the raw artifact content
|
||||
parameters:
|
||||
- name: artifact_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: Artifact content
|
||||
content:
|
||||
application/octet-stream:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
application/vnd.dsse+json:
|
||||
schema:
|
||||
type: object
|
||||
application/vnd.cyclonedx+json:
|
||||
schema:
|
||||
type: object
|
||||
'404':
|
||||
description: Artifact not found
|
||||
|
||||
components:
|
||||
schemas:
|
||||
EvidenceSubmissionRequest:
|
||||
type: object
|
||||
required:
|
||||
- bom_ref
|
||||
properties:
|
||||
bom_ref:
|
||||
type: string
|
||||
description: Package URL or component reference
|
||||
example: "pkg:docker/acme/api@sha256:abc123def456"
|
||||
cyclonedx_serial:
|
||||
type: string
|
||||
description: CycloneDX serial number (URN UUID)
|
||||
example: "urn:uuid:12345678-1234-1234-1234-123456789012"
|
||||
dsse_uri:
|
||||
type: string
|
||||
description: URI to DSSE envelope (s3://, file://, https://)
|
||||
example: "s3://evidence-bucket/path/to/envelope.json"
|
||||
rekor_uuid:
|
||||
type: string
|
||||
description: Rekor log entry UUID
|
||||
example: "f1a2b3c4d5e6f7a8"
|
||||
content:
|
||||
type: string
|
||||
format: byte
|
||||
description: Base64-encoded artifact content (alternative to dsse_uri)
|
||||
content_type:
|
||||
type: string
|
||||
description: MIME type of content
|
||||
example: "application/vnd.dsse+json"
|
||||
metadata:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Additional metadata key-value pairs
|
||||
|
||||
ArtifactMetadata:
|
||||
type: object
|
||||
required:
|
||||
- artifact_id
|
||||
- bom_ref
|
||||
- storage_key
|
||||
- sha256
|
||||
- created_at
|
||||
properties:
|
||||
artifact_id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unique artifact identifier
|
||||
bom_ref:
|
||||
type: string
|
||||
description: Package URL or component reference
|
||||
serial_number:
|
||||
type: string
|
||||
nullable: true
|
||||
description: CycloneDX serial number
|
||||
storage_key:
|
||||
type: string
|
||||
description: Storage path for artifact
|
||||
content_type:
|
||||
type: string
|
||||
description: MIME type
|
||||
size_bytes:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Content size in bytes
|
||||
sha256:
|
||||
type: string
|
||||
description: SHA-256 hash of content
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Creation timestamp
|
||||
rekor_uuid:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Rekor log entry UUID if linked
|
||||
metadata:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Additional metadata
|
||||
|
||||
ArtifactListResponse:
|
||||
type: object
|
||||
required:
|
||||
- artifacts
|
||||
- total
|
||||
properties:
|
||||
artifacts:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ArtifactMetadata'
|
||||
total:
|
||||
type: integer
|
||||
description: Total matching artifacts
|
||||
continuation_token:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Token for next page
|
||||
|
||||
ArtifactResponse:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/ArtifactMetadata'
|
||||
- type: object
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
format: byte
|
||||
nullable: true
|
||||
description: Base64-encoded content (if include_content=true)
|
||||
|
||||
ErrorResponse:
|
||||
type: object
|
||||
required:
|
||||
- error
|
||||
- message
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
description: Error code
|
||||
message:
|
||||
type: string
|
||||
description: Human-readable error message
|
||||
details:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
description: Additional error details
|
||||
280
docs/api/gates-api.yaml
Normal file
280
docs/api/gates-api.yaml
Normal file
@@ -0,0 +1,280 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Stella Ops Gates API
|
||||
description: |
|
||||
Gate check API for unknowns queue integration.
|
||||
|
||||
Sprint: SPRINT_20260118_018_Unknowns_queue_enhancement (UQ-006)
|
||||
|
||||
## Overview
|
||||
|
||||
The Gates API provides endpoints to check if a component can pass through
|
||||
the release gate based on its unknowns status. It implements fail-closed
|
||||
semantics by default for HOT unknowns.
|
||||
|
||||
## Gate Decisions
|
||||
|
||||
- **pass**: No blocking unknowns, component may proceed
|
||||
- **warn**: Non-blocking unknowns present, proceed with caution
|
||||
- **block**: HOT unknowns, KEV items, or SLA breaches require resolution
|
||||
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: Stella Ops Team
|
||||
license:
|
||||
name: AGPL-3.0-or-later
|
||||
|
||||
servers:
|
||||
- url: /api/v1
|
||||
description: API v1
|
||||
|
||||
tags:
|
||||
- name: Gates
|
||||
description: Gate check operations for unknowns
|
||||
|
||||
paths:
|
||||
/gates/{bom_ref}:
|
||||
get:
|
||||
operationId: getGateStatus
|
||||
tags: [Gates]
|
||||
summary: Get gate check result for a component
|
||||
description: |
|
||||
Returns the current unknowns state and gate decision for a BOM reference.
|
||||
Results are cached for 30 seconds.
|
||||
parameters:
|
||||
- name: bom_ref
|
||||
in: path
|
||||
required: true
|
||||
description: URL-encoded BOM reference (PURL)
|
||||
schema:
|
||||
type: string
|
||||
example: pkg%3Anpm%2Flodash%404.17.21
|
||||
responses:
|
||||
'200':
|
||||
description: Gate status retrieved successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GateStatusResponse'
|
||||
'500':
|
||||
description: Internal server error
|
||||
|
||||
/gates/{bom_ref}/check:
|
||||
post:
|
||||
operationId: checkGate
|
||||
tags: [Gates]
|
||||
summary: Perform gate check for a component
|
||||
description: |
|
||||
Performs a fresh gate check with optional verdict proposal.
|
||||
Returns 403 if the gate is blocked.
|
||||
parameters:
|
||||
- name: bom_ref
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GateCheckRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Gate passed or warning
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GateCheckResponse'
|
||||
'403':
|
||||
description: Gate blocked
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GateCheckResponse'
|
||||
|
||||
/gates/{bom_ref}/exception:
|
||||
post:
|
||||
operationId: requestGateException
|
||||
tags: [Gates]
|
||||
summary: Request an exception to bypass the gate
|
||||
description: |
|
||||
Requests approval to bypass blocking unknowns.
|
||||
Exceptions are not auto-granted and require manual approval.
|
||||
parameters:
|
||||
- name: bom_ref
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ExceptionRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Exception granted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ExceptionResponse'
|
||||
'403':
|
||||
description: Exception denied
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ExceptionResponse'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
GateStatusResponse:
|
||||
type: object
|
||||
required:
|
||||
- bom_ref
|
||||
- state
|
||||
- gate_decision
|
||||
- checked_at
|
||||
properties:
|
||||
bom_ref:
|
||||
type: string
|
||||
description: BOM reference (PURL)
|
||||
example: "pkg:npm/lodash@4.17.21"
|
||||
state:
|
||||
type: string
|
||||
enum: [resolved, pending, under_review, escalated, rejected]
|
||||
description: Aggregate state across all unknowns
|
||||
verdict_hash:
|
||||
type: string
|
||||
nullable: true
|
||||
description: SHA-256 hash of verdict if resolved
|
||||
example: "sha256:abc123..."
|
||||
unknowns:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UnknownDto'
|
||||
gate_decision:
|
||||
type: string
|
||||
enum: [pass, warn, block]
|
||||
description: Gate decision
|
||||
checked_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: When the check was performed
|
||||
|
||||
UnknownDto:
|
||||
type: object
|
||||
required:
|
||||
- unknown_id
|
||||
- band
|
||||
- state
|
||||
properties:
|
||||
unknown_id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unknown entry ID
|
||||
cve_id:
|
||||
type: string
|
||||
nullable: true
|
||||
description: CVE identifier if applicable
|
||||
example: "CVE-2026-1234"
|
||||
band:
|
||||
type: string
|
||||
enum: [hot, warm, cold]
|
||||
description: Priority band based on score
|
||||
sla_remaining_hours:
|
||||
type: number
|
||||
nullable: true
|
||||
description: Hours remaining before SLA breach
|
||||
state:
|
||||
type: string
|
||||
enum: [pending, under_review, escalated, resolved, rejected]
|
||||
description: Current processing state
|
||||
|
||||
GateCheckRequest:
|
||||
type: object
|
||||
properties:
|
||||
proposed_verdict:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Proposed VEX verdict (e.g., "not_affected")
|
||||
example: "not_affected"
|
||||
|
||||
GateCheckResponse:
|
||||
type: object
|
||||
required:
|
||||
- bom_ref
|
||||
- decision
|
||||
- state
|
||||
- checked_at
|
||||
properties:
|
||||
bom_ref:
|
||||
type: string
|
||||
decision:
|
||||
type: string
|
||||
enum: [pass, warn, block]
|
||||
state:
|
||||
type: string
|
||||
blocking_unknown_ids:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
reason:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Human-readable reason for decision
|
||||
exception_granted:
|
||||
type: boolean
|
||||
description: Whether an exception was granted
|
||||
exception_ref:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Exception reference if granted
|
||||
checked_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
ExceptionRequest:
|
||||
type: object
|
||||
required:
|
||||
- justification
|
||||
properties:
|
||||
unknown_ids:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uuid
|
||||
description: IDs of unknowns to bypass
|
||||
justification:
|
||||
type: string
|
||||
description: Business justification for exception
|
||||
minLength: 10
|
||||
|
||||
ExceptionResponse:
|
||||
type: object
|
||||
required:
|
||||
- granted
|
||||
- requested_at
|
||||
properties:
|
||||
granted:
|
||||
type: boolean
|
||||
description: Whether exception was granted
|
||||
exception_ref:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Exception reference for tracking
|
||||
denial_reason:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Reason if not granted
|
||||
expires_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: When exception expires
|
||||
requested_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: When request was made
|
||||
Reference in New Issue
Block a user