Evidence Pack Schema

Status: Catalog persistence implemented; assembly/replay workflows remain implementation in progress (SPRINT_3000_0100_0002, SPRINT_20260517_016) Type URI: https://stellaops.dev/evidence-pack@v1 Schema: docs/modules/evidence-locker/schemas/stellaops-evidence-pack.v1.schema.json


Overview

Audience: operators, auditors, and integrators who create, transfer, verify, or replay evidence packs — and developers integrating against the pack API/CLI.

Evidence Packs are time-stamped, queryable bundles containing the complete policy-evaluation context (SBOM, advisories, VEX, policy, verdicts, reachability). They enable:

Transparency and timestamp references


Pack Structure

Evidence packs are compressed tarballs (.tar.gz) with a signed manifest:

evidence-pack-{packId}.tar.gz
├── manifest.json                        # Signed manifest with content index
├── policy/
│   ├── policy-P-7-v4.json              # Policy definition snapshot
│   └── policy-run-{runId}.json         # Policy run request/status
├── sbom/
│   ├── sbom-S-42.spdx.json             # SBOM artifacts
│   └── sbom-S-318.spdx.json
├── advisories/
│   ├── nvd-2025-12345.json             # Advisory snapshots (timestamped)
│   ├── ghsa-2025-0001.json
│   └── cve-2025-99999.json
├── vex/
│   ├── vendor-vex-statement-1.json     # VEX statements (OpenVEX)
│   └── internal-vex-override-2.json
├── verdicts/
│   ├── verdict-finding-1.json          # Individual verdict attestations (DSSE)
│   ├── verdict-finding-2.json
│   └── ...
├── reachability/
│   ├── drift-{scanId}.json             # Reachability drift results
│   └── slices/
│       └── slice-{digest}.json         # Reachability slices
└── metadata/
    ├── tenant-context.json             # Tenant metadata
    ├── environment.json                # Environment context from policy run
    └── signatures.json                 # Detached signatures for pack contents

Manifest Format

See stellaops-evidence-pack.v1.schema.json for complete schema.

Example Manifest

{
  "_type": "https://stellaops.dev/evidence-pack@v1",
  "packId": "pack:run:P-7:20251223T140500Z:1b2c3d4e",
  "generatedAt": "2025-12-23T14:10:00+00:00",
  "tenantId": "tenant-alpha",
  "policyRunId": "run:P-7:20251223T140500Z:1b2c3d4e",
  "policyId": "P-7",
  "policyVersion": 4,
  "manifestVersion": "1.0.0",

  "contents": {
    "policy": [
      {
        "path": "policy/policy-P-7-v4.json",
        "digest": "sha256:abc123...",
        "size": 12345,
        "mediaType": "application/vnd.stellaops.policy+json"
      }
    ],
    "sbom": [
      {
        "path": "sbom/sbom-S-42.spdx.json",
        "digest": "sha256:sbom42...",
        "size": 234567,
        "mediaType": "application/spdx+json",
        "sbomId": "sbom:S-42"
      }
    ],
    "advisories": [
      {
        "path": "advisories/nvd-2025-12345.json",
        "digest": "sha256:adv123...",
        "size": 4567,
        "mediaType": "application/vnd.stellaops.advisory+json",
        "cveId": "CVE-2025-12345",
        "capturedAt": "2025-12-23T13:59:00+00:00"
      }
    ],
    "vex": [...],
    "verdicts": [...],
    "reachability": [...]
  },

  "statistics": {
    "totalFiles": 47,
    "totalSize": 5678901,
    "componentCount": 1742,
    "findingCount": 234,
    "verdictCount": 234,
    "advisoryCount": 89,
    "vexStatementCount": 12
  },

  "determinismHash": "sha256:pack-determinism...",
  "signatures": [
    {
      "keyId": "sha256:keypair123...",
      "algorithm": "ed25519",
      "signature": "base64-encoded-signature",
      "signedAt": "2025-12-23T14:10:05+00:00"
    }
  ]
}

API Reference

List Evidence Packs

GET /api/v1/evidence/packs

Returns persisted pack summary rows for the authenticated tenant only. The service resolves tenant scope from the bearer-token tenant claim through IStellaOpsTenantAccessor; tenant headers are not accepted as a fallback. The backing catalog is evidence_locker.evidence_packs, protected by row-level security on tenant_id.

Response:

{
  "items": [
    {
      "packId": "pack:run:P-7:20251223T140500Z:1b2c3d4e",
      "releaseId": "rel-003",
      "environment": "us-prod",
      "bundleVersion": "1.0.0",
      "status": "sealed",
      "createdAt": "2025-12-23T14:10:00Z"
    }
  ],
  "total": 1,
  "generatedAt": "2026-02-19T03:15:00Z"
}

Get Evidence Pack Detail

GET /api/v1/evidence/packs/{packId}

Returns the pack detail row plus ordered artifact summaries from evidence_locker.evidence_pack_artifacts. A pack owned by another tenant is reported as 404 pack_not_found.

Create Evidence Pack

POST /api/v1/runs/{runId}/evidence-pack

Request:

{
  "includeReachability": true,
  "compression": "gzip"
}

Response:

{
  "packId": "pack:run:P-7:20251223T140500Z:1b2c3d4e",
  "generatedAt": "2025-12-23T14:10:00+00:00",
  "downloadUri": "/api/v1/evidence-packs/pack:run:P-7:20251223T140500Z:1b2c3d4e",
  "manifestUri": "/api/v1/evidence-packs/pack:run:P-7:20251223T140500Z:1b2c3d4e/manifest",
  "packSize": 5678901,
  "statistics": {...}
}

Download Evidence Pack

GET /api/v1/evidence-packs/{packId}
Accept: application/gzip

Response: Binary tarball (.tar.gz)

Inspect Manifest

GET /api/v1/evidence-packs/{packId}/manifest

Response: JSON manifest (without downloading full pack)

Replay Policy from Pack

POST /api/v1/evidence-packs/{packId}/replay

Response:

{
  "replayId": "replay:pack:...:20251223T150000Z",
  "packId": "pack:run:P-7:20251223T140500Z:1b2c3d4e",
  "originalRunId": "run:P-7:20251223T140500Z:1b2c3d4e",
  "determinismVerified": true,
  "verdictComparison": {
    "totalOriginal": 234,
    "totalReplay": 234,
    "identical": 234,
    "differences": []
  },
  "replayDuration": 45.2
}

Verify Pack Integrity

POST /api/v1/evidence-packs/{packId}/verify

Response:

{
  "packId": "pack:run:P-7:20251223T140500Z:1b2c3d4e",
  "manifestSignatureValid": true,
  "contentIntegrityValid": true,
  "verifiedAt": "2025-12-23T15:00:00+00:00",
  "verifications": [
    {
      "file": "policy/policy-P-7-v4.json",
      "expectedDigest": "sha256:abc123...",
      "actualDigest": "sha256:abc123...",
      "valid": true
    },
    // ... all files
  ]
}

CLI Usage

Create Pack

stella pack create run:P-7:20251223T140500Z:1b2c3d4e

# Output:
# Assembling evidence pack...
# ✓ Policy definition (12 KB)
# ✓ SBOMs (2 files, 450 KB)
# ✓ Advisories (89 files, 234 KB)
# ✓ VEX statements (12 files, 45 KB)
# ✓ Verdicts (234 files, 567 KB)
# ✓ Reachability data (18 KB)
#
# Pack created: pack:run:P-7:20251223T140500Z:1b2c3d4e
# Size: 5.4 MB (compressed)
# Download: stella pack download pack:run:P-7:20251223T140500Z:1b2c3d4e

Download Pack

stella pack download pack:run:P-7:20251223T140500Z:1b2c3d4e --output ./evidence-pack.tar.gz

# Output:
# Downloading pack:run:P-7:20251223T140500Z:1b2c3d4e...
# Downloaded 5.4 MB to ./evidence-pack.tar.gz

Inspect Pack

stella pack inspect evidence-pack.tar.gz

# Output:
# Pack ID: pack:run:P-7:20251223T140500Z:1b2c3d4e
# Generated: 2025-12-23T14:10:00+00:00
# Policy: P-7 (version 4)
# Tenant: tenant-alpha
#
# Contents:
#   Policy: 2 files (12 KB)
#   SBOMs: 2 files (450 KB) - 1,742 components
#   Advisories: 89 files (234 KB)
#   VEX: 12 files (45 KB)
#   Verdicts: 234 files (567 KB)
#   Reachability: 3 files (18 KB)
#
# Total: 342 files, 1.3 MB (5.4 MB compressed)
# Determinism hash: sha256:pack-determinism...
# Signature: ✓ Verified (ed25519)

List Pack Contents

stella pack list evidence-pack.tar.gz

# Output:
# manifest.json (signed manifest)
# policy/policy-P-7-v4.json
# policy/policy-run-run:P-7:20251223T140500Z:1b2c3d4e.json
# sbom/sbom-S-42.spdx.json
# sbom/sbom-S-318.spdx.json
# advisories/nvd-2025-12345.json
# ...

Extract Artifact

stella pack export evidence-pack.tar.gz \
  --artifact sbom/sbom-S-42.spdx.json \
  --output ./sbom-S-42.spdx.json

# Output:
# Extracted sbom/sbom-S-42.spdx.json → ./sbom-S-42.spdx.json

Verify Pack

stella pack verify evidence-pack.tar.gz

# Output:
# Verifying pack:run:P-7:20251223T140500Z:1b2c3d4e...
# ✓ Manifest signature valid
# ✓ Content integrity (342/342 files)
# ✓ Determinism hash matches
#
# Pack is valid and tamper-free

Replay Policy

stella pack replay evidence-pack.tar.gz

# Output:
# Replaying policy P-7 (version 4)...
# Loading SBOMs (2 files)...
# Loading advisories (89 files)...
# Loading VEX statements (12 files)...
# Evaluating 1,742 components...
#
# Replay completed in 45.2s
# ✓ Determinism verified
# ✓ 234/234 verdicts match original
#
# Original run: run:P-7:20251223T140500Z:1b2c3d4e
# Replay run: replay:pack:...:20251223T150000Z

Deterministic Replay

Evidence packs enable deterministic policy replay:

Prerequisites

  1. Complete Context: Pack contains all inputs (SBOMs, advisories, VEX, policy, environment)
  2. Timestamp Anchoring: Advisory/VEX snapshots captured at exact cursor timestamps
  3. Canonical Inputs: All inputs normalized and sorted deterministically

Replay Process

1. Extract Pack → Verify Signature
2. Load Policy Definition (P-7 v4)
3. Load SBOMs (S-42, S-318)
4. Load Advisory Snapshots (at cursor 2025-12-23T13:59:00Z)
5. Load VEX Snapshots (at cursor 2025-12-23T13:58:30Z)
6. Reconstruct Policy Inputs (identical to original run)
7. Execute Policy Evaluation
8. Compare Replay Verdicts to Original Verdicts
9. Report Determinism Status

Determinism Validation

# Replay and compare
stella pack replay evidence-pack.tar.gz --compare

# Output includes:
# - Total verdicts: 234
# - Matching: 234
# - Differences: 0
# - Determinism hash: sha256:... (matches original)

Air-Gap Transfer

Evidence packs support offline/air-gapped workflows:

Export from Online Environment

# Create pack from policy run
stella pack create run:P-7:20251223T140500Z:1b2c3d4e --output ./pack.tar.gz

# Verify before transfer
stella pack verify ./pack.tar.gz

Transfer

# Copy to removable media or secure transfer channel
cp ./pack.tar.gz /media/usb-drive/

Import to Air-Gapped Environment

# Verify pack integrity
stella pack verify /media/usb-drive/pack.tar.gz

# Replay policy (offline, no network)
stella pack replay /media/usb-drive/pack.tar.gz

# Extract artifacts
stella pack export /media/usb-drive/pack.tar.gz \
  --artifact verdicts/verdict-finding-1.json \
  --output ./verdict-1.json

Performance

Pack Assembly Time

Component CountFindingsPack SizeAssembly Time
10010500 KB2s
1,0001005 MB15s
10,0001,00050 MB2min
100,00010,000500 MB20min

Replay Time

Replay time ≈ 90% of original policy run time (overhead from deserialization)


Storage

Retention Policy

Stella Ops is self-hosted, so packs are tiered across the operator’s own object store (any S3-compatible backend, e.g. MinIO) rather than a cloud-managed service. A typical age-based tiering policy:

AgeStorage TierAccess Pattern
< 7 daysHot (PostgreSQL index + primary object store)Frequent
7-30 daysWarm (object store, infrequent-access class)Occasional
30-90 daysCold (archival object store)Rare
> 90 daysDeep archive (offline/air-gapped media)Compliance-only

Compression Ratios

Content TypeUncompressedCompressedRatio
SBOMs (JSON)10 MB2 MB5:1
Advisories (JSON)5 MB1 MB5:1
Verdicts (DSSE)15 MB4 MB3.75:1
Total Pack30 MB7 MB4.3:1

Security

Manifest Signing

Content Integrity

Access Control


Troubleshooting

Pack Assembly Failed

Symptom: POST /api/v1/runs/{runId}/evidence-pack returns 500

Causes:

  1. Missing artifacts (SBOM/VEX not found)
  2. Object store unavailable
  3. Signing key unavailable

Resolution:

# Check policy run completed
stella policy status run:P-7:20251223T140500Z:1b2c3d4e

# Verify all artifacts present
stella pack validate-inputs run:P-7:20251223T140500Z:1b2c3d4e

# Retry pack creation
stella pack create run:P-7:20251223T140500Z:1b2c3d4e

Determinism Failure on Replay

Symptom: Replay verdicts differ from original

Causes:

  1. Advisory/VEX drift (cursor mismatch)
  2. Policy definition changed
  3. Non-deterministic evaluation logic

Resolution:

# Compare inputs
stella pack diff-inputs evidence-pack.tar.gz --original-run run:...

# Identify divergence
stella pack replay evidence-pack.tar.gz --verbose --diff

# Output shows:
# - Finding X: original=blocked, replay=warned
# - Cause: VEX statement vex:... not found in pack

References

Hybrid Diff Artifacts

When a verdict payload contains a DeltaSig predicate with hybridDiff, include the following deterministic artifacts in the evidence pack (for example under binary-diff/) and keep each artifact digest linked to the attested predicate: