Describe your model
Actions are what users can do. Roles bundle them. One JSON file in your repo, reviewed like any other change.
Roles, permissions and access checks for your product, running in your own Postgres. No seats, no per-check bill, no vendor sitting between your users and your data.
↳ local database, console and API in one command. nothing to sign up for.
Actions are what users can do. Roles bundle them. One JSON file in your repo, reviewed like any other change.
{ "actions": { "invoices.read": "Read invoices", "invoices.refund": "Refund invoices" }, "roles": { "viewer": ["invoices.read"], "finance": ["invoices.*"] } }
Keyring diffs the file against your database and applies only what changed. Dry-run first, prune when you mean it.
$ keyring push + create action invoices.read + create action invoices.refund + create role viewer + create role finance $ keyring grant finance user_123 ✓ user_123 now holds finance
One call, decided inside Postgres. No extra service, no cache to go stale, nothing a client can talk its way past.
import { createKeyring } from "@usekeyring/sdk/postgres"; const keyring = createKeyring({ database, // your pg / Neon pool apiKey: process.env.KEYRING_SECRET_KEY, }); await keyring.assert(user.id, "invoices.refund");
Schema, API, console, CLI — one MIT repo. Fork it, vendor it, ship it inside a commercial product. No open-core asterisk.
A schema and a set of functions in your own Postgres. Access data never leaves your infrastructure, and there's no meter running.
JSON output, a hint on every error, an MCP server and an AGENTS.md block. Claude and Cursor wire up permissions without guessing.
One command boots an embedded Postgres, the console and a local API. Every check you run lands in the event log, just like production.