Verify a Verdifax audit bundle

Every Verdifax run produces a sealed audit bundle, a structured JSON record of what happened (actor, model, decision, classification, effects) bound to cryptographic proof (manifest hash, per-artifact hashes, seal references). The bundle is designed so any third party can independently confirm that the recorded evidence is internally consistent, without trusting Verdifax, without contacting the API, and without any credentials.

verdifax-verify is the open-source command-line tool that performs that check. It is the offline-verification path for Verdifax bundles: the binary recomputes every hash from the bundle's own contents without ever reaching the API.

Install

Go (any platform)

go install github.com/Verdifax/verdifax-verify@latest

The binary lands at $(go env GOBIN)/verdifax-verify, usually ~/go/bin/verdifax-verify.

Docker

If you do not have Go installed, the verifier ships inside the orchestrator container image:

docker run --rm -v "$(pwd):/work" ghcr.io/verdifax/verdifax-api:latest \
  /app/verdifax-verify /work/bundle.json

Verify in 60 seconds (OK run)

For a sealed artifact from an OK run:

curl -s -H "X-Verdifax-Key: $VERDIFAX_KEY" https://api.verdifax.com/runs/63/artifacts | jq .manifest > manifest.json
verdifax-pepg-verify manifest.json

Sample output for OK manifest:

verdifax-pepg-verify 0.3.0

Manifest hash:    482f13e5c114551c507fb2ebff6df3f50a744e1fc1573b3a501e78aae8bae75c

PIPELINE ARTIFACTS
  ✓  envelope                  b5ff617aa37ce101...
  ✓  transport                 0faf905e250d5e86...
  ✓  epa                       c7cd18d289828433...
  ✓  efa                       …
  ✓  aer                       …
  ✓  transcript                …
  ✓  hardware_attestation      …
  ✓  leakage_bundle            …
  ✓  zksp_binding              …
  ✓  migration_token           …
  ✓  replay_fingerprint        …
  ✓  pote_proof                …
  ✓  final_vfa                 …

DECISION ARTIFACTS
  ✓  allow_token               6a2b4c8e9d1f5e3a...
  ✓  policy_hash               8f1d2c5e9a3b7f4c...
  ✓  evaluation_hash           b2e0f5d1a8c3e7f9...

SEAL REFERENCES
  ✓  manifest_hash             482f13e5c114551c...

VERDICT: ✓ VERIFIED MANIFEST
  Hash: 482f13e5c114551c507fb2ebff6df3f50a744e1fc1573b3a501e78aae8bae75c

Exit code is 0 on success.

Verify deny/halt receipts

For non-OK runs, the verifier handles sealed receipts (DenyReceipt, CCVHaltReceipt, MACCHaltReceipt):

# PEPG deny
curl -s -H "X-Verdifax-Key: $VERDIFAX_KEY" https://api.verdifax.com/runs/64/deny-receipt | jq .deny_receipt | verdifax-pepg-verify

# CCV halt
curl -s -H "X-Verdifax-Key: $VERDIFAX_KEY" https://api.verdifax.com/runs/65/ccv-halt-receipt | jq .ccv_halt_receipt | verdifax-pepg-verify

# MACC halt
curl -s -H "X-Verdifax-Key: $VERDIFAX_KEY" https://api.verdifax.com/runs/76/macc-halt-receipt | jq .macc_halt_receipt | verdifax-pepg-verify

The verifier CLI handles all four canonical-preimage formats. It recomputes the receipt hash and confirms it matches the sealed hash field.

What the verifier checks

The verifier's job is the same across all four outcome states: recompute the canonical preimage and confirm its SHA-256 hash matches the sealed hash field.

For OK runs (ExecutionManifest):

The verifier reconstructs the canonical preimage from all 18 manifest fields (envelope, transport, DKEC outputs, AER, ZKSP, Sealing, ledger, registry, DLA) plus the AllowToken decision fields, recomputes SHA-256, and compares against manifest_hash.

For pepg_deny (DenyReceipt):

The verifier reconstructs the preimage from envelope_id, policy_hash, evaluation_hash, fired_rule_id, decision_reason_code, mcd_finding_hash (if present), deny_clock, evaluator_version, and version, then recomputes SHA-256 against the sealed hash.

For ccv_halt (CCVHaltReceipt):

The verifier reconstructs from envelope_id, allow_token_hash, budget_hash, constraint_type, budget_limit, consumed_at_halt, partial_execution_hash, halt_reason_code, halt_clock, evaluator_version, version, then recomputes SHA-256.

For macc_halt (MACCHaltReceipt):

The verifier reconstructs from envelope_id, tenant_id, allow_token_hash, budget_hash, constraint_type, budget_limit, cumulative_at_halt, per_run_consumption, window_start, halt_reason_code, halt_clock, evaluator_version, version, then recomputes SHA-256.

Machine-readable vs. human-readable output:

The verifier CLI outputs machine-readable JSON (--json flag) for programmatic consumption. The audit PDF renders a human-friendly presentation of the same verification outcome.

Strict mode

Three artifacts in the bundle honestly declare themselves as scaffold values, placeholders whose real cryptographic backing arrives in a later build phase (transcript, hardware_attestation, zksp_binding).

A fourth artifact, pote_proof, was historically scaffolded too. Its scaffold flag is now cleared automatically when the run was sealed against a real Sigstore Rekor ledger (the default for production runs). Runs sealed in mock-ledger mode (dev/test) still carry the flag.

In default mode the verifier passes on scaffold artifacts: their hashes still recompute correctly because the scaffold value is part of the canonical content. The orchestrator is being honest about what is and isn't yet rooted in real hardware.

For high-trust environments (FedRAMP High, certain DoD use cases) where nothing less than cryptographic root of trust counts, pass --strict:

verdifax-verify --strict --show-evidence-summary bundle.json

This makes the verifier exit 1 if any artifact carries scaffold.is_scaffold = true. The --show-evidence-summary flag prints a one-glance maturity report alongside the cryptographic verification, including an explanatory verdict line so a strict-mode failure is never mistaken for a cryptographic failure. Use this combined form as the gate in your CI; the exit code drives the gate, the summary explains the result.

Use in CI

A typical pipeline that wants to enforce both internal consistency and real hardware root of trust would call:

verdifax-verify --strict --json "$BUNDLE" > verdict.json
if [ $? -ne 0 ]; then
  echo "Bundle did not verify under strict mode."
  exit 1
fi

What the verifier does NOT prove

To set expectations honestly:

The verifier confirms internal consistency of a received bundle. It does not by itself prove that the underlying execution actually happened on Verdifax hardware. A malicious orchestrator could fabricate a bundle with consistent internal hashes. What the verifier rules out is the more common threat: evidence tampered with after the fact, someone modifying an actor id, a decision result, or a data classification on a real bundle and trying to pass it off as authentic.

For protection against fabrication, you also want:

  • Manifest hash anchored to a transparency log (Sigstore Rekor). ✓ Live in production: every successful run is committed as a hashedrekord entry on rekor.sigstore.dev, the same public transparency log used by the Linux kernel and major open-source releases. The bundle's external witness is the public log itself.
  • Hardware-rooted attestation (TPM2 quote / AMD SEV-SNP report) bound to specific silicon. Scaffold today, the hardware-attestation step is designed to bind the run to a measured platform, but currently emits a scaffold value. Activates on confidential-compute deployment. See /concepts/scaffold-gaps/ for the activation procedure.

The verifier reports honestly when scaffold values are in play; nothing claims to be more than it is.

Verifier version

The current verifier is v0.3.0 and understands all four sealed artifact types (AllowToken, DenyReceipt, CCVHaltReceipt, MACCHaltReceipt) plus legacy artifact formats. It auto-detects the artifact schema from the version field and dispatches the correct canonical-preimage reconstruction.

Source code

The verifier is MIT-licensed and lives in its own public repository:

github.com/Verdifax/verdifax-verify

You are encouraged to read the source, that is the entire point of an open-source verifier.