Files
git.stella-ops.org/docs/schemas/evidence-locker-dsse.schema.json
StellaOps Bot 4042fc2184
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
release-manifest-verify / verify (push) Has been cancelled
Add unit tests for PackRunAttestation and SealedInstallEnforcer
- Implement comprehensive tests for PackRunAttestationService, covering attestation generation, verification, and event emission.
- Add tests for SealedInstallEnforcer to validate sealed install requirements and enforcement logic.
- Introduce a MonacoLoaderService stub for testing purposes to prevent Monaco workers/styles from loading during Karma runs.
2025-12-06 22:25:30 +02:00

664 lines
19 KiB
JSON

{
"$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"
}
]
}
]
}