Offline Verification Playbook (EB9)

Purpose: allow auditors to validate Evidence Locker bundles without network access, using only POSIX tools. Applies to both sealed bundle.tgz and portable portable-bundle-v1.tgz.

Prerequisites

Quick steps (sealed bundle)

  1. tar -xzf bundle.tgz -C /tmp/bundle
  2. cd /tmp/bundle
  3. Validate checksums: sha256sum -c checksums.txt
  4. Derive Merkle root (matches DSSE subject): sha256sum checksums.txt | awk '{print $1}'
  5. Validate manifest against schema (if jq present): jq -e 'input | type=="object"' manifest.json >/dev/null
  6. Verify DSSE envelope (optional but recommended):
    • cat manifest.json | base64 | cosign verify-blob --key cosign.pub --bundle signature.json --bundleType dsse
    • or, for a portable bundle, run the operator command stella evidence verify-offline portable-bundle-v1.tgz (SPRINT_20260704_009 SER-3). It runs the same EvidencePortableBundleOfflineVerifier fully offline and is fail-closed (exit 1 on any integrity failure, incl. a single flipped byte); add --output json for machine-readable results.

Protected Evidence Requirements

Production sealed bundles and Decision Capsules must include durable signer evidence. EvidenceLocker fails closed when a required timestamp authority returns no timestamp, when only transient key generation is available, or when capsule sealing would persist an unsigned result. The local/test harness exceptions are explicit configuration switches only: Signing:AllowEphemeralKeyMaterial=true and Signing:AllowUnsignedCapsules=true.

Offline reviewers should treat a production capsule with signingStatus="unsigned" as invalid protected evidence unless the package explicitly identifies itself as a local/test fixture.

Quick steps (portable bundle)

Same as sealed, plus confirm redaction:

The single offline verification authority is StellaOps.EvidenceLocker.Core.Services.EvidencePortableBundleOfflineVerifier (BCL-only; SPRINT_20260704_009 SER-3 lifted it from …Infrastructure.Services into the lean Core lib so the stella evidence verify-offline CLI can reuse it without pulling EF/Npgsql/AWS into the offline path). Use it directly for local EvidenceLocker tests and offline QA gates, or via the CLI operator command, against the portable-bundle-v1.tgz stream. The verifier performs archive-local checks only: checksum coverage, manifest file digest/size binding, manifest.sig payload binding, dsse_envelope.json payload digest binding, Rekor tile coverage for artifact and canonical BOM digests, and bundle.json redaction. It deliberately makes no network calls and does not replace public-key DSSE or Rekor checkpoint signature validation when trust roots are available.

Embeddable verifier script

Place the following script into verify-offline.sh when assembling portable bundles. It exits non-zero on any mismatch and prints the Merkle root used as DSSE subject.

#!/usr/bin/env bash
set -euo pipefail
BUNDLE="${1:-bundle.tgz}"
WORKDIR="$(mktemp -d)"
cleanup() { rm -rf "$WORKDIR"; }
trap cleanup EXIT
tar -xzf "$BUNDLE" -C "$WORKDIR"
cd "$WORKDIR"
sha256sum -c checksums.txt
MERKLE=$(sha256sum checksums.txt | awk '{print $1}')
printf "merkle_root=%s\n" "$MERKLE"
if command -v jq >/dev/null; then
  jq -e 'type=="object" and has("entries")' manifest.json >/dev/null
fi

Fixtures

References