Skip to content

SECURITY AND GOVERNANCE

Nothing moves without permission

EKKA authorizes every action an AI agent takes before it happens, and signs every action it allows into a hash chain that verifies with EKKA switched off. An action without permission stops before any I/O (before anything is read, sent or run): no socket is opened, no DNS lookup is made, no credential is read from your vault.

This page is for the person who has to approve an AI agent touching a production system, and for the engineer they will ask.

Security and governance are one thing here, not two features sitting next to each other. A Grant is least privilege. Deny before I/O is access control. A receipt is the audit trail. Revoking a Grant is incident response.

Every claim on this page ships with the command that checks it, and every one of those commands runs on your own machine. A control you cannot test yourself is a control you are taking on trust.

Check the whole signed chain right now, with no EKKA service in the loop:

ekka receipts verify
  ✓ All 234 records check out.
    Nothing has been changed, added or removed since the first one.
    36 of them were signed by this machine's Enclave, and those signatures are valid.

  This ran entirely on your machine. It did not ask EKKA anything,
  which is the point: if checking our proof needed us, it would not be proof.
  • Governed

    Every action is authorized before it happens. No Grant, no I/O.

  • Proven

    Every allowed action is signed after it happens, into a chain you can verify offline on the machine that produced it.

  • Private

    Your private prompt templates can stay in your Enclave, where they are loaded and rendered locally. Governance records use references and hashes rather than those template bodies.


How does EKKA stop an agent before it acts?

An agent asks to do something. EKKA decides first, and a refusal is complete: no socket is opened, no DNS lookup is made, no secret is read from your vault.

The refusal itself is recorded as a signed event in your audit chain, the same chain an allowed action lands in. "It was blocked" is evidence, not a claim.

Preview any decision without executing it:

ekka gate postgres list --instance demoV1 --resource customers --check

Read the decision after the fact:

ekka run show <run-id>

--check reports ALLOWED or DENIED with no I/O and no cost. It is the same decision the real call gets.

A refusal and an allow are different shapes of the same evidence

An allowed action produces a signed receipt chain you verify offline against published keys. A refusal produces a signed deny event in your audit chain, carrying who was refused, what they asked for, and the reason code. There is no receipt for work that never ran.

Both are signed. Neither depends on our dashboard, or on us.

One thing we do not put in the chain: our own bugs. If EKKA cannot classify an operation or cannot parse a token it just issued, that is an error, not a decision about you. Recording it as a refusal would make "we were broken" indistinguishable from "you were not allowed".

How do I give an agent permission, and take it back?

You do not write access-control code. You set a Grant: this agent, this operation, this resource, through this gate, until you revoke it.

ekka gate grant list                 # what is authorized right now
ekka gate grant revoke <grant-id>    # the next attempt is refused, live

Revocation is not a deploy. The operation that worked a second ago is refused a second later, and the refusal is recorded like any other decision.

Grants are also time-boxed where you want them (--ttl), and the token a gate receives is issued just in time for one operation rather than held open.

A Grant is the third of three layers, and the only one you set per agent:

Layer The question Who sets it
Edition May EKKA offer this action to your organization at all? EKKA, for every organization
Enclave Does this machine have the gate, the key, the connection? You, on your machine
Grant May this agent use this resource for this action? Your signed-in session

The door exists. It does not mean the door is open. Every organization gets every capability, so a refusal is almost always the third layer, answering RESOURCE_GRANT_DENIED. The first layer answers ENTITLEMENT_FEATURE_DENIED, and how governance works has the longer version.

What can EKKA see?

With Enclave-local prompt storage, private template bodies stay out of the governance control plane. The Enclave loads and renders them locally. Governance records carry references and hashes rather than those template bodies.

This is the boundary behind a No Knowledge Proof, described below.

The control plane receives plan definitions and values explicitly submitted as inputs, including inline prompt text. Workflow values passed between steps or included in an approval can also reach the control plane. The selected model service receives the rendered prompt, through the EKKA AI Gateway when that connection is used.

What leaves your machine explains these data paths and the execution records in detail.

What is a No Knowledge Proof?

A No Knowledge Proof is a signed execution record that uses references and hashes instead of locally held content. Its integrity can be checked without putting private prompt template bodies or local step outputs into the record.

Think of a thumbprint

A thumbprint identifies a person with certainty. No two people share one, so matching a print to a person settles the question beyond argument.

Now try it the other way around. Look at a thumbprint on its own and say what that person looks like, what they are called, where they live. You cannot. The print answers who and carries nothing else about them.

A receipt works the same way. When your agent reads a row or writes a file, EKKA records a digest of it: a short string calculated from the content. Hand anyone the same content and they can calculate the same digest and confirm the record matches. The digest does not contain the content.

A signed execution record can hold the digest while the result stays in the Enclave. Passing the result to another step or an approval can send it through the control plane.

What that buys you

  • Private prompt templates and locally held step results are represented by references and hashes in governance records.
  • The proof still works. An auditor can confirm the record was not altered after the fact without ever seeing the data it describes.
  • The Enclave and model connection determine where content is processed.

Where the comparison stops

It is not zero-knowledge cryptography. Zero-knowledge is a specific branch of mathematics for proving a statement true while revealing nothing else about it. EKKA's record carries signed references and hashes for locally held content.

This is a property of the execution record. Plan definitions and inputs you submit reach the control plane, and the selected model service receives the rendered prompt through any configured gateway. What leaves your machine explains the boundary.

Check it yourself

Read the signed record of a run you just did, and look for your own data in it. The record names what was touched and carries the digests. The rows, the prompt and the file contents are not in there.

ekka receipts show <run-id>

Where do my credentials live?

Secrets live in your Enclave's vault, encrypted at rest and sealed by your operating system's keychain. The gate injects a credential into the outbound call; nothing upstream of it ever holds one.

ekka secret list        # names and metadata. Never values

Three consequences worth stating, because each one is a real attack that does not work here:

  • A caller cannot set an authorization header. The gate refuses the request rather than letting a plan overwrite the credential it was given.
  • A refusal never quotes the request. Error text cannot leak a credential that was sitting in a query string, because the message names the field and never the value.
  • Copying the vault files off the machine gets you nothing while the unlock key is kept apart. By default it is in the keychain; on a server, ekka enclave custody file keeps it in a file, so protect that file.

What can an agent not do, even with a Grant?

Some limits come from the shape of the request, so there is no check to skip.

  • A read cannot write. A read-class call has no slot on the wire for a method or a body. It is not that a check refuses the mutation, it is that there is nowhere to put one.
  • An origin is pinned. A connection reaches the host it was made for. It cannot be redirected to another.
  • Narrowing rules bind method and path together. A connection can be limited to GET /v1/messages and nothing else on the same host.
  • Network reach is declared. A connection states whether it may reach the public internet, your loopback, or your private network. The default refuses a local address outright.

Can anything change quietly?

  • A plan version is frozen when you create it. It runs the steps it was created with, and its name and number in the audit chain always mean those bytes. Fixing a plan makes the next version beside the old one. Check the bytes yourself: ekka plan show <plan> --verify recomputes the plan's fingerprint and says whether it still matches what was recorded when the version was created.
  • A skill version is never rewritten. Creating the same name again makes the next version. A plan naming @1.0.0 keeps running @1.0.0, and the body's SHA-256 is served with the skill, so an auditor can recompute it and prove which body a past run executed.
  • Cataloged APIs are immutable. Changing an API means a new version beside the old one, so a connection pinned to the old one keeps behaving.
  • Connection records are fingerprinted. A record altered on disk by anything other than EKKA is refused before the call is considered.
  • The audit trail is append-only, enforced in the database rather than by convention: the database refuses edits and deletes to the audit trail, even from EKKA's own service account.
  • A change to who may do what cannot be saved without its audit entry. For Grants, published Skills and organization settings, the database refuses the transaction unless the entry is written alongside the change. This is the other half of append-only: one stops an entry being removed, this one stops a change happening without an entry in the first place.

You cannot check our database privileges, so check the consequence

Append-only is enforced on our side, which means you cannot run a command against it, and a claim you cannot check is a claim you have to take on trust. That is not how the rest of this page works.

What you can check is the property it exists to produce: that nothing in your chain was altered after the fact. ekka audit verify recomputes every hash link and checks every signature against the key govern publishes at /.well-known/audit-signers. That key is public and the check runs on your machine, so this is not our word for it. If a row had been edited or removed, that is what would catch it, whatever our privileges say.

Note what it does not tell you: whether something that happened is missing from the chain in the first place. Integrity and completeness are different properties, and no amount of re-reading a chain settles the second one.

Completeness is built in rather than checked, for the records that decide who may do what: the change does not commit unless its entry commits with it. So the check you can run is the ordinary one, do the thing and look for it.

ekka gate grant add ...   # change what an agent may do
ekka audit list           # it is already there

If the entry had been missing, the first command would have failed. What that covers and what it does not is in Governance receipts.

How do I check EKKA's proof without EKKA?

ekka receipts verify

That recomputes every hash link and checks every signature against the identity that made it, on your machine, with no EKKA service in the loop. If checking our proof needed us, it would not be proof.

An auditor does not need an EKKA account, and does not need to trust your screenshot. They need the chain and the public keys.

ekka receipts verify covers the whole local chain and takes no run id. For one run, read its signed record with ekka receipts show <run-id>.

Governance receipts explains what a receipt contains and how to read one.

Does the CLI track me?

The ekka binary contains no third-party analytics. No product analytics, no session recording, no activation telemetry. Check the binary you installed:

strings $(which ekka) | grep -icE 'posthog|sentry\.io|segment\.io|amplitude\.com|mixpanel|datadoghq'

That prints 0. It is the exact list our release pipeline checks on every build, so the command you run is the check that gates the release rather than a friendlier version of it.

Crash reports are first-party, minimal, and optional. The error text stays on your machine, because a crash message can contain whatever the program was holding at the time.

export DO_NOT_TRACK=1     # or EKKA_CRASH_REPORTS=0

Which command proves which claim?

Every claim on this page, in one table.

The claim The command
A refusal happens before any I/O ekka gate <type> <op> --resource <name> --check
These are the permissions that exist right now ekka gate grant list
Revoking is live, not a deploy ekka gate grant revoke <grant-id>
Secrets are names to us, never values ekka secret list
This is every endpoint my Enclave contacts ekka enclave config
The proof verifies without EKKA ekka receipts verify
The decision record for one run, including a refusal ekka run show <run-id>
Nothing in my chain was altered after the fact ekka audit verify
A change to what an agent may do cannot happen unrecorded ekka gate grant add ... then ekka audit list
There is no analytics vendor in the binary strings $(which ekka) \| grep -icE 'posthog\|sentry\.io\|segment\.io\|amplitude\.com\|mixpanel\|datadoghq'

How do I report a vulnerability?

Write to [email protected], the address in our security.txt. Our full policy, including safe harbor and what to expect, is at ekka.ai/security.