GOVERNANCE RECEIPTS
Proof you can check yourself¶
A receipt is the signed record of one governed step: what was read, which model or tool ran, and under which Gate Token. A run's receipts are linked into a hash chain, so changing, removing or reordering any one of them visibly breaks it.
This page is for the person who has to show somebody else what an AI agent actually did.
What makes it evidence rather than a log: you verify it, offline, against published keys. No dashboard is required, not even ours. A proof that needed us to confirm it would not be a proof.
Plain English up top, mechanics for developers and auditors one tab over.
Check the whole chain on your own machine, with no EKKA service in the loop:
Why anyone should believe a receipt
EKKA can prove what your agent did without ever having seen your data. The signature covers what happened, not what was in it. That is a No Knowledge Proof: EKKA holds a thumbprint of the content, which identifies it beyond argument and cannot be run backwards to recover it. The thumbprint, explained in full.
It holds however you run EKKA, hosted or in your own Enclave. Where your data lives is a separate choice, and this claim does not depend on it.
What records does a run leave?¶
Every run leaves two complementary records:
| Command | What it is | Where it lives |
|---|---|---|
ekka receipts show <run-id> |
The receipt chain: the Gate Token issued, each gate's signed receipt, and the closing run attestation, all linked by hash. | Your Enclave's local audit chain, on your machine. |
ekka run show <run-id> |
EKKA's allow / deny decision for the run and each step. | EKKA Govern's authoritative record. |
Use ekka receipts show for the cryptographic proof of what executed; use
ekka run show for the governance decision, especially for a denied action,
which produces a decision but no receipt chain (nothing ran, so nothing was
signed).
What is in a receipt?¶
Each entry in the chain carries:
- a kind, which step it records;
- a sequence number and a link to the entry before it (a fingerprint of the previous receipt);
- a signed envelope and its claims, the facts of the step (which resource, which token, actor, timestamps, and hashes of the inputs/outputs).
The kinds you'll see (the label ekka receipts show prints → the actual kind
string on the wire):
| What the CLI prints | kind |
|---|---|
| Gate Token issued | kat_issued |
| Knowledge Gate receipt (a database-gate read) | knowledge_gate_receipt |
| LLM Gateway receipt (an AI-model-gate call) | llm_gateway_receipt |
| The tool-gate receipt (on MCP tool calls) | (the tool gate's receipt) |
| Local operation receipt (a File Gate action) | local_op_receipt |
| Run attestation (the closing summary) | run_attestation |
Which of these carry a signature
The Gate Token is signed by EKKA. Each gate receipt is signed by the gate that served the action, and your Enclave checks that signature at the moment it records the receipt. A local operation receipt is signed by your Enclave's own enrolled identity key.
The run attestation is the one exception. It is the closing summary, and it carries no signature of its own. It is a SHA-256 hash chain, and it is trusted because your Enclave's session was live and EKKA can revoke that session at any time. It is still evidence, and it is tamper-evident through the hash chain, but it is a different kind of evidence from a signature. Anyone who checks will find this, so we say it here.
Why can the chain not be faked?¶
This is the important part, and it's the same idea people already know from blockchain.
Like a blockchain ledger, every receipt is cryptographically linked to the one before it, so you can't quietly rewrite history, change, remove, or reorder any entry and the links stop matching. The difference: your chain is private to your run, no coins, no mining, no public network, just the tamper-evidence.
Two properties do the work. Here they are in three depths, pick your lens:
- Signed = a wax seal. EKKA and each gate stamp every receipt with a secret only they hold. You can check the seal is genuine; no one can forge it. So a receipt can't be faked, and EKKA can't later deny issuing one.
- Chained = numbered pages that quote each other. Each receipt carries a fingerprint of the page before it. Tear one out, change a word, or shuffle the order, and the fingerprints no longer line up, tampering is obvious.
- Yours to check. You don't take anyone's word for it: you re-run the check yourself, even offline, against EKKA's public seals.
- Signatures. Each step emits a signed envelope (JWS-style): the claims are signed with the issuer's private key, each gate (a database gate, an AI-model gate, a tool gate) and EKKA itself, each with its own key. You verify with the matching public key from EKKA's published key set. A valid signature proves both the issuer and that the payload wasn't altered.
- Hash chain. Each receipt stores
prev_hash, a cryptographic hash of the previous receipt (the first links to a genesis marker). Recomputing the hashes end-to-end detects any insert, delete, reorder, or single-byte edit. This is exactly the Merkle/blockchain construction, scoped to one run. - Independent + offline. Verification needs only the chain plus EKKA's public keys, no live call to EKKA, so the proof survives even if EKKA is unreachable.
- Authenticity & non-repudiation, every step is signed by its issuer, so its origin is provable and cannot be disowned after the fact.
- Integrity / tamper-evidence, the hash chain makes any alteration, omission, or reordering detectable; the evidence defends itself and does not depend on a trusted log store.
- Independent verification, assurance rests on public-key cryptography you can check yourself, not on trust in EKKA's UI or infrastructure.
- Complete decision record, in two halves that live in two places. The
local chain holds what ran. A denied action never runs, so it
leaves no local receipt; EKKA Govern records the denial and its reason in
its own authoritative record, which you read with
ekka run show. So the absence of an action is provable, but you prove it against Govern's record, not against the offline chain.
How do I verify it myself?¶
This recomputes every prev_hash link in the chain, and re-checks the
signature on every local operation receipt against the identity key your
Enclave enrolled with, entirely on your machine, no network required. It
takes no run id and covers the whole local chain; to read one run's record, use
ekka receipts show <run-id>. If a single field, receipt, or ordering had been
touched, the hash chain breaks and verification fails. The guarantee doesn't
rest on trusting a dashboard; it rests on math you can re-run.
Gate receipt signatures are checked when the receipt arrives, against the key EKKA pinned for that gate, before your Enclave writes it down. So a gate signature is verified once, at the only moment an attacker could have swapped it, and the hash chain protects it from then on.
What does a denied action leave behind?¶
- An allowed run produces a full chain, Gate Token → gate receipts → run summary.
- A denied action produces no receipt chain, by design: EKKA refuses it
before the Enclave does any work, so there is nothing to sign. The refusal is
recorded as a decision instead, see it with
ekka run show <run-id>(e.g.RESOURCE_GRANT_DENIED). Proving that something did not happen is exactly what an auditor needs, and the deny decision is that proof.
In your dashboard¶
Your organization's dashboard shows the governance record for each run, the
decision per step, the tokens exercised, and the plan that ran, so your team can
review runs without the CLI. The signed cryptographic chain stays on the Enclave
via ekka receipts show for independent, offline verification.
What the chain does and does not prove¶
The chain proves integrity: nothing in it was altered, reordered or removed.
ekka audit verify recomputes every hash link and every signature.
Completeness is a different claim: that everything which happened is in the chain. Re-reading the chain can never prove this one, because an action that wrote no entry leaves a chain that still verifies perfectly. It has to be built in instead.
For the records that decide who may do what, it now is. Issuing or revoking a Grant, publishing a Skill, changing your organization's settings: the database refuses to commit the change unless the audit entry is written in the same transaction. Not checked afterwards, and not checked by us remembering to. The change and its record land together, or neither lands.
That is a real check, not a reassurance. If the entry had been missing, the first command would have failed.
Where this stops¶
Five kinds of record are protected this way today, not everything EKKA stores. Some tables mix a decision with routine machine bookkeeping. A running Enclave reports that it is still alive every few seconds, on the same row that records who claimed it, and demanding an audit entry per heartbeat would bury the decisions rather than record them.
Those are guarded a weaker way, and it is worth being plain that it is weaker: a build check refuses any new code path that changes authority without recording it. That catches a developer who forgets. It cannot catch a change made by some other route, which is exactly what the database constraint above does catch.
Refusals are in the chain too, so a denied action is as provable as an allowed one.
Why does this matter?¶
The hardest thing in compliance is proving a negative, that your AI never touched something it shouldn't. Because a resource you never granted can never appear in the chain, the signed record proves the AI never read it. That's the difference between an AI feature that is an audit liability and one that is an audit asset.