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
- 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.
664 lines
19 KiB
JSON
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"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|