Skip to Content
Running Keel Verify

Running Keel Verify

This walkthrough shows how a signed audit export is independently verifiable against exported signing material, without relying on a Keel dashboard, support response, or private Keel system.

Use a clean terminal on a machine where you can preserve the original downloaded files. Do not edit, reformat, decompress, or re-compress the export bundle before verification.

1. Install keel-verify

Install the verifier using the distribution path your Keel contact provides.

python -m pip install keel-verifier

If your review process requires source pinning, clone the published verifier repository and run the script from that checkout.

git clone https://github.com/keelapi/keel-verifier.git cd keel-verifier python -m pip install -r requirements.txt

Confirm that the CLI is available.

keel-verify --help

2. Request a signed export from your Keel admin

Ask your Keel admin to create an audit export with chain entries included.

POST /v1/compliance/exports?include_chain_entries=true

For a scoped review, specify the relevant time window and an audit-grade export type such as full_audit, hipaa_audit, soc2_evidence, or incident_evidence.

curl -sS -X POST "https://api.keelapi.com/v1/compliance/exports?include_chain_entries=true" \ -H "Authorization: Bearer $KEEL_ADMIN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "export_type": "full_audit", "format": "json", "filters": { "created_at_from": "2026-05-01T00:00:00Z", "created_at_to": "2026-05-07T23:59:59Z" } }'

The important part is include_chain_entries=true. Without bundled chain entries, the verifier can still verify the export signature, but it cannot walk the event chain or verify permit closure evidence.

3. Download the export bundle and manifests

Download the export result from:

GET /v1/compliance/exports/{export_id}

Preserve these files exactly as downloaded:

FileExample nameNotes
Export bundlebundle.jsonThe audit export payload.
Export manifestexport-manifest.jsonThe signed manifest for the bundle.
Public key manifestpublic-key-manifest.jsonDownload from GET /v1/compliance/keys, or use --key-manifest-url.

For non-self-attested verification, prefer the public key manifest or a pinned key over relying only on a key embedded in the artifact.

4. Run the verifier

Run export verification, chain walking, and closure verification together.

keel-verify export \ --export-file bundle.json \ --manifest export-manifest.json \ --key-manifest public-key-manifest.json \ --walk-events \ --verify-closure

You can also fetch the key manifest at verification time.

keel-verify export \ --export-file bundle.json \ --manifest export-manifest.json \ --key-manifest-url https://api.keelapi.com/v1/compliance/keys \ --walk-events \ --verify-closure

The current source-script argument names are --export-file and --manifest. If your packaged binary accepts positional files, the equivalent command is the same export bundle plus export manifest, with --walk-events and --verify-closure enabled.

5. Interpret the output

Successful verification prints VERIFIED, then separate WALK-EVENTS: VERIFIED and VERIFY-CLOSURE: VERIFIED sections when you enabled both checks.

Verified export
VERIFIED
Export:       bundle.json
Content hash: sha256:7f4a0e2d4f0a6c7c1a9c8a0c1e2b3d4f5a6b7c8d9e0f1234567890abcdef1234
Signature:    ed25519:7n5e2i9Kq8nP4m1Zp0...
Public key:   ed25519:BASE64_PUBLIC_KEY...
Key id:       export-2026-annual
Trust source: key manifest (public-key-manifest.json) key_id=export-2026-annual status=active
WALK-EVENTS: chain_scope=project:6f38 first sequence_number=1028, prev_hash unverifiable from this bundle (continuity prior to window requires server-side verify_chain_integrity)
WALK-EVENTS: VERIFIED
chain_scopes:        1
entries_walked:      42
record_hash_checks:  42 PASS
prev_hash_checks:    41 PASS (excludes window-edge entries)
sequence_checks:     41 PASS
VERIFY-CLOSURE: VERIFIED
chain_scopes:        1
closures_verified:   9
signature_checks:    9 PASS
digest_checks:       18 PASS
dispatch_digest_check: PASS
Tampered export
VERIFIED
Export:       bundle.json
Content hash: sha256:7f4a0e2d4f0a6c7c1a9c8a0c1e2b3d4f5a6b7c8d9e0f1234567890abcdef1234
Signature:    ed25519:7n5e2i9Kq8nP4m1Zp0...
Public key:   ed25519:BASE64_PUBLIC_KEY...
Key id:       export-2026-annual
Trust source: key manifest (public-key-manifest.json) key_id=export-2026-annual status=active
FAILED: WALK_RECORD_HASH_MISMATCH: event_id=evt_01JX2EXAMPLE expected=sha256:8b8d1b6c... actual=sha256:4c41a991...

Read the output in layers:

  • VERIFIED means the export bundle matched its signed export manifest.
  • WALK-EVENTS: VERIFIED means the bundled chain entries recomputed and linked correctly inside the exported window.
  • VERIFY-CLOSURE: VERIFIED means closure signatures, dispatch request body bytes digests, and provider/client digest references matched the bundled evidence.
  • FAILED: <CODE>: means the verifier found a tampering signal or an untrusted format. Use the Tampering Detection Matrix.

6. What to do if verification fails

Treat any verification failure as an audit-integrity incident until disproven.

  1. Preserve the original export bundle, export manifest, public key manifest, verifier version, command, stdout, and stderr.
  2. Re-run the same command from a clean directory without modifying the downloaded files.
  3. Request a fresh export for the same time window and compare the failure.
  4. Confirm that the key manifest came from GET /v1/compliance/keys for the same Keel environment.
  5. Stop relying on the affected export in audit files until the failure is explained.
  6. Escalate to your Keel admin and to security@keelapi.com. Include the export ID, command, verifier version, error code, and file hashes.
  7. For incidents, request an incident_evidence export that brackets the affected window with the closest available checkpoints before and after the window.

Do not manually repair an export and then rely on the repaired copy. If the original fails verification, the original is the evidence.

Last updated on Edit this page on GitHub