Skip to content
Comparison

Comparison

The comparison that matters is not evaluator against evaluator — it is how much of the authorization problem is solved when policies are data, written at runtime by admins and agents rather than compiled from files. That problem has five parts: deciding, storing, validating, auditing, and administering. This library ships all five, in your process, against your own database.

agentauthzCedarOpenFGA / SpiceDB / Ory KetoCasbin
Complete out of the box — decide + store + validate + audit + administerall fiveevaluator onlycheck service; the rest variesevaluator + thin adapters
Extra infrastructure to runnone — in-processnone (WASM from JS)a stateful service to deploy, scale and keep upnone
Policies authored at runtime by admins and agentsfirst-class: schema-validated rows, errors named so a UI shows them verbatimbuild it yourselftuples via APIreload from files/adapters
Storageshipped — Postgres with migrations and at-rest checks — and swappable: any backend passing the conformance fixtures is decision-identicalbring your ownthe service’s internal storethin adapters
A deny whose condition cannot be evaluatedthe deny stands — fail closedthe erroring policy is skipped — the deny silently liftsn/a (graph model)depends on the matcher
Safe for untrusted policy authorsby construction: no expression language, closed action vocabulary, no action wildcardsfull expression language to reviewn/amatchers are evaluated expression strings
Per-decision audit trailbuilt in, fire-and-forgetbuild it yourselfvariesbuild it yourself
Admin surfaceserved as data: the descriptor + framework-free handlers; one UI fits any hostbuild it yourselfservice APIsbuild it yourself
Runtime dependencieszero (kysely optional, for the pg backend)WASM bindingclient SDK + serverdependency tree

The deny row deserves a sentence: an engine that skips an erroring policy fails open at the exact place the author asked it to fail closed. Here, an allow needs a definitive match and a deny stands on anything less than a definitive miss — both directions resolve toward less access. That asymmetry is the design center, and it is pinned by conformance fixtures any alternative backend must reproduce.

Any authentication

The engine is deliberately blind to authentication: it never sees a credential, a token, or a session. The host resolves the caller — through any OIDC provider (Ory Kratos/Hydra, EntraID, Auth0, Keycloak, …), its own native users, API keys, or mTLS — into explicit {kind, id} subjects before the check. Swapping identity providers never touches a policy, a grant, or a call site, and machine principals are the same shape as human ones.

Different problems

Two things in that table’s neighborhood are different products, not missing features:

  • Formally verified evaluation of a policy language is Cedar’s product. If your policies are written by engineers, reviewed in git, and shipped with deployments, Cedar’s verification and analysis tooling are the point — and storage, audit and administration being your problem is fine, because your CI is the admin surface.
  • Graph questions at scale — “list everything alice can see” over millions of relationships — are what Zanzibar-shaped services (OpenFGA, SpiceDB, Ory Keto) exist to answer. That is a reverse-index query shape, not a check, and it justifies running the extra service when you have it.

This library asks a narrower question — may this subject do this action on this resource, right now — and answers it with everything around the answer already built.