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_type | Bundle contents |
|---|---|
governance_events | Governance event rows with their chain integrity metadata. Supports jsonl, json, and csv formats. |
usage | Usage log rows. |
permits | Permit rows. |
full_audit | With 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_evidence | Sectioned jsonl bundle: summary, active_policy, policy_change, permit_sample, and governance_event records scoped to the requested window. |
hipaa_audit | Sectioned jsonl bundle including permits, governed_requests, usage_ledgers, governance_decision_snapshots, permit_attestations, and execution lifecycle records. |
vanta_evidence | Decision-centric JSON bundle for external compliance tooling ingestion. Must use format: "json". |
financial_reconciliation | Usage and billing reconciliation rows over the requested window. See Reconciliation for the pillar this export packages. |
access_review | Signed 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_evidence | Signed 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:..."
}
}| Field | Meaning |
|---|---|
content_hash | SHA-256 of the compressed export payload, hex-encoded with sha256: prefix |
signature | Ed25519 signature over the content hash, base64-encoded with ed25519: prefix |
public_key | The Ed25519 public key used to sign this export, included for independent verification |
chain_integrity.chain_length | Length of the project’s verified governance event chain at export time |
chain_integrity.last_verified_hash | Hash 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:
- Recompute the SHA-256 of the compressed export payload.
- Compare the computed hash against
content_hashin the manifest. - Match the signing key and its active window against the trusted public key manifest or bundled root.
- Verify the Ed25519 signature over the content hash using that trusted key.
- Treat the
chain_integritysnapshot 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.
Related pages
- Independent Verification Overview — what a CISO can prove independently
- Running Keel Verify — step-by-step verifier workflow for signed exports
- Trust & Integrity — the full four-layer integrity stack
- Route Guarantees — trust properties per route
- Configuration Reference — operator configuration categories for deployed Keel runtimes