permdock 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/README.md +268 -1
  2. package/dist/a2a/index.d.ts +178 -0
  3. package/dist/a2a/index.js +271 -0
  4. package/dist/ai-sdk/index.d.ts +74 -0
  5. package/dist/ai-sdk/index.js +137 -0
  6. package/dist/approval-required-TzNB9oQA.js +6 -0
  7. package/dist/approvals/index.d.ts +3 -0
  8. package/dist/approvals/index.js +4 -0
  9. package/dist/approvals-DaxY-Bdg.js +218 -0
  10. package/dist/approvers-aH0PJkmf.js +20 -0
  11. package/dist/arazzo-CTeVuXr5.js +70 -0
  12. package/dist/arazzo-aoTkqYsJ.js +54 -0
  13. package/dist/authzen/index.d.ts +48 -0
  14. package/dist/authzen/index.js +336 -0
  15. package/dist/better-auth/index.d.ts +92 -0
  16. package/dist/better-auth/index.js +324 -0
  17. package/dist/budget-JqcRqyhK.d.ts +11 -0
  18. package/dist/budget-NbEtbJC_.js +11 -0
  19. package/dist/capability-B68OFnZx.js +171 -0
  20. package/dist/capability-BDG_nkxt.d.ts +99 -0
  21. package/dist/catalog/index.d.ts +12 -0
  22. package/dist/catalog/index.js +2 -0
  23. package/dist/catalog-B0E6bggc.js +48 -0
  24. package/dist/catalog-H-vFGwWK.js +55 -0
  25. package/dist/catalog-doc-BSo_Q_-6.js +298 -0
  26. package/dist/catalog-idsHc0vo.js +2 -0
  27. package/dist/catalog-path-CnI0XTFK.js +12 -0
  28. package/dist/claude-agent/index.d.ts +81 -0
  29. package/dist/claude-agent/index.js +83 -0
  30. package/dist/clerk/index.d.ts +56 -0
  31. package/dist/clerk/index.js +280 -0
  32. package/dist/cli/bin.d.ts +1 -0
  33. package/dist/cli/bin.js +20 -0
  34. package/dist/cli/index.d.ts +46 -0
  35. package/dist/cli/index.js +5 -0
  36. package/dist/cloud/index.d.ts +91 -0
  37. package/dist/cloud/index.js +390 -0
  38. package/dist/cloud-BNQTrmrr.js +50 -0
  39. package/dist/cloud-Cuxr6Czw.js +117 -0
  40. package/dist/collect-B7_TIfmg.js +49 -0
  41. package/dist/collect-O-tOtbnk.js +350 -0
  42. package/dist/collect-fRPAQIWb.js +2 -0
  43. package/dist/commands-BMh_Etm2.js +93 -0
  44. package/dist/compact-y6vfu2_f.js +19 -0
  45. package/dist/compare-pfyVnBjE.js +12 -0
  46. package/dist/compile-CQbvyIBr.d.ts +30 -0
  47. package/dist/compile-D22iwvuV.js +558 -0
  48. package/dist/config-BPYmjTOp.js +26 -0
  49. package/dist/connection-JvqwHODC.js +194 -0
  50. package/dist/context-CKEAabd7.js +73 -0
  51. package/dist/context-gtAwAILx.js +6 -0
  52. package/dist/convex/index.d.ts +40 -0
  53. package/dist/convex/index.js +55 -0
  54. package/dist/create-BKF3dgFk.d.ts +162 -0
  55. package/dist/create-CSkhDU9T.js +222 -0
  56. package/dist/credential-B_rkUNlY.js +326 -0
  57. package/dist/credentials-BgRX3WEg.js +268 -0
  58. package/dist/describe-Bt1YD5uS.js +99 -0
  59. package/dist/describe-DernyItf.d.ts +37 -0
  60. package/dist/diff-BUzf5Poi.js +48 -0
  61. package/dist/diff-x5Il8LVa.js +418 -0
  62. package/dist/digest-B3kc_PgQ.d.ts +19 -0
  63. package/dist/digest-BI-6aa6d.js +27 -0
  64. package/dist/doctor-BGle8Gqi.js +1314 -0
  65. package/dist/doctor-Bqo6FwUa.js +53 -0
  66. package/dist/drizzle/index.d.ts +72 -0
  67. package/dist/drizzle/index.js +160 -0
  68. package/dist/duration-xK2jGFVc.js +25 -0
  69. package/dist/elysia/index.d.ts +71 -0
  70. package/dist/elysia/index.js +103 -0
  71. package/dist/errors-DSMnAVNa.js +43 -0
  72. package/dist/errors-DbZ1YOnb.d.ts +138 -0
  73. package/dist/errors-Iy71s7Oj.js +177 -0
  74. package/dist/errors-m3u9TmDu.js +27 -0
  75. package/dist/evaluations-DsAU9ppl.js +479 -0
  76. package/dist/eve/index.d.ts +95 -0
  77. package/dist/eve/index.js +181 -0
  78. package/dist/express/index.d.ts +46 -0
  79. package/dist/express/index.js +108 -0
  80. package/dist/fastify/index.d.ts +56 -0
  81. package/dist/fastify/index.js +141 -0
  82. package/dist/files-B_wAGYmt.js +121 -0
  83. package/dist/fixtures-Cvaw0gDG.js +64 -0
  84. package/dist/freeze-y1_jQL4v.js +31 -0
  85. package/dist/from-snapshot-BMGnhmgv.js +552 -0
  86. package/dist/generate-CH7ThJ14.js +173 -0
  87. package/dist/grantee-Bv04_Vzf.js +521 -0
  88. package/dist/headers-B5RRv3Xm.js +6 -0
  89. package/dist/headers-C8SHQccD.d.ts +6 -0
  90. package/dist/helpers-DnSOrhB9.js +682 -0
  91. package/dist/hono/index.d.ts +70 -0
  92. package/dist/hono/index.js +131 -0
  93. package/dist/hosted-BwKQ1BTA.js +265 -0
  94. package/dist/http-DPuDaChb.d.ts +13 -0
  95. package/dist/http-GgVApX1k.js +111 -0
  96. package/dist/index-CltcQ4Bf.d.ts +138 -0
  97. package/dist/index-LF_hS-yn.d.ts +177 -0
  98. package/dist/index-fG6NSXlc.d.ts +9 -0
  99. package/dist/index-xIxJLwOQ.d.ts +415 -0
  100. package/dist/index.d.ts +11 -0
  101. package/dist/index.js +21 -0
  102. package/dist/jwt/index.d.ts +87 -0
  103. package/dist/jwt/index.js +571 -0
  104. package/dist/kernel-YOGCWNLf.js +211 -0
  105. package/dist/kysely/index.d.ts +77 -0
  106. package/dist/kysely/index.js +129 -0
  107. package/dist/load-BZ24CpZP.js +69 -0
  108. package/dist/load-QOOm1z70.js +2 -0
  109. package/dist/load-jose-BL6LH4bL.js +11 -0
  110. package/dist/lru-8q4WZjBV.js +28 -0
  111. package/dist/manifest-DDQbC6K0.d.ts +118 -0
  112. package/dist/map-DowSO96j.js +158 -0
  113. package/dist/map-claims-B_6I1Rn-.js +360 -0
  114. package/dist/map-error-RJ3ZsUyA.js +16 -0
  115. package/dist/markers-B0hYLvMD.js +60 -0
  116. package/dist/may-use-CnFEjVEp.js +37 -0
  117. package/dist/mcp/index.d.ts +127 -0
  118. package/dist/mcp/index.js +563 -0
  119. package/dist/nest/index.d.ts +80 -0
  120. package/dist/nest/index.js +270 -0
  121. package/dist/next/client.d.ts +24 -0
  122. package/dist/next/client.js +31 -0
  123. package/dist/next/index.d.ts +110 -0
  124. package/dist/next/index.js +195 -0
  125. package/dist/next/plugin.d.ts +14 -0
  126. package/dist/next/plugin.js +2 -0
  127. package/dist/node/index.d.ts +43 -0
  128. package/dist/node/index.js +66 -0
  129. package/dist/openai/index.d.ts +71 -0
  130. package/dist/openai/index.js +105 -0
  131. package/dist/openapi/index.d.ts +93 -0
  132. package/dist/openapi/index.js +3 -0
  133. package/dist/openapi-CwePaF7C.js +164 -0
  134. package/dist/openapi-DWD0Uc_4.js +250 -0
  135. package/dist/openapi-DcqM8nU7.js +306 -0
  136. package/dist/openapi-import-BWRUNNeW.js +5959 -0
  137. package/dist/openapi-schema-D8j_T9tO.js +6902 -0
  138. package/dist/orpc/index.d.ts +64 -0
  139. package/dist/orpc/index.js +188 -0
  140. package/dist/otel/index.d.ts +13 -0
  141. package/dist/otel/index.js +202 -0
  142. package/dist/package-root-zGkxO3oN.js +30 -0
  143. package/dist/parse-DPfIvFMU.js +135 -0
  144. package/dist/pdp/index.d.ts +22 -0
  145. package/dist/pdp/index.js +795 -0
  146. package/dist/peer-BOr_kJE1.js +31 -0
  147. package/dist/permdock-yoZ7EjxX.js +2956 -0
  148. package/dist/permissions-B4apnahQ.d.ts +185 -0
  149. package/dist/permissions-B8vCg_bI.d.ts +52 -0
  150. package/dist/permissions-CofRqesP.js +142 -0
  151. package/dist/permissions-DC7GROPA.js +600 -0
  152. package/dist/pg-4GJWDUxG.js +953 -0
  153. package/dist/pins-CqE1jZuF.js +12 -0
  154. package/dist/plugin-4gr7IxFJ.js +65 -0
  155. package/dist/policy-ANp36PnI.js +971 -0
  156. package/dist/policy-CInmNGkM.d.ts +1959 -0
  157. package/dist/policy-Cq2fB8Q5.d.ts +20 -0
  158. package/dist/prisma/index.d.ts +135 -0
  159. package/dist/prisma/index.js +430 -0
  160. package/dist/problem-Cgp9-KZA.js +226 -0
  161. package/dist/prompt-CXYhLfsS.js +32 -0
  162. package/dist/protected-B4K3BKoX.js +138 -0
  163. package/dist/protected-BuPAycJT.d.ts +26 -0
  164. package/dist/protected-wY7nXhY9.d.ts +23 -0
  165. package/dist/provider-_wx46HpB.js +48 -0
  166. package/dist/provider-wTAUda2v.d.ts +6 -0
  167. package/dist/react/index.d.ts +6 -0
  168. package/dist/react/index.js +6 -0
  169. package/dist/react/provider-client.d.ts +2 -0
  170. package/dist/react/provider-client.js +3 -0
  171. package/dist/react-native/index.d.ts +42 -0
  172. package/dist/react-native/index.js +174 -0
  173. package/dist/refs-ChLSxbST.js +90 -0
  174. package/dist/relations-r4soIFZB.js +426 -0
  175. package/dist/revocations-Cy06JNx2.d.ts +21 -0
  176. package/dist/rls-BOFU3chG.js +233 -0
  177. package/dist/rls-CJVja9Ww.js +2119 -0
  178. package/dist/rls-graph-DxQ39PJj.js +371 -0
  179. package/dist/rls-helpers-BxRuif0l.js +1346 -0
  180. package/dist/rls-import-CXV6LBlS.js +942 -0
  181. package/dist/rls-migrate-DrFPbf8p.js +366 -0
  182. package/dist/row-check-BajTgQZ-.d.ts +43 -0
  183. package/dist/run-CJ6UvS3a.js +155 -0
  184. package/dist/runtime-DP9ttFh1.js +27 -0
  185. package/dist/saas-BRrZzJkM.js +1193 -0
  186. package/dist/schema-P8yoma__.js +296 -0
  187. package/dist/scim/index.d.ts +2 -0
  188. package/dist/scim/index.js +2 -0
  189. package/dist/scim-9NFa0XVZ.js +1445 -0
  190. package/dist/scopes-cKVp_WTw.js +212 -0
  191. package/dist/server/index.d.ts +123 -0
  192. package/dist/server/index.js +8 -0
  193. package/dist/sha256-BO0swRXL.js +150 -0
  194. package/dist/sink-Bd9PSyfq.js +141 -0
  195. package/dist/sink-Cfr9-7YC.d.ts +104 -0
  196. package/dist/skills-C_lpV4Jx.js +50 -0
  197. package/dist/skills-Dx3QLnMY.js +110 -0
  198. package/dist/snapshot-DE8dE_hz.js +1051 -0
  199. package/dist/solid/index.d.ts +63 -0
  200. package/dist/solid/index.js +197 -0
  201. package/dist/source-DoBBYJi2.js +6 -0
  202. package/dist/sources-DOpW5Ila.d.ts +347 -0
  203. package/dist/sources-DVHM3Mwq.js +284 -0
  204. package/dist/sql-Bll1d7y0.js +22 -0
  205. package/dist/src-CTNT-PBW.js +430 -0
  206. package/dist/ssf/index.d.ts +3 -0
  207. package/dist/ssf/index.js +622 -0
  208. package/dist/store-Bq90395i.d.ts +27 -0
  209. package/dist/store-C6hFW6ta.js +508 -0
  210. package/dist/stores-CkG2HrSg.js +140 -0
  211. package/dist/stores-CvOnu_2T.d.ts +41 -0
  212. package/dist/stream-BhMfZOwr.d.ts +12 -0
  213. package/dist/stream-Q_xlB6Ko.js +52 -0
  214. package/dist/style-CTm1AXDT.js +22 -0
  215. package/dist/subject-C6dLxqHU.js +24 -0
  216. package/dist/subject-settings-xt7V845g.js +82 -0
  217. package/dist/supabase/index.d.ts +67 -0
  218. package/dist/supabase/index.js +4 -0
  219. package/dist/supabase/middleware.d.ts +77 -0
  220. package/dist/supabase/middleware.js +68 -0
  221. package/dist/supabase-D8UlBA7Z.js +83 -0
  222. package/dist/supabase-DTxGtYdi.js +796 -0
  223. package/dist/supabase-hook-DW-xP4hU.js +2 -0
  224. package/dist/supabase-hook-D_OqGb_V.js +1528 -0
  225. package/dist/svelte/Protected.svelte +34 -0
  226. package/dist/svelte/index.d.ts +10 -0
  227. package/dist/svelte/index.js +53 -0
  228. package/dist/svelte/runtime.d.ts +6 -0
  229. package/dist/svelte/runtime.js +3 -0
  230. package/dist/svelte/source.d.ts +10 -0
  231. package/dist/svelte/source.js +8 -0
  232. package/dist/terminal/index.d.ts +171 -0
  233. package/dist/terminal/index.js +821 -0
  234. package/dist/testing/index.d.ts +656 -0
  235. package/dist/testing/index.js +3208 -0
  236. package/dist/testing/saas/index.d.ts +194 -0
  237. package/dist/testing/saas/index.js +3 -0
  238. package/dist/testing/saas/permissions.d.ts +2 -0
  239. package/dist/testing/saas/permissions.js +2 -0
  240. package/dist/text-diff-BdkkYSbi.js +15 -0
  241. package/dist/thenable-okc2xDsj.js +10 -0
  242. package/dist/timeout-D51niuQP.js +8 -0
  243. package/dist/trpc/index.d.ts +80 -0
  244. package/dist/trpc/index.js +205 -0
  245. package/dist/types-B8w5PFtS.d.ts +141 -0
  246. package/dist/types-B9dmiiab.d.ts +66 -0
  247. package/dist/types-BBK-exvJ.d.ts +177 -0
  248. package/dist/types-BvBk1wgn.d.ts +118 -0
  249. package/dist/types-CxquUByI.d.ts +9 -0
  250. package/dist/types-D6Z6-rKJ.d.ts +312 -0
  251. package/dist/types-DbWdEfcm.d.ts +87 -0
  252. package/dist/types-bva3i4Gf.d.ts +98 -0
  253. package/dist/types-i4BAOvdb.d.ts +97 -0
  254. package/dist/unplugin/index.d.ts +7 -0
  255. package/dist/unplugin/index.js +30 -0
  256. package/dist/usage-1ozMubLY.js +42 -0
  257. package/dist/usage-CUnK6Ou9.js +530 -0
  258. package/dist/usage-PyEor6GA.js +2 -0
  259. package/dist/validity-D0uRmJKJ.js +224 -0
  260. package/dist/verifier-B90agnhl.js +461 -0
  261. package/dist/version-CnSh33Fj.js +16 -0
  262. package/dist/vocabulary-Dk0fs-Jk.d.ts +56 -0
  263. package/dist/vue/index.d.ts +57 -0
  264. package/dist/vue/index.js +203 -0
  265. package/dist/webmcp/index.d.ts +75 -0
  266. package/dist/webmcp/index.js +313 -0
  267. package/package.json +423 -4
  268. package/rulesets/permdock.yaml +29 -0
  269. package/schemas/catalog-v1.json +507 -0
  270. package/schemas/openapi/oas-3.1.json +1298 -0
  271. package/schemas/openapi/oas-3.2.json +1516 -0
  272. package/schemas/openapi/overlay-1.1.json +79 -0
  273. package/schemas/supabase-claims-v1.json +139 -0
  274. package/schemas/supabase-manifest-v1.json +217 -0
  275. package/skills/permdock/SKILL.md +66 -0
  276. package/skills/permdock-agents/SKILL.md +77 -0
  277. package/skills/permdock-agents/references/runtimes.md +211 -0
  278. package/skills/permdock-approvals/SKILL.md +80 -0
  279. package/skills/permdock-approvals/references/stores-and-resume.md +83 -0
  280. package/skills/permdock-audit/SKILL.md +67 -0
  281. package/skills/permdock-credentials/SKILL.md +55 -0
  282. package/skills/permdock-credentials/references/tokens-keys-links.md +127 -0
  283. package/skills/permdock-data/SKILL.md +57 -0
  284. package/skills/permdock-data/references/queries-and-rls.md +54 -0
  285. package/skills/permdock-data/references/relationships.md +65 -0
  286. package/skills/permdock-tenancy/SKILL.md +77 -0
  287. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +83 -0
  288. package/skills/permdock-wire/SKILL.md +116 -0
  289. package/skills/permdock-wire/references/adapters.md +480 -0
  290. package/skills/permdock-wire/references/policy-options.md +43 -0
package/README.md CHANGED
@@ -1,3 +1,270 @@
1
1
  # permdock
2
2
 
3
- Placeholder release that reserves the package name. Install `permdock@latest` once 0.1.0 is out: <https://permdock.dev>.
3
+ **Typed permissions for TypeScript apps, APIs, databases and AI agents.**
4
+
5
+ [![npm](https://img.shields.io/npm/v/permdock?label=permdock)](https://www.npmjs.com/package/permdock)
6
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ScaleDockHQ/permdock/blob/main/LICENSE)
7
+ [![CI](https://img.shields.io/github/actions/workflow/status/ScaleDockHQ/permdock/ci.yml?label=CI)](https://github.com/ScaleDockHQ/permdock/actions)
8
+ ![Node.js 24+](https://img.shields.io/badge/Node.js-24%2B-5fa04e.svg)
9
+ ![TypeScript 7](https://img.shields.io/badge/TypeScript-7-3178c6.svg)
10
+
11
+ Define permissions once as typed references over the Zod, Valibot or ArkType schemas you already have. Grant them to roles with portable conditions. Check them in React, React Native, Next.js, Hono, tRPC and MCP servers. Compile the same conditions to SQL `where` clauses and Postgres Row Level Security policies. Drive tool approvals in the Vercel AI SDK, the Claude Agent SDK, Eve and the OpenAI Agents SDK from the same decision.
12
+
13
+ > **Pre-release.** The first published version is `0.1.0`. See the [roadmap](https://permdock.dev/docs/roadmap).
14
+
15
+ [Docs](https://permdock.dev/docs) · [Quick start](https://permdock.dev/docs/getting-started/quick-start) · [Adapters](https://permdock.dev/docs/adapters) · [For AI agents](https://permdock.dev/docs/for-ai-agents) · [Source](https://github.com/ScaleDockHQ/permdock)
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pnpm add permdock # core, every adapter as a subpath export, the permdock CLI and permdock/testing
21
+ ```
22
+
23
+ - One package. Core is `permdock`; every adapter is a subpath (`permdock/react`, `permdock/hono`, `permdock/next`, `permdock/ai-sdk`, …). The `permdock` binary (`collect`, `catalog`, `usage`, `openapi`, `rls`, `doctor`, `skills`) and the `permdock/testing` runners ship in the same package.
24
+ - ESM only. Node.js 24 or later. Written in and tested with TypeScript 7; the public types are also checked under TypeScript 5.9 and 6.
25
+ - Runtime entries depend on `@standard-schema/spec` only. The CLI's dependencies (`oxc-parser`, `citty`, `jiti`, `smol-toml`, `package-manager-detector`, `@clack/prompts`, `diff`) never reach them. Framework SDKs are optional peers, and structurally typed providers (`supabase`, `clerk`, `better-auth`, `convex`, `prisma`, `mcp`, `react-native`) declare no peer at all.
26
+
27
+ ## Why PermDock
28
+
29
+ Permission logic in a typical TypeScript app is spread across `if (user.role === 'admin')` checks in components, string keys like `'post:update'` in middleware, a hand-written client copy of the server rules, RLS policies nobody can diff against the app, and AI agents that call tools on a user's behalf with no way to say "ask first". PermDock replaces all of that with one definition and one decision object.
30
+
31
+ - **Reference-based.** `permissions.post.update` is a typed, frozen object carrying `key`, `scope`, schema and metadata. Go-to-definition works, renames are safe, and the runtime definition is the catalog.
32
+ - **Standard Schema native.** Resources are built from any [Standard Schema](https://standardschema.dev) validator; instance types are inferred; untrusted input is validated at trust boundaries only.
33
+ - **Policy as data.** Roles are arrays of `allow` / `deny` grants with a portable condition AST. One condition evaluates in the browser, filters arrays, compiles to Drizzle / Prisma / Kysely `where`, and generates Postgres RLS.
34
+ - **Multi-tenant roles.** A role is held globally, in a tenant, in a team or on one resource: `role('admin', grants, { on: 'tenant' })` replaces the `orgId` condition you used to repeat on every grant. Memberships come from your auth provider; PermDock stores nothing. Read [tenants, teams and scoped roles](https://permdock.dev/docs/concepts/tenancy).
35
+ - **Decisions, not booleans.** `decide()` returns `granted`, `denied` or `approval-required` with the matched grant, denial reasons and permitted alternatives. Adapters turn that into RFC 9457 Problem Details, model-readable MCP refusals and AI SDK approval states.
36
+ - **Snapshots that carry conditions.** The client answers ownership checks offline with no duplicated rules, and `<Protected>` never blocks a Next.js 16.3 instant navigation.
37
+ - **Agent-native.** A two-principal subject (principal, actor, delegation), adapters for MCP, the AI SDK, the Claude Agent SDK, Eve, the OpenAI Agents SDK, WebMCP and A2A, an AuthZEN 1.0 decision endpoint, and bundled agent skills.
38
+ - **Human approvals that resume safely.** `approval: 'human'` grants yield a third outcome with a replay-safe `token`. Pending approvals live in a pluggable `ApprovalStore`; approvers are authenticated and never the agent; plain HTTP resumes with a `PermDock-Approval` header.
39
+ - **Secure by default.** Fail-closed, deny overrides allow, an unknown reference is a type error, prototype-safe, no eval, `service_role` never emitted, model-supplied subjects never trusted, an agent with no delegation denied, no one approving their own request, never a default tenant, data validated against the resource schema unless the caller marks a row it loaded `trusted: true`.
40
+ - **Authentication stays upstream.** PermDock consumes verified material only: sessions, JWKS-verified JWTs (`permdock/jwt`, with `jose` as an optional peer), Supabase, Clerk and Better Auth claims, MCP `authInfo`. Token failures become RFC 6750 challenges, never thrown errors. Read [authentication](https://permdock.dev/docs/concepts/authentication).
41
+ - **The Cloud is optional.** Every decision runs in-process. PermDock Cloud adds a decision log, access reviews, an approval inbox, a hosted AuthZEN endpoint and a SCIM relay, all behind interfaces this package ships with in-process defaults. Read [PermDock Cloud](https://permdock.dev/docs/adapters/cloud).
42
+
43
+ ## Quick start
44
+
45
+ ### 1. Define permissions
46
+
47
+ Importable everywhere: server, client, React Native, MCP, tests.
48
+
49
+ ```ts
50
+ // src/permissions.ts
51
+ import { definePermissions, defineRoles, resource } from "permdock";
52
+ import { z } from "zod"; // or valibot / arktype / effect
53
+
54
+ const Post = z.object({
55
+ id: z.string(),
56
+ authorId: z.string(),
57
+ orgId: z.string(),
58
+ published: z.boolean(),
59
+ });
60
+
61
+ export const permissions = definePermissions({
62
+ post: resource(Post, {
63
+ id: "id", // identity field: cache keys, filter, RLS
64
+ actions: ["read", "update", "delete", "publish"], // take an instance
65
+ collection: ["create", "list"], // do not
66
+ }),
67
+ });
68
+
69
+ export const roles = defineRoles({ member: {}, admin: { on: "tenant" } });
70
+
71
+ permissions.post.update.key; // 'post.update'
72
+ ```
73
+
74
+ ### 2. Write the policy
75
+
76
+ Server-only. Roles are data; conditions are portable.
77
+
78
+ ```ts
79
+ // src/policy.ts
80
+ import { allow, definePolicy, principal, relation, role } from "permdock";
81
+ import { permissions, roles } from "./permissions";
82
+
83
+ const member = role(roles.member, [
84
+ allow(permissions.post.read),
85
+ allow(permissions.post.create),
86
+ allow(permissions.post.update, { to: relation(permissions.post, "author") }),
87
+ allow(permissions.post.delete, {
88
+ where: { authorId: principal.id },
89
+ approval: "human",
90
+ }),
91
+ ]);
92
+
93
+ const admin = role(
94
+ roles.admin,
95
+ [...member.grants, allow(permissions.post.delete)],
96
+ { on: "tenant" },
97
+ );
98
+
99
+ export const policy = definePolicy(
100
+ { permissions, roles },
101
+ {
102
+ roles: [member, admin],
103
+ scopes: { tenant: { key: "orgId" } },
104
+ principal: (user: User | null) =>
105
+ user && {
106
+ id: user.id,
107
+ roles: user.roles,
108
+ tenant: user.activeOrgId,
109
+ memberships: user.memberships,
110
+ },
111
+ validate: "boundary",
112
+ },
113
+ );
114
+ ```
115
+
116
+ `subjectFromClerk`, `subjectFromBetterAuth`, `subjectFromSupabase` and `subjectFromJwt` produce `memberships` from the provider you already use.
117
+
118
+ ### 3. Decide
119
+
120
+ ```ts
121
+ import { createPermDock } from "permdock";
122
+
123
+ const permdock = await createPermDock(policy, user); // frozen, request-scoped, never throws
124
+ permdock.can(permissions.post.update, post); // boolean
125
+ permdock.decide(permissions.post.delete, post); // { outcome: 'granted' | 'denied' | 'approval-required', ... }
126
+ permdock.filter(permissions.post.read, posts); // Post[]
127
+ permdock.where(permissions.post.read); // portable condition for Drizzle / Prisma / Kysely / SQL
128
+ permdock.snapshot({ include: [permissions.post] }); // JSON for the client
129
+ ```
130
+
131
+ ### React
132
+
133
+ ```tsx
134
+ import { PermDockProvider, Protected, usePermission } from "permdock/react";
135
+
136
+ <PermDockProvider snapshot={snapshot} endpoint="/api/permdock">
137
+ <Protected
138
+ permission={permissions.post.update}
139
+ data={post}
140
+ fallback={<Locked />}
141
+ >
142
+ <EditButton />
143
+ </Protected>
144
+ </PermDockProvider>;
145
+
146
+ const { allowed, status } = usePermission(permissions.post.update, post);
147
+ ```
148
+
149
+ The same hook names exist in React Native, Vue, Svelte and Solid. Read [building UI](https://permdock.dev/docs/concepts/ui).
150
+
151
+ ### Next.js 16.3
152
+
153
+ ```ts
154
+ // src/permdock/server.ts
155
+ import { createPermDock } from "permdock/next";
156
+
157
+ export const { getPermDock, requireAccess, permdockHandler } = createPermDock(
158
+ policy,
159
+ {
160
+ subject: async () => getUser(await cookies()),
161
+ },
162
+ );
163
+
164
+ // in a page or Server Action
165
+ await requireAccess({ permission: permissions.post.update, data: post }); // forbidden() / unauthorized() on a denial
166
+ ```
167
+
168
+ ### Hono
169
+
170
+ Express, Fastify, Elysia, Nest, Node, tRPC and oRPC have the same shape.
171
+
172
+ ```ts
173
+ import { createPermDock } from "permdock/hono";
174
+
175
+ export const { permdock, protect } = createPermDock(policy, {
176
+ subject: (c) => c.get("user"),
177
+ });
178
+ app.use(permdock());
179
+ app.delete(
180
+ "/posts/:id",
181
+ protect(permissions.post.delete, (c) => loadPost(c.req.param("id"))),
182
+ handler,
183
+ );
184
+ // deny → 403 application/problem+json with permission, denials and alternatives
185
+ ```
186
+
187
+ ### MCP
188
+
189
+ ```ts
190
+ import { createPermDock } from "permdock/mcp";
191
+
192
+ const { protectServer } = createPermDock(policy, {
193
+ subject: (authInfo) => userFrom(authInfo),
194
+ });
195
+ protectServer(server).registerTool(
196
+ "delete_post",
197
+ {
198
+ permission: permissions.post.delete,
199
+ inputSchema,
200
+ data: (args) => loadPost(args.id),
201
+ },
202
+ handler,
203
+ );
204
+ // tools filtered per caller, args validated, refusals carry reasons and alternatives
205
+ ```
206
+
207
+ ### AI SDK
208
+
209
+ ```ts
210
+ import { createPermDock } from "permdock/ai-sdk";
211
+
212
+ const { toolApproval } = createPermDock(policy, {
213
+ subject: ({ runtimeContext }) => runtimeContext.user,
214
+ actor: ({ runtimeContext }) => ({
215
+ id: runtimeContext.agentId,
216
+ kind: "ai-sdk",
217
+ }),
218
+ tools: {
219
+ delete_post: {
220
+ permission: permissions.post.delete,
221
+ data: (args) => loadPost(args.id),
222
+ },
223
+ },
224
+ });
225
+ generateText({ model, tools, toolApproval }); // granted → approved, denied → denied, approval-required → user-approval
226
+ ```
227
+
228
+ ### RLS
229
+
230
+ ```bash
231
+ permdock rls generate --target drizzle --dialect supabase # roles × grants → policies
232
+ permdock rls verify --db $DATABASE_URL # can() vs database parity
233
+ ```
234
+
235
+ ## Works with
236
+
237
+ Any Standard Schema validator: Zod, Valibot, ArkType, Effect Schema. One import path per target:
238
+
239
+ | Group | Entries |
240
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
241
+ | UI | `permdock/react` · `permdock/react-native` · `permdock/vue` · `permdock/svelte` · `permdock/solid` |
242
+ | Full-stack | `permdock/next` |
243
+ | HTTP | `permdock/server` · `permdock/hono` · `permdock/express` · `permdock/fastify` · `permdock/elysia` · `permdock/nest` · `permdock/node` |
244
+ | Terminal | `permdock/terminal` for your own CLI (not the `permdock` binary) |
245
+ | RPC | `permdock/trpc` · `permdock/orpc` |
246
+ | Agents | `permdock/mcp` · `permdock/ai-sdk` · `permdock/claude-agent` · `permdock/eve` · `permdock/openai` · `permdock/webmcp` · `permdock/a2a` |
247
+ | Decision plane | `permdock/authzen` · `permdock/approvals` · `permdock/cloud` · `permdock/scim` · `permdock/ssf` · `permdock/openapi` · `permdock/otel` · `permdock/pdp` |
248
+ | Data | `permdock/drizzle` · `permdock/prisma` · `permdock/kysely` · `permdock rls` |
249
+ | Auth and providers | `permdock/jwt` · `permdock/supabase` · `permdock/supabase/middleware` · `permdock/better-auth` · `permdock/clerk` · `permdock/convex` |
250
+ | Build | `permdock/next/plugin` · `permdock/unplugin` |
251
+ | Testing | `permdock/testing` |
252
+
253
+ Nuxt, Astro, React Router, TanStack Start and Effect use these entries plus `permdock/unplugin`. The full matrix with example apps and related standards is on the [adapters page](https://permdock.dev/docs/adapters).
254
+
255
+ ## Compared with
256
+
257
+ Other TypeScript permission libraries (CASL, permix, Kilpi, `@zap-studio/permit`) return booleans from string keys and stop at the server or the UI. Hosted PDPs (Cerbos, Permit.io, OpenFGA, SpiceDB) put a network call on every check. PermDock is an embedded, typed library with one decision object across UI, API, SQL, RLS and agent approvals. Read the [comparison](https://permdock.dev/docs/comparison).
258
+
259
+ ## For AI agents
260
+
261
+ ```bash
262
+ npx skills add ScaleDockHQ/PermDock # the permdock, permdock-wire, permdock-audit and topic skills
263
+ permdock skills # the same skills, offline, from node_modules/permdock/skills
264
+ ```
265
+
266
+ Claude Code users can add the plugin marketplace instead: `/plugin marketplace add ScaleDockHQ/permdock`. Every docs page is served as Markdown, plus `llms.txt` and `llms-full.txt`. Read [for AI agents](https://permdock.dev/docs/for-ai-agents).
267
+
268
+ ## License
269
+
270
+ [MIT](https://github.com/ScaleDockHQ/permdock/blob/main/LICENSE) © 2026 ScaleDockHQ. Report vulnerabilities privately through [GitHub security advisories](https://github.com/ScaleDockHQ/permdock/security/advisories/new).
@@ -0,0 +1,178 @@
1
+ import { $ as DecisionSink, C as Policy, at as LimitStore, ct as MembershipSource, ft as RelationSource, mr as Principal, or as AuthorizationDetail, pt as RoleSource, sn as PolicySource, tt as EntitlementSource, xt as SnapshotSource } from "../policy-CInmNGkM.js";
2
+ import { d as Permission } from "../permissions-B4apnahQ.js";
3
+ import { f as ApprovalStore } from "../types-B8w5PFtS.js";
4
+ import { o as ProblemDetails } from "../errors-DbZ1YOnb.js";
5
+ //#region src/a2a/types.d.ts
6
+ type A2aAuth = {
7
+ readonly clientId?: string;
8
+ readonly scopes?: readonly string[];
9
+ readonly extra?: {
10
+ readonly authorizationDetails?: readonly AuthorizationDetail[];
11
+ readonly approval?: string;
12
+ };
13
+ };
14
+ /** OpenAPI-style input; the card carries the A2A 1.0 union form. */
15
+ type A2aSecurityScheme = {
16
+ readonly type: "oauth2";
17
+ readonly oauth2MetadataUrl: string;
18
+ readonly description?: string;
19
+ } | {
20
+ readonly type: "http";
21
+ readonly scheme: string;
22
+ readonly bearerFormat?: string;
23
+ readonly description?: string;
24
+ } | {
25
+ readonly type: "openIdConnect";
26
+ readonly openIdConnectUrl: string;
27
+ readonly description?: string;
28
+ } | {
29
+ readonly type: "mutualTLS";
30
+ readonly description?: string;
31
+ } | {
32
+ readonly type: "apiKey";
33
+ readonly in: "query" | "header" | "cookie";
34
+ readonly name: string;
35
+ readonly description?: string;
36
+ };
37
+ /** A2A 1.0 `SecurityScheme`: exactly one member set. */
38
+ type A2aWireSecurityScheme = {
39
+ readonly oauth2SecurityScheme: {
40
+ readonly oauth2MetadataUrl: string;
41
+ readonly description?: string;
42
+ };
43
+ } | {
44
+ readonly httpAuthSecurityScheme: {
45
+ readonly scheme: string;
46
+ readonly bearerFormat?: string;
47
+ readonly description?: string;
48
+ };
49
+ } | {
50
+ readonly openIdConnectSecurityScheme: {
51
+ readonly openIdConnectUrl: string;
52
+ readonly description?: string;
53
+ };
54
+ } | {
55
+ readonly mtlsSecurityScheme: {
56
+ readonly description?: string;
57
+ };
58
+ } | {
59
+ readonly apiKeySecurityScheme: {
60
+ readonly location: "query" | "header" | "cookie";
61
+ readonly name: string;
62
+ readonly description?: string;
63
+ };
64
+ };
65
+ type A2aCardInfo = {
66
+ readonly name: string;
67
+ /** Required by A2A 1.0; defaults to `name`. */
68
+ readonly description?: string;
69
+ /** The preferred interface URL, the first `supportedInterfaces` entry. */
70
+ readonly url: string;
71
+ readonly version: string;
72
+ /** Defaults to `JSONRPC`. */
73
+ readonly protocolBinding?: "JSONRPC" | "GRPC" | "HTTP+JSON";
74
+ readonly provider?: {
75
+ readonly organization: string;
76
+ readonly url: string;
77
+ };
78
+ readonly documentationUrl?: string;
79
+ readonly iconUrl?: string;
80
+ /** Media types; default `['text/plain']`. */
81
+ readonly defaultInputModes?: readonly string[];
82
+ readonly defaultOutputModes?: readonly string[];
83
+ readonly streaming?: boolean;
84
+ readonly pushNotifications?: boolean;
85
+ };
86
+ type A2aSkillConfig = {
87
+ readonly permission: Permission;
88
+ readonly description?: string;
89
+ /** Required by A2A 1.0; defaults to the permission's resource. */
90
+ readonly tags?: readonly string[];
91
+ readonly data?: (task: unknown) => Promise<unknown>;
92
+ };
93
+ /** A2A 1.0 `SecurityRequirement`: scheme name to required scopes. */
94
+ type A2aSecurityRequirement = {
95
+ readonly schemes: Readonly<Record<string, {
96
+ readonly list: readonly string[];
97
+ }>>;
98
+ };
99
+ type A2aSkill = {
100
+ readonly id: string;
101
+ readonly name: string;
102
+ readonly description: string;
103
+ readonly tags: readonly string[];
104
+ readonly securityRequirements: readonly A2aSecurityRequirement[];
105
+ };
106
+ /** A2A 1.0 `AgentCardSignature`: a JWS over the card without `signatures`. */
107
+ type A2aAgentCardSignature = {
108
+ readonly protected: string;
109
+ readonly signature: string;
110
+ };
111
+ type A2aAgentCard = {
112
+ readonly name: string;
113
+ readonly description: string;
114
+ readonly version: string;
115
+ readonly supportedInterfaces: readonly {
116
+ readonly url: string;
117
+ readonly protocolBinding: string;
118
+ readonly protocolVersion: "1.0";
119
+ }[];
120
+ readonly provider?: {
121
+ readonly organization: string;
122
+ readonly url: string;
123
+ };
124
+ readonly documentationUrl?: string;
125
+ readonly iconUrl?: string;
126
+ readonly capabilities: {
127
+ readonly extendedAgentCard: true;
128
+ readonly streaming?: boolean;
129
+ readonly pushNotifications?: boolean;
130
+ };
131
+ readonly defaultInputModes: readonly string[];
132
+ readonly defaultOutputModes: readonly string[];
133
+ readonly securitySchemes: Readonly<Record<string, A2aWireSecurityScheme>>;
134
+ readonly skills: readonly A2aSkill[];
135
+ readonly signatures?: readonly A2aAgentCardSignature[];
136
+ };
137
+ type A2aTaskOutcome = {
138
+ readonly ok: true;
139
+ } | {
140
+ readonly ok: false;
141
+ readonly status: 401 | 403;
142
+ readonly state: "failed" | "input-required";
143
+ readonly problem: ProblemDetails;
144
+ readonly wwwAuthenticate?: string;
145
+ };
146
+ type A2aPermDockOptions<TUser = unknown> = {
147
+ readonly subject: (auth: A2aAuth) => TUser | Promise<TUser>;
148
+ readonly card: A2aCardInfo;
149
+ readonly securitySchemes: Readonly<Record<string, A2aSecurityScheme>>;
150
+ readonly skills: Readonly<Record<string, A2aSkillConfig>>;
151
+ readonly tenant?: string | ((auth: A2aAuth) => string | undefined | Promise<string | undefined>);
152
+ readonly memberships?: MembershipSource | readonly MembershipSource[];
153
+ /** The object graph for relation grants that walk a parent chain; without it they deny. */
154
+ readonly relations?: RelationSource;
155
+ readonly entitlements?: EntitlementSource;
156
+ readonly customRoles?: RoleSource;
157
+ /** Hosted grants, read once per instance; see `PolicySource`. */
158
+ readonly policies?: PolicySource;
159
+ readonly store?: ApprovalStore;
160
+ readonly sink?: DecisionSink;
161
+ readonly limits?: LimitStore;
162
+ readonly snapshots?: SnapshotSource;
163
+ };
164
+ type A2aPermDock = {
165
+ readonly agentCard: () => A2aAgentCard;
166
+ readonly extendedAgentCard: (auth: A2aAuth) => Promise<A2aAgentCard>;
167
+ readonly protectSkill: (selector: (task: unknown) => string) => (task: unknown, auth: A2aAuth) => Promise<A2aTaskOutcome>;
168
+ /**
169
+ * Appends an A2A 1.0 signature. `sign` returns a compact JWS over the
170
+ * RFC 8785 canonical card it is given; the payload is detached.
171
+ */
172
+ readonly sign: (card: A2aAgentCard, sign: (payload: string) => Promise<string>) => Promise<A2aAgentCard>;
173
+ };
174
+ //#endregion
175
+ //#region src/a2a/create.d.ts
176
+ export declare function createPermDock<TUser, TPrincipal extends Principal = Principal>(policy: Policy<TUser, TPrincipal>, options: A2aPermDockOptions<TUser>): A2aPermDock;
177
+ //#endregion
178
+ export type { A2aAgentCard, A2aAgentCardSignature, A2aAuth, A2aCardInfo, A2aPermDock, A2aPermDockOptions, A2aSecurityRequirement, A2aSecurityScheme, A2aSkill, A2aSkillConfig, A2aTaskOutcome, A2aWireSecurityScheme };