Typed permissions for apps, APIs, databases and AI agents
Define a policy once in TypeScript. Check it in React, on the server and in agent tools; compile the same conditions to SQL and Postgres RLS.
Why PermDock
Authorisation as typed code, checked everywhere it runs
One policy object drives the UI, the HTTP layer, the database and the agent tools.
Typed references
Three outcomes
Conditions compile to SQL
Agent tools behind the same policy
- search_docsgranted
- refund_invoiceapproval-required
- delete_orgdenied
UI that matches the server
Fail-closed
Every surface
One decision, every surface
The same permission reference drives UI, HTTP, MCP tools, agent runtimes and generated RLS.
Interactive
decide() in the browser
A real PermDock policy. Switch role and action to see granted, denied and approval-required.
Portable-first
One where, three compilers
The same condition evaluates in memory, compiles to Drizzle, Prisma and Kysely, and generates Postgres RLS. Closures stay a branded escape hatch.
Agent-native
The same Decision gates the tool call
granted, denied and approval-required map onto MCP, the Vercel AI SDK, the Claude Agent SDK, Eve, OpenAI Agents, WebMCP and A2A. An agent never approves its own call.
Secure by default
Invariants, not a later pass
A PR that breaks one of these is wrong, whatever else it does.
Works with
Adapters you already ship
Each tile is a first-class entry. The public API is typed permission references, never string keys.
UI
HTTP and RPC
Agents
Data
Auth
Get started
Install, define, grant, decide
Install
pnpm add permdock
Define
definePermissions with resource() over the schema you already have.
Policy
definePolicy with role(), allow() and portable conditions.
Decide
createPermDock, then can(), decide() or assert() on every surface.
Optional
The Cloud is optional
Every hosted capability has an in-process default. A store or sink never influences an outcome. Cloud outages do not change can() or decide().
Before you adopt
Licensing, network, fail-closed, and where authentication lives.
The library is MIT. Every decision runs in-process. PermDock Cloud is optional and never sits on the decision path.
Ship the check with the feature
Install the package, define the resources you already have, and put decide() on the route, the tool and the query.