openapi: 3.1.0 info: title: StellaOps Evidence & Decision API description: | REST API for evidence retrieval and decision recording. Sprint: SPRINT_3602_0001_0001 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: [] 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' 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