# Triage Evidence Export API Reference Version: 1.0 Sprint: SPRINT_9200_0001_0002, SPRINT_9200_0001_0003 Status: Stable ## Overview The Triage Evidence Export API provides endpoints for downloading complete evidence packages as archives. These endpoints support both individual finding exports and batch exports for entire scan runs. ## Base URL ``` /api/v1/triage ``` ## Endpoints ### Export Finding Evidence Bundle Downloads a complete evidence bundle for a single finding as a ZIP or TAR.GZ archive. ``` GET /findings/{findingId}/evidence/export ``` #### Path Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `findingId` | string | Yes | Finding identifier | #### Query Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `format` | string | `zip` | Archive format: `zip`, `tar.gz`, `targz`, `tgz` | #### Response Headers | Header | Description | |--------|-------------| | `Content-Type` | `application/zip` or `application/gzip` | | `Content-Disposition` | `attachment; filename="evidence-{findingId}.zip"` | | `X-Archive-Digest` | SHA-256 digest of the archive: `sha256:{digest}` | #### Response Codes | Code | Description | |------|-------------| | 200 | Success - archive stream returned | | 400 | Invalid format specified | | 404 | Finding not found | #### Example Request ```bash curl -X GET \ "https://api.stellaops.example/api/v1/triage/findings/f-abc123/evidence/export?format=zip" \ -H "Authorization: Bearer " \ -o evidence-f-abc123.zip ``` #### Example Response Binary stream of the archive file. ### Get Unified Evidence Retrieves the unified evidence package as JSON (not downloadable archive). ``` GET /findings/{findingId}/evidence ``` #### Path Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `findingId` | string | Yes | Finding identifier | #### Query Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `includeSbom` | boolean | `true` | Include SBOM evidence | | `includeReachability` | boolean | `true` | Include reachability evidence | | `includeVex` | boolean | `true` | Include VEX claims | | `includeAttestations` | boolean | `true` | Include attestations | | `includeDeltas` | boolean | `true` | Include delta evidence | | `includePolicy` | boolean | `true` | Include policy evidence | | `includeReplayCommand` | boolean | `true` | Include replay command | #### Response Headers | Header | Description | |--------|-------------| | `ETag` | Content-addressed cache key: `"{cacheKey}"` | | `Cache-Control` | `private, max-age=300` | #### Response Codes | Code | Description | |------|-------------| | 200 | Success - evidence returned | | 304 | Not Modified (ETag match) | | 404 | Finding not found | #### Example Request ```bash curl -X GET \ "https://api.stellaops.example/api/v1/triage/findings/f-abc123/evidence" \ -H "Authorization: Bearer " \ -H "If-None-Match: \"sha256:abc123...\"" ``` #### Example Response (200 OK) ```json { "findingId": "f-abc123", "cveId": "CVE-2024-1234", "componentPurl": "pkg:npm/lodash@4.17.15", "sbom": { "format": "cyclonedx", "version": "1.5", "documentUri": "/sboms/sha256:abc123", "digest": "sha256:abc123...", "component": { "purl": "pkg:npm/lodash@4.17.15", "name": "lodash", "version": "4.17.15", "ecosystem": "npm" } }, "reachability": { "subgraphId": "sg-xyz789", "status": "reachable", "confidence": 0.95, "method": "static", "entryPoints": [...] }, "vexClaims": [...], "attestations": [...], "deltas": {...}, "policy": {...}, "manifests": { "artifactDigest": "sha256:a1b2c3...", "manifestHash": "sha256:def456...", "feedSnapshotHash": "sha256:feed789...", "policyHash": "sha256:policy321..." }, "verification": { "status": "verified", "hashesVerified": true, "attestationsVerified": true, "evidenceComplete": true }, "replayCommand": "stella scan replay --artifact sha256:a1b2c3... --manifest sha256:def456... --feeds sha256:feed789... --policy sha256:policy321...", "shortReplayCommand": "stella replay snapshot --verdict V-12345", "evidenceBundleUrl": "/v1/triage/findings/f-abc123/evidence/export", "generatedAt": "2025-01-15T10:30:00Z", "cacheKey": "sha256:unique123..." } ``` ### Get Replay Command Retrieves the replay command for a finding. ``` GET /findings/{findingId}/replay-command ``` #### Path Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `findingId` | string | Yes | Finding identifier | #### Query Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `shells` | string[] | `["bash"]` | Target shells: `bash`, `powershell`, `cmd` | | `includeOffline` | boolean | `false` | Include offline replay variant | | `generateBundle` | boolean | `false` | Generate evidence bundle | #### Response Codes | Code | Description | |------|-------------| | 200 | Success - replay command returned | | 404 | Finding not found | #### Example Response ```json { "findingId": "f-abc123", "commands": { "bash": "stella scan replay --artifact sha256:a1b2c3... --manifest sha256:def456... --feeds sha256:feed789... --policy sha256:policy321...", "powershell": "stella scan replay --artifact sha256:a1b2c3... --manifest sha256:def456... --feeds sha256:feed789... --policy sha256:policy321..." }, "shortCommand": "stella replay snapshot --verdict V-12345", "inputHashes": { "artifactDigest": "sha256:a1b2c3...", "manifestHash": "sha256:def456...", "feedSnapshotHash": "sha256:feed789...", "policyHash": "sha256:policy321..." }, "bundleUrl": "/v1/triage/findings/f-abc123/evidence/export", "generatedAt": "2025-01-15T10:30:00Z" } ``` ### Get Scan Replay Command Retrieves the replay command for an entire scan. ``` GET /scans/{scanId}/replay-command ``` #### Path Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `scanId` | string | Yes | Scan identifier | #### Query Parameters Same as finding replay command endpoint. #### Response Codes | Code | Description | |------|-------------| | 200 | Success - replay command returned | | 404 | Scan not found | ## ETag Caching The unified evidence endpoint supports HTTP caching via ETag/If-None-Match: 1. **Initial request**: Returns evidence with `ETag` header 2. **Subsequent requests**: Include `If-None-Match: "{etag}"` header 3. **If unchanged**: Returns `304 Not Modified` (no body) 4. **If changed**: Returns `200 OK` with new evidence and ETag Example flow: ```bash # Initial request curl -i "https://api.stellaops.example/api/v1/triage/findings/f-abc123/evidence" # Response: 200 OK, ETag: "sha256:abc123..." # Conditional request curl -i "https://api.stellaops.example/api/v1/triage/findings/f-abc123/evidence" \ -H 'If-None-Match: "sha256:abc123..."' # Response: 304 Not Modified (if unchanged) ``` ## Archive Integrity To verify downloaded archives: ```bash # Get expected digest from header EXPECTED=$(curl -sI ".../evidence/export" | grep X-Archive-Digest | cut -d: -f2-) # Download and verify curl -o evidence.zip ".../evidence/export" ACTUAL=$(sha256sum evidence.zip | cut -d' ' -f1) if [ "sha256:$ACTUAL" = "$EXPECTED" ]; then echo "Archive verified" else echo "Verification failed!" exit 1 fi ``` ## See Also - [Evidence Bundle Format Specification](../modules/cli/guides/commands/evidence-bundle-format.md) - [stella scan replay Command Reference](../modules/cli/guides/commands/scan-replay.md) - [Unified Evidence Model](./evidence-api-reference.md)