{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://stellaops.org/schemas/evidence-locker/bundle-packaging.v1.schema.json", "title": "EvidenceLocker Bundle Packaging Schema", "description": "Defines the structure of sealed evidence bundle packages (.tgz) produced by the EvidenceLocker module. These bundles are deterministic, signed, and suitable for offline verification, forensic handoff, and air-gapped import.", "type": "object", "required": ["bundleArchive"], "$defs": { "bundleKind": { "type": "integer", "enum": [1, 2, 3], "description": "Evidence bundle kind: 1=Evaluation, 2=Job, 3=Export" }, "bundleStatus": { "type": "integer", "enum": [1, 2, 3, 4, 5], "description": "Evidence bundle status: 1=Pending, 2=Assembling, 3=Sealed, 4=Failed, 5=Archived" }, "sha256Hash": { "type": "string", "pattern": "^[a-f0-9]{64}$", "description": "SHA-256 hash in lowercase hexadecimal (64 characters)" }, "uuid": { "type": "string", "format": "uuid", "description": "UUID in standard format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)" }, "iso8601DateTime": { "type": "string", "format": "date-time", "description": "ISO 8601 date-time string with timezone" }, "manifestEntry": { "type": "object", "title": "Manifest Entry", "description": "An individual artifact entry within the evidence bundle manifest", "required": ["section", "canonicalPath", "sha256", "sizeBytes"], "properties": { "section": { "type": "string", "description": "Logical section grouping (e.g., 'sbom', 'vex', 'attestation', 'advisory', 'policy')", "minLength": 1, "examples": ["sbom", "vex", "attestation", "advisory", "policy", "scan-results"] }, "canonicalPath": { "type": "string", "description": "Canonical path within the bundle namespace (deterministic ordering key)", "pattern": "^[a-zA-Z0-9/_.-]+$", "examples": ["sbom/cyclonedx.json", "attestation/provenance.dsse"] }, "sha256": { "$ref": "#/$defs/sha256Hash" }, "sizeBytes": { "type": "integer", "minimum": 0, "description": "Size of the artifact in bytes" }, "mediaType": { "type": ["string", "null"], "description": "MIME type of the artifact content", "examples": ["application/json", "application/vnd.cyclonedx+json", "application/vnd.in-toto+dsse"] }, "attributes": { "type": ["object", "null"], "additionalProperties": { "type": "string" }, "description": "Optional key-value attributes for the artifact (e.g., format version, provenance hints)" } }, "additionalProperties": false }, "manifestDocument": { "type": "object", "title": "Bundle Manifest", "description": "The manifest.json file embedded in the bundle package, containing the Merkle tree leaf entries", "required": ["bundleId", "tenantId", "kind", "createdAt"], "properties": { "bundleId": { "$ref": "#/$defs/uuid" }, "tenantId": { "$ref": "#/$defs/uuid" }, "kind": { "$ref": "#/$defs/bundleKind" }, "createdAt": { "$ref": "#/$defs/iso8601DateTime" }, "metadata": { "type": ["object", "null"], "additionalProperties": { "type": "string" }, "description": "Optional bundle-level metadata key-value pairs" }, "entries": { "type": ["array", "null"], "items": { "$ref": "#/$defs/manifestEntry" }, "description": "Array of manifest entries (artifacts) in the bundle" } }, "additionalProperties": false }, "signatureDocument": { "type": "object", "title": "Bundle Signature", "description": "The signature.json file embedded in the bundle package, containing DSSE envelope and optional RFC3161 timestamp", "required": ["payloadType", "payload", "signature", "algorithm", "provider", "signedAt"], "properties": { "payloadType": { "type": "string", "description": "DSSE payload type URI", "examples": ["application/vnd.stellaops.evidence-bundle.manifest+json"] }, "payload": { "type": "string", "contentEncoding": "base64", "description": "Base64-encoded payload (the manifest JSON)" }, "signature": { "type": "string", "description": "Cryptographic signature over the payload" }, "keyId": { "type": ["string", "null"], "description": "Key identifier for signature verification (e.g., Fulcio certificate fingerprint, key alias)" }, "algorithm": { "type": "string", "description": "Signature algorithm used", "examples": ["ECDSA-P256-SHA256", "RSA-PSS-SHA256", "Ed25519", "GOST3410-2012-256", "SM2"] }, "provider": { "type": "string", "description": "Crypto provider or signer identity", "examples": ["StellaOps", "Sigstore-Fulcio", "FIPS-HSM", "CryptoPro-CSP"] }, "signedAt": { "$ref": "#/$defs/iso8601DateTime" }, "timestampedAt": { "oneOf": [ { "$ref": "#/$defs/iso8601DateTime" }, { "type": "null" } ], "description": "RFC3161 timestamp authority response time (if timestamped)" }, "timestampAuthority": { "type": ["string", "null"], "description": "RFC3161 TSA URL or identifier", "examples": ["https://freetsa.org/tsr", "https://timestamp.digicert.com"] }, "timestampToken": { "type": ["string", "null"], "contentEncoding": "base64", "description": "Base64-encoded RFC3161 timestamp token (if timestamped)" } }, "additionalProperties": false }, "bundleMetadataDocument": { "type": "object", "title": "Bundle Metadata", "description": "The bundle.json file embedded in the bundle package, containing top-level bundle metadata", "required": ["bundleId", "tenantId", "kind", "status", "rootHash", "storageKey", "createdAt"], "properties": { "bundleId": { "$ref": "#/$defs/uuid" }, "tenantId": { "$ref": "#/$defs/uuid" }, "kind": { "$ref": "#/$defs/bundleKind" }, "status": { "$ref": "#/$defs/bundleStatus" }, "rootHash": { "$ref": "#/$defs/sha256Hash", "description": "Merkle tree root hash computed from manifest entries" }, "storageKey": { "type": "string", "description": "Storage location key for the sealed bundle", "minLength": 1 }, "createdAt": { "$ref": "#/$defs/iso8601DateTime" }, "sealedAt": { "oneOf": [ { "$ref": "#/$defs/iso8601DateTime" }, { "type": "null" } ], "description": "Timestamp when the bundle was sealed" } }, "additionalProperties": false }, "checksumsFile": { "type": "object", "title": "Checksums File Format", "description": "Structure of the checksums.txt file (human-readable SHA-256 verification list)", "properties": { "format": { "type": "string", "const": "sha256", "description": "Hash algorithm used (always SHA-256)" }, "rootHash": { "$ref": "#/$defs/sha256Hash", "description": "Merkle root hash for the bundle" }, "entries": { "type": "array", "items": { "type": "object", "required": ["sha256", "path"], "properties": { "sha256": { "$ref": "#/$defs/sha256Hash" }, "path": { "type": "string" } } }, "description": "List of file checksums in 'sha256 path' format" } } } }, "properties": { "bundleArchive": { "type": "object", "title": "Bundle Archive Structure", "description": "The .tgz (gzip-compressed tar) archive structure", "required": ["format", "compression", "deterministic", "contents"], "properties": { "format": { "type": "string", "const": "tar", "description": "Archive format (PAX tar)" }, "compression": { "type": "string", "const": "gzip", "description": "Compression algorithm" }, "deterministic": { "type": "boolean", "const": true, "description": "Bundle is deterministic (fixed timestamps, sorted entries)" }, "fixedTimestamp": { "type": "string", "const": "2025-01-01T00:00:00Z", "description": "Fixed timestamp used for deterministic output" }, "contents": { "type": "object", "title": "Archive Contents", "description": "Files contained in the bundle archive", "required": ["manifest.json", "signature.json", "bundle.json", "checksums.txt", "instructions.txt"], "properties": { "manifest.json": { "$ref": "#/$defs/manifestDocument" }, "signature.json": { "$ref": "#/$defs/signatureDocument" }, "bundle.json": { "$ref": "#/$defs/bundleMetadataDocument" }, "checksums.txt": { "type": "string", "description": "Human-readable checksums file in 'sha256 path' format" }, "instructions.txt": { "type": "string", "description": "Human-readable verification instructions" } }, "additionalProperties": false } }, "additionalProperties": false } }, "additionalProperties": false, "examples": [ { "bundleArchive": { "format": "tar", "compression": "gzip", "deterministic": true, "fixedTimestamp": "2025-01-01T00:00:00Z", "contents": { "manifest.json": { "bundleId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "tenantId": "00000000-0000-0000-0000-000000000001", "kind": 2, "createdAt": "2025-12-07T10:30:00Z", "metadata": { "source": "scanner-job-123", "target": "registry.example.com/app:v1.2.3" }, "entries": [ { "section": "sbom", "canonicalPath": "sbom/cyclonedx.json", "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "sizeBytes": 15234, "mediaType": "application/vnd.cyclonedx+json", "attributes": { "specVersion": "1.6", "format": "json" } }, { "section": "attestation", "canonicalPath": "attestation/provenance.dsse", "sha256": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456", "sizeBytes": 4096, "mediaType": "application/vnd.in-toto+dsse" } ] }, "signature.json": { "payloadType": "application/vnd.stellaops.evidence-bundle.manifest+json", "payload": "eyJidW5kbGVJZCI6ImExYjJjM2Q0LWU1ZjYtNzg5MC1hYmNkLWVmMTIzNDU2Nzg5MCIsLi4ufQ==", "signature": "MEUCIQDx...", "keyId": "sha256:abc123...", "algorithm": "ECDSA-P256-SHA256", "provider": "StellaOps", "signedAt": "2025-12-07T10:30:05Z", "timestampedAt": "2025-12-07T10:30:06Z", "timestampAuthority": "https://freetsa.org/tsr", "timestampToken": "MIIEpgYJKo..." }, "bundle.json": { "bundleId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "tenantId": "00000000-0000-0000-0000-000000000001", "kind": 2, "status": 3, "rootHash": "f4d8e9c7b6a5432109876543210fedcba9876543210fedcba9876543210fedc", "storageKey": "evidence/00000000-0000-0000-0000-000000000001/a1b2c3d4-e5f6-7890-abcd-ef1234567890/bundle.tgz", "createdAt": "2025-12-07T10:30:00Z", "sealedAt": "2025-12-07T10:30:05Z" }, "checksums.txt": "# Evidence bundle checksums (sha256)\nroot f4d8e9c7b6a5432109876543210fedcba9876543210fedcba9876543210fedc\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 sbom/cyclonedx.json\na1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456 attestation/provenance.dsse\n", "instructions.txt": "Evidence Bundle Instructions\n============================\nBundle ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890\n..." } } } ] }