Files
git.stella-ops.org/docs/schemas/excititor-chunk-api.openapi.yaml
StellaOps Bot 4042fc2184
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
release-manifest-verify / verify (push) Has been cancelled
Add unit tests for PackRunAttestation and SealedInstallEnforcer
- Implement comprehensive tests for PackRunAttestationService, covering attestation generation, verification, and event emission.
- Add tests for SealedInstallEnforcer to validate sealed install requirements and enforcement logic.
- Introduce a MonacoLoaderService stub for testing purposes to prevent Monaco workers/styles from loading during Karma runs.
2025-12-06 22:25:30 +02:00

674 lines
17 KiB
YAML

openapi: 3.1.0
info:
title: StellaOps Excititor Chunk API
version: 1.0.0
description: |
API for VEX document chunked ingestion and processing in Excititor service.
Unblocks EXCITITOR-DOCS-0001, EXCITITOR-ENG-0001, EXCITITOR-OPS-0001 (3 tasks).
contact:
name: StellaOps Platform Team
url: https://stella-ops.org
license:
name: AGPL-3.0-or-later
url: https://www.gnu.org/licenses/agpl-3.0.html
servers:
- url: /api/v1/excititor
description: Excititor API base path
tags:
- name: chunks
description: Chunked document upload operations
- name: vex
description: VEX document ingestion
- name: processing
description: Document processing status
- name: health
description: Service health endpoints
paths:
/chunks/initiate:
post:
operationId: initiateChunkedUpload
summary: Initiate a chunked upload session
description: Start a new chunked upload session for large VEX documents
tags:
- chunks
security:
- bearerAuth: []
- oauth2: [excititor:write]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChunkedUploadInitRequest'
responses:
'201':
description: Upload session created
content:
application/json:
schema:
$ref: '#/components/schemas/ChunkedUploadSession'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
/chunks/{session_id}:
put:
operationId: uploadChunk
summary: Upload a chunk
description: Upload a single chunk for an active upload session
tags:
- chunks
security:
- bearerAuth: []
- oauth2: [excititor:write]
parameters:
- name: session_id
in: path
required: true
schema:
type: string
format: uuid
- name: X-Chunk-Index
in: header
required: true
schema:
type: integer
minimum: 0
- name: X-Chunk-Digest
in: header
required: true
schema:
type: string
pattern: '^sha256:[a-f0-9]{64}$'
- name: Content-Range
in: header
required: false
schema:
type: string
requestBody:
required: true
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
'200':
description: Chunk uploaded successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ChunkUploadResult'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: Chunk already uploaded or out of sequence
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
get:
operationId: getUploadSessionStatus
summary: Get upload session status
description: Retrieve the current status of a chunked upload session
tags:
- chunks
security:
- bearerAuth: []
- oauth2: [excititor:read]
parameters:
- name: session_id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Upload session status
content:
application/json:
schema:
$ref: '#/components/schemas/ChunkedUploadSession'
'404':
$ref: '#/components/responses/NotFound'
delete:
operationId: cancelUploadSession
summary: Cancel upload session
description: Cancel an active upload session and clean up partial data
tags:
- chunks
security:
- bearerAuth: []
- oauth2: [excititor:write]
parameters:
- name: session_id
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Session cancelled
'404':
$ref: '#/components/responses/NotFound'
/chunks/{session_id}/complete:
post:
operationId: completeChunkedUpload
summary: Complete chunked upload
description: Finalize a chunked upload and trigger VEX processing
tags:
- chunks
security:
- bearerAuth: []
- oauth2: [excititor:write]
parameters:
- name: session_id
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChunkedUploadCompleteRequest'
responses:
'200':
description: Upload completed, processing started
content:
application/json:
schema:
$ref: '#/components/schemas/VexIngestionJob'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: Missing chunks or invalid digest
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
/vex/ingest:
post:
operationId: ingestVexDocument
summary: Ingest a VEX document
description: Ingest a small VEX document directly (for documents < 10MB)
tags:
- vex
security:
- bearerAuth: []
- oauth2: [excititor:write]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VexIngestionRequest'
application/vnd.openvex+json:
schema:
type: object
application/vnd.csaf+json:
schema:
type: object
application/vnd.cyclonedx+json:
schema:
type: object
responses:
'202':
description: VEX document accepted for processing
content:
application/json:
schema:
$ref: '#/components/schemas/VexIngestionJob'
'400':
$ref: '#/components/responses/BadRequest'
'413':
description: Payload too large - use chunked upload
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
/vex/jobs/{job_id}:
get:
operationId: getIngestionJobStatus
summary: Get ingestion job status
description: Retrieve the status of a VEX ingestion job
tags:
- processing
security:
- bearerAuth: []
- oauth2: [excititor:read]
parameters:
- name: job_id
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Job status
content:
application/json:
schema:
$ref: '#/components/schemas/VexIngestionJob'
'404':
$ref: '#/components/responses/NotFound'
/vex/jobs:
get:
operationId: listIngestionJobs
summary: List ingestion jobs
description: List VEX ingestion jobs with filtering and pagination
tags:
- processing
security:
- bearerAuth: []
- oauth2: [excititor:read]
parameters:
- name: status
in: query
schema:
type: string
enum: [pending, processing, completed, failed]
- name: created_after
in: query
schema:
type: string
format: date-time
- name: created_before
in: query
schema:
type: string
format: date-time
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
- name: page_size
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
responses:
'200':
description: List of jobs
content:
application/json:
schema:
$ref: '#/components/schemas/VexIngestionJobList'
/health:
get:
operationId: healthCheck
summary: Health check
description: Service health check endpoint
tags:
- health
security: []
responses:
'200':
description: Service healthy
content:
application/json:
schema:
$ref: '#/components/schemas/HealthStatus'
'503':
description: Service unhealthy
content:
application/json:
schema:
$ref: '#/components/schemas/HealthStatus'
/health/ready:
get:
operationId: readinessCheck
summary: Readiness check
description: Kubernetes readiness probe endpoint
tags:
- health
security: []
responses:
'200':
description: Service ready
'503':
description: Service not ready
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
oauth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: /oauth/token
scopes:
excititor:read: Read VEX data
excititor:write: Write VEX data
schemas:
ChunkedUploadInitRequest:
type: object
required:
- filename
- total_size
- content_type
properties:
filename:
type: string
description: Original filename
total_size:
type: integer
minimum: 1
description: Total file size in bytes
content_type:
type: string
enum:
- application/json
- application/vnd.openvex+json
- application/vnd.csaf+json
- application/vnd.cyclonedx+json
expected_digest:
type: string
pattern: '^sha256:[a-f0-9]{64}$'
description: Expected SHA-256 digest of complete file
chunk_size:
type: integer
minimum: 1048576
maximum: 104857600
default: 10485760
description: Chunk size in bytes (1MB - 100MB, default 10MB)
metadata:
type: object
additionalProperties: true
description: Optional metadata for the upload
ChunkedUploadSession:
type: object
required:
- session_id
- status
- created_at
properties:
session_id:
type: string
format: uuid
status:
type: string
enum: [active, completed, cancelled, expired]
filename:
type: string
total_size:
type: integer
chunk_size:
type: integer
total_chunks:
type: integer
uploaded_chunks:
type: array
items:
type: integer
chunks_remaining:
type: integer
bytes_uploaded:
type: integer
created_at:
type: string
format: date-time
expires_at:
type: string
format: date-time
upload_url:
type: string
format: uri
description: URL for chunk uploads
ChunkUploadResult:
type: object
required:
- chunk_index
- received
properties:
chunk_index:
type: integer
received:
type: boolean
digest_verified:
type: boolean
bytes_received:
type: integer
chunks_remaining:
type: integer
ChunkedUploadCompleteRequest:
type: object
required:
- final_digest
properties:
final_digest:
type: string
pattern: '^sha256:[a-f0-9]{64}$'
description: SHA-256 digest of reassembled file
process_immediately:
type: boolean
default: true
description: Start processing immediately after assembly
VexIngestionRequest:
type: object
required:
- document
properties:
document:
type: object
description: VEX document (OpenVEX, CSAF, or CycloneDX format)
format:
type: string
enum: [openvex, csaf, cyclonedx, auto]
default: auto
source:
type: string
description: Source identifier for the VEX document
priority:
type: string
enum: [low, normal, high]
default: normal
metadata:
type: object
additionalProperties: true
VexIngestionJob:
type: object
required:
- job_id
- status
- created_at
properties:
job_id:
type: string
format: uuid
status:
type: string
enum: [pending, validating, processing, indexing, completed, failed]
format_detected:
type: string
enum: [openvex, csaf, cyclonedx, unknown]
created_at:
type: string
format: date-time
started_at:
type: string
format: date-time
completed_at:
type: string
format: date-time
document_digest:
type: string
pattern: '^sha256:[a-f0-9]{64}$'
statements_count:
type: integer
description: Number of VEX statements processed
products_count:
type: integer
description: Number of products affected
vulnerabilities_count:
type: integer
description: Number of vulnerabilities referenced
errors:
type: array
items:
$ref: '#/components/schemas/ProcessingError'
warnings:
type: array
items:
type: string
result_ref:
type: string
description: Reference to processing result
VexIngestionJobList:
type: object
required:
- jobs
- total_count
properties:
jobs:
type: array
items:
$ref: '#/components/schemas/VexIngestionJob'
total_count:
type: integer
page:
type: integer
page_size:
type: integer
next_page_token:
type: string
ProcessingError:
type: object
required:
- code
- message
properties:
code:
type: string
message:
type: string
location:
type: string
description: JSON path to error location
details:
type: object
additionalProperties: true
HealthStatus:
type: object
required:
- status
properties:
status:
type: string
enum: [healthy, degraded, unhealthy]
version:
type: string
uptime_seconds:
type: integer
checks:
type: array
items:
type: object
properties:
name:
type: string
status:
type: string
enum: [pass, warn, fail]
message:
type: string
ProblemDetails:
type: object
required:
- type
- title
- status
properties:
type:
type: string
format: uri
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string
format: uri
errors:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
responses:
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
TooManyRequests:
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
headers:
Retry-After:
schema:
type: integer
description: Seconds until rate limit resets