# Proof Chain API Reference > **Version**: 1.0.0 > **OpenAPI Spec**: [`proofs-openapi.yaml`](./proofs-openapi.yaml) The Proof Chain API provides endpoints for creating and verifying cryptographic proof bundles that link SBOM entries to vulnerability assessments through attestable DSSE envelopes. --- ## Overview The proof chain creates an auditable, cryptographically-verifiable trail from vulnerability evidence through policy reasoning to VEX verdicts. Each component is signed with DSSE envelopes and aggregated into a merkle-rooted proof spine. ### Proof Chain Components | Component | Predicate Type | Purpose | |-----------|----------------|---------| | **Evidence** | `evidence.stella/v1` | Raw findings from scanners/feeds | | **Reasoning** | `reasoning.stella/v1` | Policy evaluation trace | | **VEX Verdict** | `cdx-vex.stella/v1` | Final VEX status determination | | **Proof Spine** | `proofspine.stella/v1` | Merkle aggregation of all components | | **Verdict Receipt** | `verdict.stella/v1` | Human-readable verification receipt | ### Content-Addressed IDs All proof chain components use content-addressed identifiers: ``` Format: sha256:<64-hex-chars> Example: sha256:e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6... ``` IDs are computed by: 1. Canonicalizing the JSON payload (RFC 8785/JCS) 2. Computing SHA-256 hash 3. Prefixing with `sha256:` --- ## Authentication All endpoints require authentication via: - **Bearer Token**: Authority-issued OpToken with appropriate scopes - **mTLS**: Mutual TLS with client certificate (service-to-service) Required scopes: - `proofs.read` - Read proof bundles and receipts - `proofs.write` - Create proof spines - `anchors.manage` - Manage trust anchors - `proofs.verify` - Perform verification --- ## Endpoints ### Proofs #### POST /proofs/{entry}/spine Create a proof spine for an SBOM entry. **Parameters:** - `entry` (path, required): SBOMEntryID in format `sha256::pkg:` **Request Body:** ```json { "evidenceIds": ["sha256:e7f8a9b0..."], "reasoningId": "sha256:f0e1d2c3...", "vexVerdictId": "sha256:d4c5b6a7...", "policyVersion": "v1.2.3" } ``` **Response (201 Created):** ```json { "proofBundleId": "sha256:1a2b3c4d...", "receiptUrl": "/proofs/sha256:abc:pkg:npm/lodash@4.17.21/receipt" } ``` **Errors:** - `400 Bad Request`: Invalid SBOM entry ID format - `404 Not Found`: Evidence, reasoning, or VEX verdict not found - `422 Unprocessable Entity`: Validation error --- #### GET /proofs/{entry}/spine Get the proof spine for an SBOM entry. **Parameters:** - `entry` (path, required): SBOMEntryID **Response (200 OK):** ```json { "sbomEntryId": "sha256:abc123:pkg:npm/lodash@4.17.21", "proofBundleId": "sha256:1a2b3c4d...", "evidenceIds": ["sha256:e7f8a9b0..."], "reasoningId": "sha256:f0e1d2c3...", "vexVerdictId": "sha256:d4c5b6a7...", "policyVersion": "v1.2.3", "createdAt": "2025-12-17T10:00:00Z" } ``` --- #### GET /proofs/{entry}/receipt Get the verification receipt for an SBOM entry's proof spine. **Response (200 OK):** ```json { "graphRevisionId": "grv_sha256:9f8e7d6c...", "findingKey": { "sbomEntryId": "sha256:abc123:pkg:npm/lodash@4.17.21", "vulnerabilityId": "CVE-2025-1234" }, "rule": { "id": "critical-vuln-block", "version": "v1.0.0" }, "decision": { "verdict": "pass", "severity": "none", "reasoning": "Not affected - vulnerable code not present" }, "createdAt": "2025-12-17T10:00:00Z", "verified": true } ``` --- #### GET /proofs/{entry}/vex Get the VEX attestation for an SBOM entry. **Response (200 OK):** ```json { "sbomEntryId": "sha256:abc123:pkg:npm/lodash@4.17.21", "vulnerabilityId": "CVE-2025-1234", "status": "not_affected", "justification": "vulnerable_code_not_present", "policyVersion": "v1.2.3", "reasoningId": "sha256:f0e1d2c3...", "vexVerdictId": "sha256:d4c5b6a7..." } ``` --- ### Trust Anchors #### GET /anchors List all configured trust anchors. **Response (200 OK):** ```json { "anchors": [ { "id": "anchor-001", "keyId": "sha256:abc123...", "algorithm": "ECDSA-P256", "status": "active", "createdAt": "2025-01-01T00:00:00Z" } ] } ``` --- #### POST /anchors Create a new trust anchor. **Request Body:** ```json { "keyId": "sha256:abc123...", "algorithm": "ECDSA-P256", "publicKey": "-----BEGIN PUBLIC KEY-----\n..." } ``` **Response (201 Created):** ```json { "id": "anchor-002", "keyId": "sha256:abc123...", "algorithm": "ECDSA-P256", "status": "active", "createdAt": "2025-12-17T10:00:00Z" } ``` --- #### DELETE /anchors/{anchorId} Delete (revoke) a trust anchor. **Response:** `204 No Content` --- ### Verification #### POST /verify Perform full verification of a proof bundle. **Request Body:** ```json { "proofBundleId": "sha256:1a2b3c4d...", "checkRekor": true, "anchorIds": ["anchor-001"] } ``` **Response (200 OK):** ```json { "proofBundleId": "sha256:1a2b3c4d...", "verified": true, "checks": { "signatureValid": true, "idRecomputed": true, "merklePathValid": true, "rekorInclusionValid": true }, "errors": [], "verifiedAt": "2025-12-17T10:00:00Z" } ``` **Verification Steps:** 1. **Signature Verification**: Verify DSSE envelope signatures against trust anchors 2. **ID Recomputation**: Recompute content-addressed IDs and compare 3. **Merkle Path Verification**: Verify proof bundle merkle tree construction 4. **Rekor Inclusion**: Verify transparency log inclusion proof (if enabled) --- #### POST /verify/batch Verify multiple proof bundles in a single request. **Request Body:** ```json { "bundles": [ { "proofBundleId": "sha256:1a2b3c4d...", "checkRekor": true }, { "proofBundleId": "sha256:5e6f7g8h...", "checkRekor": false } ] } ``` **Response (200 OK):** ```json { "results": [ { "proofBundleId": "sha256:1a2b3c4d...", "verified": true, "checks": {...} }, { "proofBundleId": "sha256:5e6f7g8h...", "verified": false, "errors": ["..."] } ] } ``` --- ## Error Handling All errors follow RFC 7807 Problem Details format: ```json { "title": "Validation Error", "detail": "Evidence ID sha256:abc... not found", "status": 422, "errors": { "evidenceIds[0]": ["Evidence not found"] } } ``` ### Common Error Codes | Status | Meaning | |--------|---------| | 400 | Invalid request format or parameters | | 401 | Authentication required | | 403 | Insufficient permissions | | 404 | Resource not found | | 409 | Conflict (e.g., anchor already exists) | | 422 | Validation error | | 500 | Internal server error | --- ## Offline Verification For air-gapped environments, verification can be performed without Rekor: ```json { "proofBundleId": "sha256:1a2b3c4d...", "checkRekor": false } ``` This skips Rekor inclusion proof verification but still performs: - DSSE signature verification - Content-addressed ID recomputation - Merkle path verification --- ## Related Documentation - [Proof Chain Predicates](../modules/attestor/architecture.md#predicate-types) - DSSE predicate type specifications - [Content-Addressed IDs](../modules/attestor/architecture.md#content-addressed-identifier-formats) - ID generation rules - [Attestor Architecture](../modules/attestor/architecture.md) - Full attestor module documentation