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: 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 anyone can verify offline.

  • Private

    Your prompts, your rows, your files and your credentials never reach EKKA.


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.

What can EKKA see?

Govern decides whether an action is allowed. It does that without seeing the content of the action. Prompts, model output, database rows, file contents: none of it reaches EKKA. What reaches EKKA is the shape of the request and cryptographic digests of the result.

We call this a No Knowledge Proof, and it has its own section below.

That property holds whether you run your own Enclave or use a hosted one. Where your data lives is a choice; not being read is not a choice.

What leaves your machine is the field-by-field detail, including the one thing we do receive when a run finishes and why.

What is a No Knowledge Proof?

A No Knowledge Proof is a record that proves what your agent did without containing what your agent handled. EKKA can stand behind that record because EKKA signed it, and EKKA never saw the contents.

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. Nobody can work backwards from the digest to the content, because the content was never put into it.

EKKA holds the thumbprint. The data it belongs to stays with you.

What that buys you

  • Your prompts, model output, database rows and file contents stay in your environment, so there is no copy of them on our side.
  • The proof still works. An auditor can confirm the record was not altered after the fact without ever seeing the data it describes.
  • It holds however you run EKKA, hosted or in your own Enclave. Where your data lives is a separate choice, and this does not depend on it.

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. This is blunter and easier to check: we signed it, and we never saw it.

It is also a claim about the content of an action, not about every field. When you dispatch a plan, the inputs you typed travel with it, because EKKA authorizes the call against them. What leaves your machine is the field-by-field list.

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. The sealing key is in the keychain, not in the files.

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

Some limits are structural, which means they hold even if every other check somewhere failed.

  • 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: a REVOKE on the runtime role and a trigger on top of it, because a REVOKE does not bind a table's owner.
  • 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 contact@ekka.ai, the address in our security.txt. Our full policy, including safe harbor and what to expect, is at ekka.ai/security.