KeyCard
KeyCard is a cross-language access-control library, strongly inspired by CASL.js. It lets you define an authorization policy once — in one place, in one format — and enforce it anywhere: server-side, client-side, in a different process, or in a completely different programming language.
This guide covers the language-agnostic concepts: the policy format, the condition language, and the evaluation rules every KeyCard implementation must follow. For installation instructions and language-specific API docs, use the Language selector in the navbar above, or jump straight to the JavaScript or Java guide.
Why KeyCard
Most authorization libraries tie you to one language and one runtime. KeyCard separates the two halves of the problem:
- Building a policy — a fluent, type-safe
PolicyBuilderAPI that turns a set ofallow/denyrules into aPolicyDefinition. - Evaluating a policy — a
Policyobject that answerscan(action, subject)questions against aPolicyDefinition.
A PolicyDefinition is a small, order-significant, JSON-encodable document.
Build it once in your backend of choice, hand the JSON to a browser, a mobile
client, or a service written in another language, and every one of them
evaluates the exact same rules the exact same way.
Core concepts
| Term | Meaning |
|---|---|
| Claims | The input used to build a policy — a JWT, a user record, anything |
| Action | What the user wants to do — Create, Read, Update, Delete, ... |
| Subject | What the user wants to do it to — Article, Project, ... |
| Rule | An [effect, action, subject, conditions?] tuple |
| PolicyBuilder | Fluent API that turns claims into a PolicyDefinition |
| PolicyDefinition | The serializable, JSON-encodable output of a builder |
| Policy | The object you actually call .can() / .cannot() / .require() on |
See the Glossary for the complete list of terms.
A minimal policy
version: "1.0" # KeyCard policy spec version (SemVer)
meta:
actions: [ Create, Update, Delete ]
subjects: [ Article ]
rules:
- [ allow, Create, Article ] # anyone may create an article
- [ allow, Update, Article, { owner_id: 1 } ] # only the owner may update
- [ deny, Delete, Article, { status: { $not: "archived" } } ] # can't delete unless archived
rulesis a single, order-significant list. The last matching rule wins — it is not "any deny beats any allow."- Every policy has an implicit wildcard token,
_ANY_, for both actions and subjects (e.g.[allow, _ANY_, _ANY_]matches anything). A policy may rename or disable either wildcard viameta.anyAction/meta.anySubject. - With no matching rule, the default is deny.
Continue to Policy Definition for the full structure,
or Condition Operators for the condition language
used in the conditions slot of a rule.
Normative specification
This guide is an informal overview. The exact rule-evaluation algorithm, the full condition-operator table, and the catalogue of required edge-case behavior live in the normative v1.0 specification, which every language implementation is validated against with a shared conformance suite.