{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://stella-ops.org/schemas/evidence-locker-dsse.schema.json", "title": "StellaOps Evidence Locker DSSE Schema", "description": "Schema for Evidence Locker DSSE attestations, Merkle locker payloads, and evidence batch operations. Unblocks EXCITITOR-OBS-52/53/54.", "type": "object", "definitions": { "EvidenceLockerBatch": { "type": "object", "description": "A batch of evidence artifacts submitted to the Evidence Locker", "required": ["batch_id", "artifacts", "created_at"], "properties": { "batch_id": { "type": "string", "format": "uuid", "description": "Unique identifier for this evidence batch" }, "artifacts": { "type": "array", "items": { "$ref": "#/definitions/EvidenceArtifact" }, "minItems": 1, "description": "List of evidence artifacts in this batch" }, "created_at": { "type": "string", "format": "date-time" }, "created_by": { "type": "string", "description": "Identity of the batch creator" }, "tenant_id": { "type": "string", "format": "uuid" }, "project_id": { "type": "string", "format": "uuid" }, "pipeline_context": { "$ref": "#/definitions/PipelineContext" }, "aggregate_digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$", "description": "SHA-256 digest of all artifact digests concatenated and sorted" }, "merkle_root": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$", "description": "Merkle tree root of the batch" }, "dsse_envelope": { "$ref": "#/definitions/DsseEnvelope" }, "retention_policy": { "$ref": "#/definitions/RetentionPolicy" }, "status": { "type": "string", "enum": ["pending", "committed", "anchored", "sealed", "expired"], "description": "Current status of the batch" } } }, "EvidenceArtifact": { "type": "object", "description": "A single evidence artifact within a batch", "required": ["artifact_id", "artifact_type", "digest", "stored_at"], "properties": { "artifact_id": { "type": "string", "format": "uuid" }, "artifact_type": { "type": "string", "enum": [ "sbom", "vex", "scan_result", "attestation", "policy_evaluation", "callgraph", "runtime_facts", "timeline_event", "audit_log", "configuration", "signature" ], "description": "Type of evidence artifact" }, "digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$", "description": "SHA-256 digest of the artifact content" }, "content_type": { "type": "string", "description": "MIME type of the artifact (e.g., application/json)" }, "size_bytes": { "type": "integer", "minimum": 0 }, "storage_uri": { "type": "string", "format": "uri", "description": "URI to retrieve the artifact from object storage" }, "stored_at": { "type": "string", "format": "date-time" }, "labels": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Key-value labels for filtering and organization" }, "subject": { "$ref": "#/definitions/ArtifactSubject" }, "provenance": { "$ref": "#/definitions/ArtifactProvenance" }, "merkle_position": { "$ref": "#/definitions/MerklePosition" } } }, "ArtifactSubject": { "type": "object", "description": "Subject the artifact relates to (e.g., a component or vulnerability)", "properties": { "subject_type": { "type": "string", "enum": ["component", "vulnerability", "product", "scan", "pipeline", "policy"] }, "identifier": { "type": "string", "description": "Subject identifier (PURL, CVE ID, etc.)" }, "version": { "type": "string" }, "digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" } } }, "ArtifactProvenance": { "type": "object", "description": "Provenance information for an artifact", "properties": { "producer": { "type": "string", "description": "Service or tool that produced this artifact" }, "producer_version": { "type": "string" }, "produced_at": { "type": "string", "format": "date-time" }, "build_invocation_id": { "type": "string", "description": "CI/CD build or pipeline invocation ID" }, "entry_point": { "type": "string", "description": "Entry point command or script" }, "input_digests": { "type": "array", "items": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, "description": "Digests of inputs used to produce this artifact" } } }, "MerklePosition": { "type": "object", "description": "Position in the Merkle tree for tamper detection", "required": ["index", "tree_size", "proof"], "properties": { "index": { "type": "integer", "minimum": 0, "description": "Leaf index in the Merkle tree" }, "tree_size": { "type": "integer", "minimum": 1, "description": "Total number of leaves in the tree" }, "proof": { "type": "array", "items": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, "description": "Audit path hashes for verification" }, "root_digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$", "description": "Merkle root at time of inclusion" } } }, "PipelineContext": { "type": "object", "description": "Context of the pipeline that created the batch", "properties": { "pipeline_id": { "type": "string" }, "pipeline_name": { "type": "string" }, "run_id": { "type": "string" }, "step_id": { "type": "string" }, "repository": { "type": "string" }, "commit_sha": { "type": "string", "pattern": "^[a-f0-9]{40}$" }, "branch": { "type": "string" }, "environment": { "type": "string", "enum": ["development", "staging", "production"] } } }, "DsseEnvelope": { "type": "object", "description": "DSSE (Dead Simple Signing Envelope) for batch attestation", "required": ["payloadType", "payload", "signatures"], "properties": { "payloadType": { "type": "string", "const": "application/vnd.stellaops.evidence-batch.v1+json", "description": "DSSE payload type" }, "payload": { "type": "string", "contentEncoding": "base64", "description": "Base64-encoded batch payload" }, "signatures": { "type": "array", "items": { "$ref": "#/definitions/DsseSignature" }, "minItems": 1 } } }, "DsseSignature": { "type": "object", "description": "A signature on the DSSE envelope", "required": ["sig"], "properties": { "keyid": { "type": "string", "description": "Key identifier (e.g., Fulcio certificate fingerprint)" }, "sig": { "type": "string", "contentEncoding": "base64", "description": "Base64-encoded signature" }, "cert": { "type": "string", "contentEncoding": "base64", "description": "Base64-encoded signing certificate (for keyless signing)" } } }, "RetentionPolicy": { "type": "object", "description": "Retention policy for evidence artifacts", "properties": { "retention_days": { "type": "integer", "minimum": 1, "description": "Number of days to retain artifacts" }, "retention_class": { "type": "string", "enum": ["standard", "extended", "compliance", "indefinite"], "description": "Retention class for policy lookup" }, "expires_at": { "type": "string", "format": "date-time" }, "hold_until": { "type": "string", "format": "date-time", "description": "Legal hold expiration (overrides retention_days)" }, "archive_after_days": { "type": "integer", "minimum": 0, "description": "Days before archiving to cold storage" }, "delete_on_expiry": { "type": "boolean", "default": true, "description": "Whether to delete artifacts when retention expires" } } }, "TimelineEvent": { "type": "object", "description": "Timeline event linked to evidence artifacts", "required": ["event_id", "event_type", "occurred_at"], "properties": { "event_id": { "type": "string", "format": "uuid" }, "event_type": { "type": "string", "enum": [ "evidence_batch_created", "evidence_batch_committed", "merkle_anchor_published", "artifact_accessed", "artifact_verified", "retention_extended", "artifact_archived", "artifact_deleted", "batch_sealed", "verification_failed" ] }, "occurred_at": { "type": "string", "format": "date-time" }, "actor": { "type": "string", "description": "User or service that triggered the event" }, "batch_id": { "type": "string", "format": "uuid" }, "artifact_ids": { "type": "array", "items": { "type": "string", "format": "uuid" }, "description": "Affected artifact IDs" }, "details": { "type": "object", "additionalProperties": true }, "evidence_refs": { "type": "array", "items": { "$ref": "#/definitions/EvidenceRef" }, "description": "References to related evidence" } } }, "EvidenceRef": { "type": "object", "description": "Reference to evidence artifact", "required": ["artifact_id", "digest"], "properties": { "artifact_id": { "type": "string", "format": "uuid" }, "digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, "storage_uri": { "type": "string", "format": "uri" }, "artifact_type": { "type": "string" } } }, "MerkleAnchor": { "type": "object", "description": "Merkle tree anchor published to transparency log", "required": ["anchor_id", "merkle_root", "tree_size", "published_at"], "properties": { "anchor_id": { "type": "string", "format": "uuid" }, "merkle_root": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, "tree_size": { "type": "integer", "minimum": 1 }, "published_at": { "type": "string", "format": "date-time" }, "batch_ids": { "type": "array", "items": { "type": "string", "format": "uuid" }, "description": "Batches included in this anchor" }, "previous_anchor_id": { "type": "string", "format": "uuid", "description": "Previous anchor in the chain" }, "consistency_proof": { "type": "array", "items": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, "description": "Consistency proof from previous anchor" }, "rekor_entry": { "$ref": "#/definitions/RekorEntry" } } }, "RekorEntry": { "type": "object", "description": "Entry in Sigstore Rekor transparency log", "properties": { "log_index": { "type": "integer", "minimum": 0 }, "log_id": { "type": "string" }, "integrated_time": { "type": "integer", "description": "Unix timestamp when entry was integrated" }, "uuid": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, "body": { "type": "string", "contentEncoding": "base64" }, "inclusion_proof": { "$ref": "#/definitions/InclusionProof" } } }, "InclusionProof": { "type": "object", "description": "Inclusion proof for transparency log", "required": ["log_index", "root_hash", "tree_size", "hashes"], "properties": { "log_index": { "type": "integer", "minimum": 0 }, "root_hash": { "type": "string", "contentEncoding": "base64" }, "tree_size": { "type": "integer", "minimum": 1 }, "hashes": { "type": "array", "items": { "type": "string", "contentEncoding": "base64" } } } }, "VerificationRequest": { "type": "object", "description": "Request to verify evidence artifact integrity", "required": ["artifact_id"], "properties": { "artifact_id": { "type": "string", "format": "uuid" }, "expected_digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, "verify_merkle_proof": { "type": "boolean", "default": true }, "verify_dsse_signature": { "type": "boolean", "default": true }, "verify_rekor_inclusion": { "type": "boolean", "default": false } } }, "VerificationResult": { "type": "object", "description": "Result of evidence verification", "required": ["artifact_id", "verified", "timestamp"], "properties": { "artifact_id": { "type": "string", "format": "uuid" }, "verified": { "type": "boolean" }, "timestamp": { "type": "string", "format": "date-time" }, "checks": { "type": "array", "items": { "$ref": "#/definitions/VerificationCheck" } }, "error": { "type": "string", "description": "Error message if verification failed" } } }, "VerificationCheck": { "type": "object", "description": "Individual verification check result", "required": ["check_type", "passed"], "properties": { "check_type": { "type": "string", "enum": [ "digest_match", "merkle_proof_valid", "dsse_signature_valid", "certificate_valid", "rekor_inclusion_valid", "timestamp_valid" ] }, "passed": { "type": "boolean" }, "details": { "type": "string" } } } }, "properties": { "batches": { "type": "array", "items": { "$ref": "#/definitions/EvidenceLockerBatch" } } }, "examples": [ { "batches": [ { "batch_id": "550e8400-e29b-41d4-a716-446655440000", "artifacts": [ { "artifact_id": "660e8400-e29b-41d4-a716-446655440001", "artifact_type": "sbom", "digest": "sha256:abc123def456789012345678901234567890123456789012345678901234abcd", "content_type": "application/vnd.cyclonedx+json", "size_bytes": 15234, "storage_uri": "s3://evidence-locker/batches/550e8400.../sbom.json", "stored_at": "2025-12-06T10:00:00Z", "labels": { "project": "frontend-app", "environment": "production" }, "subject": { "subject_type": "component", "identifier": "pkg:npm/frontend-app@1.0.0", "digest": "sha256:def456..." }, "provenance": { "producer": "stellaops-scanner", "producer_version": "2025.10.0", "produced_at": "2025-12-06T09:55:00Z", "build_invocation_id": "ci-12345" }, "merkle_position": { "index": 0, "tree_size": 3, "proof": [ "sha256:111...", "sha256:222..." ], "root_digest": "sha256:merkleroot..." } } ], "created_at": "2025-12-06T10:00:00Z", "created_by": "stellaops-pipeline", "tenant_id": "tenant-001", "aggregate_digest": "sha256:aggregate123...", "merkle_root": "sha256:merkleroot...", "dsse_envelope": { "payloadType": "application/vnd.stellaops.evidence-batch.v1+json", "payload": "eyJiYXRjaF9pZCI6IjU1MGU4NDAwLi4uIn0=", "signatures": [ { "keyid": "fulcio:abc123", "sig": "MEUCIQDxxx..." } ] }, "retention_policy": { "retention_days": 365, "retention_class": "compliance", "archive_after_days": 90 }, "status": "committed" } ] } ] }