Open source · Soroban · Stellar

Access control that fails closed.

Keygate is a capability-based authorisation stack for Soroban: a capability registry, policy rules, a circuit breaker that latches shut, and m-of-n multisig administration.

vault/src/lib.rs
let core = KeygateCoreClient::new(env, &core_id);
core.require_access(&caller, &resource, &action);

let breaker = KeygateBreakerClient::new(env, &breaker_id);
if breaker.enforce(&resource, &amount) == Outcome::Breached {
    // Skip, don't fail: an error would revert
    // the latch the breaker just wrote.
    return Ok(());
}

token.transfer(&vault, &caller, &amount);
4Soroban contracts
61contract unit tests
3repositories, Rust + TS
Apache-2.0licensed throughout
How it works

Three questions, three layers.

Every guarded call passes through each layer in order. Any one of them can say no, and none of them defaults to yes.

caller
Layer 1

keygate-policy

Do we permit this action at all, right now?

Layer 2

keygate-core

Does this holder still hold the capability?

Layer 3

circuit-breaker

Has this resource exceeded its budget in this window?

keygate-contracts

Four contracts, each with one job.

Kept separate on purpose: an incident response is one deny rule, not a bulk revocation, and deleting the rule restores exactly the state before it.

keygate-core

The capability registry. Issue, renew, revoke and check time-bound grants, with a two-step admin handover and a freeze switch.

registryttl grantspause

keygate-policy

Allow and deny rules per resource and action, in front of a registry. Deny takes an action out of service without touching hundreds of grants.

allow / denydefault effect

keygate-circuit-breaker

Rolling-window budgets that latch closed on a breach and stay closed until an explicit reset. One exploit cannot keep draining in small steps.

rolling windowlatching

keygate-multisig

m-of-n administration. Relays any encoded call once quorum approves, so the registry's admin key is never held by one person.

quorumcall relayowner rotation
Design

Built around how Soroban actually behaves.

Every rule below was verified against the real Soroban host in CI, not just the mocked one.

  • A breach is a value, not an error. A failed call loses its own writes, so the breaker reports Outcome::Breached and keeps the latch.
  • No self-re-entry. A contract cannot call itself, so owner rotation is applied inside the multisig's execute.
  • Lazy windows, lazy expiry. No cron job: windows roll forward on first use, so an idle resource costs nothing.
01 — fail closed

Missing means no.

An unconfigured resource, a missing grant or a paused registry rejects. The server mirrors this: if it can't prove yes, it answers no.

02 — latch

Tripping is sticky.

Time passing and raising the limit do not reopen a tripped breaker. Only an admin reset does.

03 — no single key

Admin through quorum.

Route every admin action through the multisig, so freezing issuance or repointing a policy takes m signatures.

The stack

Contracts, server and SDK.

Contracts hold capabilities on-chain. The server mirrors them from contract events and answers queries. The client builds the calls and checks server decisions before trusting them.

Contribute

Help build it.

Keygate is open source and part of the Drips Wave program. Pick up any issue labelled good first issue or help wanted in the repos above.