Skip to Content
Signed Exports

Signed Exports

Signed exports are a Production+ feature. When your deployment has a signing key configured, successfully assembled compliance exports carry an Ed25519 manifest alongside the export payload.

Requesting a signed export

Use the compliance export surface:

POST /v1/compliance/exports GET /v1/compliance/exports GET /v1/compliance/exports/{id}

All three routes are GA. When the deployment has a signing key configured, exports include a manifest file automatically — no extra parameter is needed. (Operator setup details are part of the deployment guide rather than this public page.)

See Route Guarantees for the full trust properties of the compliance surface.

When a bulk export is refused

Bulk auditor-safe exports with chain entries are unavailable when the selected chain contains raw action arguments that fail the export privacy guard, even when their values are tokenized. Session action-permit records can contain these fields. Preserve the refusal and the original signed evidence; do not redact, rewrite or manufacture replacement chain entries. A narrower window is usable only if it contains compatible evidence and still supplies the claims you need.

The public GET /v1/permits/{permit_id}/proof-pack can supply a per-Permit decision-integrity pack for available signed decision evidence. Verify its declared claims with independently trusted signing material. This does not prove full-chain continuity, execution closure or an external effect. Missing lifecycle artifacts remain missing; a decision pack does not replace a refused bulk audit export.

Export types

The export_type field on the request determines the bundle contents. Production and Enterprise support the listed export types when a signing key is configured and the selected evidence passes export assembly and privacy checks.

export_typeBundle contents
governance_eventsGovernance event rows with their chain integrity metadata. Supports jsonl, json, and csv formats.
usageUsage log rows.
permitsPermit rows.
full_auditWith format: "json", a structured audit bundle with selected records and available linked evidence, usage, replay and requested chain entries. JSONL/CSV selections are record-only downloads.
soc2_evidenceSectioned jsonl bundle: summary, active_policy, policy_change, permit_sample, and governance_event records scoped to the requested window.
hipaa_auditSectioned jsonl bundle including permits, governed_requests, usage_ledgers, governance_decision_snapshots, permit_attestations, and execution lifecycle records.
vanta_evidenceDecision-centric JSON bundle for external compliance tooling ingestion. Must use format: "json".
financial_reconciliationUsage and billing reconciliation rows over the requested window. See Reconciliation for the pillar this export packages.
access_reviewSigned zip of CSVs covering users, organization members, team members, API keys, provider keys, and approver groups. Raw key material and key hashes are never included.
incident_evidenceSigned zip with governance_events.jsonl (chain metadata intact), permits.jsonl, admin_actions.jsonl, bracket_checkpoints.json (the last externally-anchored checkpoint before the incident window and the first after it), and incident_metadata.json. Available historical checkpoints are included where present; they are not guaranteed before/after anchors for a new incident. A window after the newest checkpoint has after_end_at: null until the next checkpoint is published.

A configured export signer supplies a manifest authenticating the delivered payload bytes. That does not give every payload format the same structural verification claims. Record-only JSONL or CSV downloads and sectioned/archive exports do not by themselves preserve the complete audit bundle, scope sidecars, or requested decision/closure envelope. For offline chain and closure verification, request full_audit with format: "json" and chain entries, download the complete proof-pack ZIP (in the dashboard, Download proof pack (.zip) on the export; the raw payload and manifest downloads are not sufficient), and preserve every extracted signed artifact and referenced sidecar. Follow Running Keel Verify; inspect the verdict for each requested claim.

Manifest shape

Every signed export carries a manifest alongside the export payload:

{ "export_id": "uuid", "project_id": "uuid", "export_type": "soc2_evidence", "format": "jsonl", "compressed": true, "record_count": 1547, "content_hash": "sha256:...", "signature": "ed25519:...", "public_key": "ed25519:...", "signed_at": "2026-04-14T00:00:00Z", "keel_version": "1.x", "chain_integrity": { "verified_at": "2026-04-14T00:00:00Z", "chain_length": 4521, "last_verified_hash": "sha256:..." } }
FieldMeaning
content_hashSHA-256 of the compressed export payload, hex-encoded with sha256: prefix
signatureEd25519 signature over the content hash, base64-encoded with ed25519: prefix
public_keyThe Ed25519 public key used to sign this export, included for independent verification
chain_integrity.chain_lengthLength of the project’s verified governance event chain at export time
chain_integrity.last_verified_hashHash of the last verified record in the chain at export time

Verifying an export independently

Exports can be verified offline after you obtain trusted signing material. Match the manifest’s key_id and public_key against the independently retrieved GET /v1/compliance/keys manifest or the verifier’s bundled production trust root. A public key embedded only in the artifact establishes self-consistency, not Keel authenticity.

A verifier must perform these steps:

  1. Recompute the SHA-256 of the compressed export payload.
  2. Compare the computed hash against content_hash in the manifest.
  3. Match the signing key and its active window against the trusted public key manifest or bundled root.
  4. Verify the Ed25519 signature over the content hash using that trusted key.
  5. Treat the chain_integrity snapshot as an informational summary, not as per-record attestation.

If any of the first four steps fails, do not accept the export as authentic Keel evidence.

An Ed25519 library can check the signature; independent trust material is also required to identify the signer.

Use released keel-verifier==3.28.0; its overall verdict passes only when every requested, required claim is supported. An export signature alone is not a chain or closure verdict.

For CISO review, request a full_audit JSON proof pack with chain entries and run the standalone verifier on its preserved JSON payload with --walk-events and --verify-closure, its signed key manifest, and independently obtained trusted signing material. See Independent Verification Overview and Running Keel Verify.

Key rotation

Operators can rotate the active signing key without re-signing historical exports. Existing exports remain verifiable using their original bytes and a retained trusted public key for the signing window. Do not trust a newly supplied key solely because it appears inside the historical artifact. The operator-side rotation procedure is part of the deployment guide.

What signed exports prove (and don’t prove)

They prove: The export payload has not been modified since it left Keel. Any modification to the compressed export file invalidates the Ed25519 signature.

They do not prove:

  • That every record that should be in the export is present. The manifest attests the content it received, not that the export is complete.
  • That the chain integrity snapshot covers every event ever written for the project. Chain length is a snapshot of the verified chain at export time.
  • Any per-record inclusion proof. See Trust & Integrity for the current limits of the integrity stack.
Last updated on Edit this page on GitHub