Files
git.stella-ops.org/docs/api/proofs.md
master 8bbfe4d2d2 feat(rate-limiting): Implement core rate limiting functionality with configuration, decision-making, metrics, middleware, and service registration
- Add RateLimitConfig for configuration management with YAML binding support.
- Introduce RateLimitDecision to encapsulate the result of rate limit checks.
- Implement RateLimitMetrics for OpenTelemetry metrics tracking.
- Create RateLimitMiddleware for enforcing rate limits on incoming requests.
- Develop RateLimitService to orchestrate instance and environment rate limit checks.
- Add RateLimitServiceCollectionExtensions for dependency injection registration.
2025-12-17 18:02:37 +02:00

7.2 KiB

Proof Chain API Reference

Version: 1.0.0
OpenAPI Spec: 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:<hash>:pkg:<purl>

Request Body:

{
  "evidenceIds": ["sha256:e7f8a9b0..."],
  "reasoningId": "sha256:f0e1d2c3...",
  "vexVerdictId": "sha256:d4c5b6a7...",
  "policyVersion": "v1.2.3"
}

Response (201 Created):

{
  "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):

{
  "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):

{
  "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):

{
  "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):

{
  "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:

{
  "keyId": "sha256:abc123...",
  "algorithm": "ECDSA-P256",
  "publicKey": "-----BEGIN PUBLIC KEY-----\n..."
}

Response (201 Created):

{
  "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:

{
  "proofBundleId": "sha256:1a2b3c4d...",
  "checkRekor": true,
  "anchorIds": ["anchor-001"]
}

Response (200 OK):

{
  "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:

{
  "bundles": [
    { "proofBundleId": "sha256:1a2b3c4d...", "checkRekor": true },
    { "proofBundleId": "sha256:5e6f7g8h...", "checkRekor": false }
  ]
}

Response (200 OK):

{
  "results": [
    { "proofBundleId": "sha256:1a2b3c4d...", "verified": true, "checks": {...} },
    { "proofBundleId": "sha256:5e6f7g8h...", "verified": false, "errors": ["..."] }
  ]
}

Error Handling

All errors follow RFC 7807 Problem Details format:

{
  "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:

{
  "proofBundleId": "sha256:1a2b3c4d...",
  "checkRekor": false
}

This skips Rekor inclusion proof verification but still performs:

  • DSSE signature verification
  • Content-addressed ID recomputation
  • Merkle path verification