Documentation
GuideBundles

Bundles

Understand bundle structure, integrity mechanisms, and verification workflows.

Bundle Anatomy

An evidence bundle is a .tar.gz archive with a standardized structure:

evidence-bundle-20260109-123456.tar.gz

├── manifest.json              # Bundle metadata
├── run.json                   # Collection context
├── checksums.sha256           # SHA-256 hashes
├── signature.sig              # Ed25519 signature

├── sources/                   # Raw API responses
│   ├── github/
│   │   ├── org_settings.json
│   │   ├── repo_acme_backend_branch_protection.json
│   │   └── repo_acme_backend_codeowners.json
│   ├── aws/
│   │   ├── iam_password_policy.json
│   │   ├── cloudtrail_trails.json
│   │   └── cloudwatch_log_groups.json
│   └── google-workspace/
│       ├── users_2sv.json
│       └── role_assignments.json

└── derived/                   # Processed evidence
    ├── normalized.json        # Control mappings
    └── hints.json            # Compliance recommendations

Core Files

manifest.json

Bundle table of contents with metadata.

{
  "bundle_version": "1.0",
  "tool_version": "0.1.0",
  "created_at": "2026-01-09T12:34:56Z",
  "framework": "soc2_type1",
  "controls": ["CC6.1", "CC6.6", "CC7.2"],
  "sources": ["github", "aws"],
  "artifacts": [
    {
      "filename": "sources/github/org_settings.json",
      "source": "github",
      "artifact_type": "org_settings",
      "collected_at": "2026-01-09T12:34:50Z",
      "controls": ["CC6.1"],
      "checksum": "abc123...",
      "size_bytes": 456
    }
  ],
  "signer": {
    "algorithm": "Ed25519",
    "public_key": "def456...",
    "key_id": "evidence-sdk-v1"
  }
}

Key fields:

  • bundle_version - Bundle format version (currently 1.0)
  • framework - Compliance framework (soc2_type1, etc.)
  • controls - SOC 2 controls covered
  • artifacts - List of all evidence files with metadata
  • signer - Public key for signature verification

run.json

Collection execution context.

{
  "started_at": "2026-01-09T12:34:45Z",
  "completed_at": "2026-01-09T12:34:56Z",
  "duration_seconds": 11,
  "hostname": "github-actions-runner-1",
  "platform": "linux",
  "tool_version": "0.1.0",
  "config_hash": "ghi789...",
  "environment": {
    "ci": true,
    "github_actions": true,
    "run_id": "1234567890"
  }
}

Use cases:

  • Audit trail of when/where collection ran
  • Reproducibility - can recreate collection conditions
  • Troubleshooting - diagnose issues from environment data

checksums.sha256

SHA-256 hashes of all files.

abc123...  manifest.json
def456...  run.json
ghi789...  sources/github/org_settings.json
jkl012...  sources/github/repo_acme_backend_branch_protection.json
mno345...  sources/aws/iam_password_policy.json
pqr678...  derived/normalized.json
stu901...  derived/hints.json

Format: Standard sha256sum output

  • {hash} {filepath}
  • One line per file
  • Excludes checksums.sha256 and signature.sig themselves

Verification:

# Extract bundle
tar -xzf evidence-bundle-*.tar.gz
cd evidence-bundle-*/

# Verify checksums
sha256sum -c checksums.sha256
# Output: All files OK

signature.sig

Ed25519 signature over checksums.sha256.

Binary file containing 64-byte Ed25519 signature

Signing process:

// 1. Hash all files → checksums.sha256
const checksums = generateChecksums(files);

// 2. Sign checksums file with private key
const signature = Ed25519.sign(
  privateKey,
  checksums
);

// 3. Write signature to signature.sig
fs.writeFileSync('signature.sig', signature);

Verification:

openssl dgst -sha256 -verify public.pem \
  -signature signature.sig checksums.sha256
# Output: Verified OK

Artifact Organization

sources/

Raw API responses from connectors, organized by source.

GitHub artifacts:

sources/github/
├── org_settings.json                          # Organization config
├── repo_{org}_{repo}_branch_protection.json   # Per-repo protection
├── repo_{org}_{repo}_codeowners.json          # Per-repo CODEOWNERS
└── repo_{org}_{repo}_collaborators.json       # Per-repo access

AWS artifacts:

sources/aws/
├── iam_password_policy.json              # Account password policy
├── cloudtrail_trails.json                # CloudTrail configuration
├── cloudtrail_trail_{name}_status.json   # Per-trail status
└── cloudwatch_log_groups.json            # Log group configuration

Google Workspace artifacts:

sources/google-workspace/
├── users_2sv.json              # 2-step verification status
├── role_assignments.json       # Admin role assignments
└── users_lifecycle.json        # User provisioning/suspension

derived/

Processed evidence with control mappings.

normalized.json:

Maps raw artifacts to SOC 2 controls with compliance status.

{
  "controls": {
    "CC6.1": {
      "name": "Logical Access Controls",
      "status": "pass",
      "evidence": [
        {
          "source": "github",
          "artifact": "org_settings.json",
          "finding": "2FA enforced for all members",
          "compliant": true
        },
        {
          "source": "aws",
          "artifact": "iam_password_policy.json",
          "finding": "Password minimum length: 14 characters",
          "compliant": true
        }
      ],
      "summary": "All requirements met"
    }
  }
}

hints.json:

Compliance recommendations and improvement suggestions.

{
  "hints": [
    {
      "severity": "info",
      "control": "CC6.1",
      "category": "improvement",
      "message": "AWS password policy allows 90-day expiration. Consider reducing to 60 days.",
      "source": "aws",
      "artifact": "iam_password_policy.json"
    },
    {
      "severity": "low",
      "control": "CC7.2",
      "category": "partial",
      "message": "Branch protection requires 2 reviewers. Consider increasing to 3 for critical repos.",
      "source": "github",
      "artifact": "repo_acme_backend_branch_protection.json"
    }
  ]
}

Integrity Mechanisms

evidence bundles use two-layer integrity verification:

Layer 1: SHA-256 Checksums

Each file is hashed individually:

File → SHA-256 → Checksum

Properties:

  • Deterministic: Same file always produces same hash
  • One-way: Cannot reverse hash to get original file
  • Collision-resistant: Practically impossible to find two files with same hash
  • Fast: Efficient on modern CPUs

Detection:

  • Tamper any file → Checksum changes → Verification fails
  • Add/remove files → Checksum list incomplete → Verification fails
  • Corrupt during transfer → Checksum mismatch → Verification fails

Layer 2: Ed25519 Signature

Checksums file is signed:

Checksums → Ed25519 Private Key → Signature
Signature → Ed25519 Public Key → Verified

Properties:

  • Authenticity: Proves bundle created by private key holder
  • Non-repudiation: Creator cannot deny creating bundle
  • Tamper-evident: Any modification invalidates signature
  • Fast: Faster than RSA, smaller signatures (64 bytes)

Detection:

  • Tamper checksums file → Signature invalid
  • Wrong public key → Signature verification fails
  • Signature modified → Verification fails

Verification Workflow

Complete bundle verification in 4 steps:

Step 1: Extract Bundle

tar -xzf evidence-bundle-20260109-123456.tar.gz
cd evidence-bundle-20260109-123456/

Checks:

  • Archive extracts without errors
  • Expected files present
  • Directory structure correct

Step 2: Validate Manifest

cat manifest.json | jq

Checks:

  • JSON syntax valid
  • Required fields present
  • Bundle version supported
  • Artifact list matches actual files

Step 3: Verify Checksums

sha256sum -c checksums.sha256

Expected output:

manifest.json: OK
run.json: OK
sources/github/org_settings.json: OK
sources/aws/iam_password_policy.json: OK
derived/normalized.json: OK
derived/hints.json: OK

Checks:

  • All files listed in checksums exist
  • Each file's hash matches expected value
  • No extra or missing files

Step 4: Verify Signature

evidence verify evidence-bundle-*.tar.gz \
  --public-key public.pem

Or manually:

openssl dgst -sha256 -verify public.pem \
  -signature signature.sig checksums.sha256

Expected output:

Verified OK

Checks:

  • Signature valid for checksums file
  • Public key matches bundle signer
  • Signature created by corresponding private key

Bundle Lifecycle

1. Collection

evidence collect

Process:

  1. Validate configuration
  2. Connect to sources (GitHub, AWS, etc.)
  3. Collect artifacts via API
  4. Normalize evidence → control mappings
  5. Generate compliance hints

2. Bundle Creation

Process:

  1. Create manifest with artifact metadata
  2. Write run.json with execution context
  3. Generate SHA-256 checksums for all files
  4. Sign checksums with Ed25519 private key
  5. Package as .tar.gz archive

Output:

evidence-bundles/evidence-bundle-20260109-123456.tar.gz

3. Verification

evidence verify evidence-bundle-*.tar.gz \
  --public-key public.pem

Checks:

  • Checksums valid
  • Signature valid
  • Manifest structure correct

4. Distribution

Options:

Upload to platform:

evidence upload evidence-bundle-*.tar.gz

Share with auditor:

# Send bundle via secure channel
# Send public key via separate channel (out-of-band)

Store for records:

# Archive bundles for compliance period
aws s3 cp evidence-bundle-*.tar.gz s3://compliance-evidence/

5. Audit

Auditor receives:

  • Bundle file (.tar.gz)
  • Public key (.pem) via out-of-band channel

Auditor verifies:

evidence verify evidence-bundle-*.tar.gz \
  --public-key public.pem

Auditor inspects:

tar -xzf evidence-bundle-*.tar.gz
cd evidence-bundle-*/
cat sources/github/org_settings.json | jq
cat derived/normalized.json | jq

Bundle Versioning

Current: Version 1.0

{
  "bundle_version": "1.0",
  // ...
}

Features:

  • TAR/GZIP compression
  • SHA-256 checksums
  • Ed25519 signatures
  • JSON artifacts
  • sources/ and derived/ organization

Future Versions

Planned improvements:

  • Version 1.1: Compressed artifacts (gzip individual files)
  • Version 1.2: Incremental bundles (delta from previous)
  • Version 2.0: Multiple signature support (co-signing)

Backwards compatibility:

  • evidence CLI supports all bundle versions
  • Older versions remain verifiable
  • Migration tools provided for major version changes

Bundle Size Optimization

Current Approach

Typical bundle sizes:

  • Single source (GitHub): 5-20 KB
  • Multi-source (GitHub + AWS): 20-50 KB
  • Full collection (3 sources): 30-75 KB

Why small:

  • Configuration data only, no source code
  • JSON compression via gzip
  • Minimal metadata overhead

Size Limits

Default limit: 50MB

bundle:
  max_size_mb: 50

Why limits:

  • Prevents accidental source code collection
  • Ensures reasonable upload times
  • Policy enforcement (bundles should be small)

If limit exceeded:

✗ Bundle creation failed

Bundle size (52.3 MB) exceeds limit (50 MB)

Large artifacts detected:
  - sources/github/repo_acme_backend_files.json (45 MB)

Possible causes:
  - Accidentally collecting file contents
  - Too many repositories in single collection
  - Large API responses

Recommendations:
  - Review configuration to exclude file contents
  - Split collection across multiple bundles
  - Increase max_size_mb limit if necessary

Next Steps

SOC 2 Control Mappings Understand how bundle contents map to compliance controls.

SOC 2 Controls →

Bundle Format Reference See complete technical specification for bundle format.

Bundle Format Spec →

Verification Guide Learn all verification methods and troubleshooting.

Verify Bundles →