permdock 0.1.0 → 0.2.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 (349) hide show
  1. package/README.md +106 -47
  2. package/dist/a2a/index.d.ts +7 -16
  3. package/dist/a2a/index.js +59 -98
  4. package/dist/adapter-context-mlWsVGGg.js +23 -0
  5. package/dist/ai-sdk/index.d.ts +37 -16
  6. package/dist/ai-sdk/index.js +30 -13
  7. package/dist/approvals/index.d.ts +3 -3
  8. package/dist/approvals/index.js +5 -4
  9. package/dist/{approvals-DaxY-Bdg.js → approvals-DbYAuNkG.js} +17 -11
  10. package/dist/approvers-DT4AVyIg.js +52 -0
  11. package/dist/{arazzo-CTeVuXr5.js → arazzo-BAgw9ap6.js} +2 -2
  12. package/dist/{arazzo-aoTkqYsJ.js → arazzo-cmvX2jDe.js} +2 -2
  13. package/dist/authzen/index.d.ts +4 -13
  14. package/dist/authzen/index.js +16 -50
  15. package/dist/better-auth/index.d.ts +20 -3
  16. package/dist/better-auth/index.js +27 -7
  17. package/dist/better-supabase/index.d.ts +206 -0
  18. package/dist/better-supabase/index.js +620 -0
  19. package/dist/bind-CVy3Espv.d.ts +25 -0
  20. package/dist/bind-VnYn2HKq.js +97 -0
  21. package/dist/boundary-BM8a_P6E.js +13 -0
  22. package/dist/boundary-BmHxVH1J.d.ts +15 -0
  23. package/dist/canonical-json-DemiK4Vp.js +26 -0
  24. package/dist/{capability-B68OFnZx.js → capability-4qPdO9gk.js} +7 -5
  25. package/dist/{capability-BDG_nkxt.d.ts → capability-Dq43tT1u.d.ts} +2 -2
  26. package/dist/catalog/index.d.ts +1 -1
  27. package/dist/catalog/index.js +1 -1
  28. package/dist/catalog-BjZSovXQ.js +2 -0
  29. package/dist/{catalog-doc-BSo_Q_-6.js → catalog-doc-Dsc9y7sd.js} +23 -12
  30. package/dist/{catalog-B0E6bggc.js → catalog-h2tlKFkq.js} +2 -2
  31. package/dist/{catalog-H-vFGwWK.js → catalog-z8q6bi_r.js} +4 -4
  32. package/dist/claude-agent/index.d.ts +5 -14
  33. package/dist/claude-agent/index.js +4 -10
  34. package/dist/clerk/index.d.ts +12 -3
  35. package/dist/clerk/index.js +26 -5
  36. package/dist/cli/bin.js +1 -1
  37. package/dist/cli/index.d.ts +3 -3
  38. package/dist/cli/index.js +2 -2
  39. package/dist/clients-C7zLFuWT.d.ts +12 -0
  40. package/dist/clients-DjU5ABMy.js +23 -0
  41. package/dist/cloud/index.d.ts +4 -5
  42. package/dist/cloud/index.js +20 -6
  43. package/dist/{cloud-BNQTrmrr.js → cloud-BGhHS-lY.js} +2 -2
  44. package/dist/{cloud-Cuxr6Czw.js → cloud-Bo3e9Ak3.js} +7 -6
  45. package/dist/{collect-O-tOtbnk.js → collect-DDDv_ESs.js} +194 -42
  46. package/dist/collect-DLlujdHC.js +83 -0
  47. package/dist/collect-rG2IQ3t0.js +2 -0
  48. package/dist/{commands-BMh_Etm2.js → commands-DWOrSQic.js} +16 -12
  49. package/dist/compile/index.d.ts +3 -0
  50. package/dist/compile/index.js +2 -0
  51. package/dist/{compile-D22iwvuV.js → compile-Ba4blROR.js} +85 -30
  52. package/dist/compile-CNnl6uIt.d.ts +94 -0
  53. package/dist/config-BJiM-xAm.js +157 -0
  54. package/dist/config-Bn00Z3ks.js +36 -0
  55. package/dist/config-report-Dw_JcUqT.js +44 -0
  56. package/dist/{connection-JvqwHODC.js → connection-CU8MQxRi.js} +1 -1
  57. package/dist/{context-CKEAabd7.js → context-Ttp0ekMT.js} +36 -27
  58. package/dist/convex/index.d.ts +9 -4
  59. package/dist/convex/index.js +14 -4
  60. package/dist/create-BWyx3jua.d.ts +245 -0
  61. package/dist/create-CPhDL6qx.js +253 -0
  62. package/dist/{credential-B_rkUNlY.js → credential-8P81ff4u.js} +26 -46
  63. package/dist/delegation-D8pUEuce.js +103 -0
  64. package/dist/{describe-Bt1YD5uS.js → describe-B_gVZEVi.js} +10 -15
  65. package/dist/{describe-DernyItf.d.ts → describe-PdoqESvg.d.ts} +9 -10
  66. package/dist/{diff-x5Il8LVa.js → diff-B8Tunc3o.js} +44 -11
  67. package/dist/{diff-BUzf5Poi.js → diff-CzqLxZ77.js} +2 -2
  68. package/dist/doctor-WpvG6p4k.js +1194 -0
  69. package/dist/doctor-collect-ByfYlNv1.js +664 -0
  70. package/dist/{doctor-Bqo6FwUa.js → doctor-rOr-4ZfS.js} +2 -2
  71. package/dist/drizzle/index.d.ts +4 -3
  72. package/dist/drizzle/index.js +3 -3
  73. package/dist/elysia/index.d.ts +6 -28
  74. package/dist/elysia/index.js +16 -60
  75. package/dist/{errors-DSMnAVNa.js → errors-CWfoNg9N.js} +8 -4
  76. package/dist/{errors-Iy71s7Oj.js → errors-Cz5zn0mW.js} +17 -71
  77. package/dist/{errors-DbZ1YOnb.d.ts → errors-DAqevpNk.d.ts} +8 -21
  78. package/dist/{errors-m3u9TmDu.js → errors-DRnGZHzF.js} +4 -1
  79. package/dist/evaluation-items-CfCCejQd.js +40 -0
  80. package/dist/{evaluations-DsAU9ppl.js → evaluations-tz6D9A2G.js} +28 -46
  81. package/dist/eve/index.d.ts +6 -15
  82. package/dist/eve/index.js +7 -12
  83. package/dist/expiry-BoBJ8Tvc.js +7 -0
  84. package/dist/express/index.d.ts +6 -29
  85. package/dist/express/index.js +28 -58
  86. package/dist/fastify/index.d.ts +6 -29
  87. package/dist/fastify/index.js +16 -65
  88. package/dist/fields-BMl1RxoX.js +26 -0
  89. package/dist/{files-B_wAGYmt.js → files-DWUN9PzI.js} +5 -1
  90. package/dist/{fixtures-Cvaw0gDG.js → fixtures-ht28Cplr.js} +5 -2
  91. package/dist/{freeze-y1_jQL4v.js → freeze-CrU8nQeX.js} +31 -2
  92. package/dist/{from-snapshot-BMGnhmgv.js → from-snapshot-C3sHpZNS.js} +65 -48
  93. package/dist/{grantee-Bv04_Vzf.js → grantee-Cv5Sogfv.js} +88 -7
  94. package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
  95. package/dist/{headers-B5RRv3Xm.js → headers-BZSDieNT.js} +1 -1
  96. package/dist/{headers-C8SHQccD.d.ts → headers-Cf-zWvsO.d.ts} +1 -1
  97. package/dist/helpers-H_KARDVC.js +421 -0
  98. package/dist/hono/index.d.ts +6 -28
  99. package/dist/hono/index.js +11 -43
  100. package/dist/{hosted-BwKQ1BTA.js → hosted-DJQw46hn.js} +6 -5
  101. package/dist/{http-GgVApX1k.js → http-BIhmLfCc.js} +4 -20
  102. package/dist/http-SO7qGttf.js +44 -0
  103. package/dist/ids-DC4V4CFu.js +18 -0
  104. package/dist/{index-LF_hS-yn.d.ts → index-A0YNL8jZ.d.ts} +1 -1
  105. package/dist/index-CtE07CBF.d.ts +6 -0
  106. package/dist/{index-xIxJLwOQ.d.ts → index-D3vbkoSI.d.ts} +75 -7
  107. package/dist/{index-CltcQ4Bf.d.ts → index-D6_cSa1z.d.ts} +68 -5
  108. package/dist/index.d.ts +14 -9
  109. package/dist/index.js +22 -17
  110. package/dist/instance-options-BK_rNOSC.d.ts +11 -0
  111. package/dist/instance-options-Dhhcnm3y.js +22 -0
  112. package/dist/{parse-DPfIvFMU.js → json-schema-BsAflUGW.js} +28 -57
  113. package/dist/jwt/index.d.ts +10 -6
  114. package/dist/jwt/index.js +32 -13
  115. package/dist/kernel-GSQnMz3O.js +208 -0
  116. package/dist/kysely/index.d.ts +4 -3
  117. package/dist/kysely/index.js +3 -3
  118. package/dist/live-options-H2eG8dfJ.js +60 -0
  119. package/dist/{load-BZ24CpZP.js → load-DhWEB9P1.js} +16 -10
  120. package/dist/load-DwJUafYN.js +2 -0
  121. package/dist/manifest-iaoBXHKc.js +783 -0
  122. package/dist/manifest-uDS9y5de.d.ts +206 -0
  123. package/dist/{map-DowSO96j.js → map-AcxK9o_D.js} +4 -15
  124. package/dist/{map-claims-B_6I1Rn-.js → map-claims-Z4QZOiFF.js} +13 -4
  125. package/dist/map-error-pgUWNNtG.js +23 -0
  126. package/dist/may-use-DndQ5tQ-.js +77 -0
  127. package/dist/mcp/index.d.ts +54 -22
  128. package/dist/mcp/index.js +218 -178
  129. package/dist/nest/index.d.ts +26 -31
  130. package/dist/nest/index.js +75 -84
  131. package/dist/next/client.d.ts +7 -8
  132. package/dist/next/client.js +11 -9
  133. package/dist/next/index.d.ts +30 -47
  134. package/dist/next/index.js +45 -60
  135. package/dist/next/plugin.d.ts +1 -1
  136. package/dist/next/plugin.js +32 -1
  137. package/dist/node/index.d.ts +9 -28
  138. package/dist/node/index.js +11 -43
  139. package/dist/openai/index.d.ts +6 -15
  140. package/dist/openai/index.js +7 -20
  141. package/dist/openapi/index.d.ts +87 -4
  142. package/dist/openapi/index.js +3 -3
  143. package/dist/{openapi-CwePaF7C.js → openapi-Bbg4wGVL.js} +3 -3
  144. package/dist/{openapi-DcqM8nU7.js → openapi-BqRBvAng.js} +237 -5
  145. package/dist/{openapi-DWD0Uc_4.js → openapi-CqqEbHsL.js} +5 -5
  146. package/dist/{openapi-import-BWRUNNeW.js → openapi-import-cmwetbzw.js} +1 -1
  147. package/dist/{openapi-schema-D8j_T9tO.js → openapi-schema--ARjyfQr.js} +2 -2
  148. package/dist/orpc/index.d.ts +15 -28
  149. package/dist/orpc/index.js +74 -117
  150. package/dist/otel/index.d.ts +2 -2
  151. package/dist/parse-BuyjxhZV.js +53 -0
  152. package/dist/parse-local-manifest-BkGQNzAh.d.ts +10 -0
  153. package/dist/parse-local-manifest-BrMozJCo.js +36 -0
  154. package/dist/pdp/index.d.ts +2 -2
  155. package/dist/pdp/index.js +14 -127
  156. package/dist/{permdock-yoZ7EjxX.js → permdock-CzqXjCpU.js} +641 -126
  157. package/dist/{permissions-B8vCg_bI.d.ts → permissions-CDgvKG5L.d.ts} +2 -2
  158. package/dist/{permissions-CofRqesP.js → permissions-CpZrivYv.js} +3 -3
  159. package/dist/{permissions-DC7GROPA.js → permissions-DVoF6dMt.js} +77 -15
  160. package/dist/{permissions-B4apnahQ.d.ts → permissions-DttnqqxC.d.ts} +34 -5
  161. package/dist/{pins-CqE1jZuF.js → pins-8ILTftC9.js} +2 -2
  162. package/dist/{policy-CInmNGkM.d.ts → policy-CFZAr_Al.d.ts} +330 -37
  163. package/dist/{policy-Cq2fB8Q5.d.ts → policy-D8UFyERw.d.ts} +2 -2
  164. package/dist/{policy-ANp36PnI.js → policy-xyWg7QdR.js} +173 -22
  165. package/dist/powersync-A8x_Yyvh.js +2 -0
  166. package/dist/powersync-C7kLglqX.js +540 -0
  167. package/dist/powersync-yW1UUFzp.js +62 -0
  168. package/dist/prisma/index.d.ts +3 -2
  169. package/dist/prisma/index.js +45 -20
  170. package/dist/{problem-Cgp9-KZA.js → problem-B43ztKIm.js} +74 -109
  171. package/dist/problem-details-CkL50EEf.d.ts +7 -0
  172. package/dist/problem-details-_AMOYz-w.js +144 -0
  173. package/dist/{protected-BuPAycJT.d.ts → protected-CNsMzrVd.d.ts} +5 -4
  174. package/dist/protected-Cs6kTaHo.js +100 -0
  175. package/dist/protected-bZs6rbT1.d.ts +40 -0
  176. package/dist/{provider-wTAUda2v.d.ts → provider-Cjr62YMV.d.ts} +1 -1
  177. package/dist/provider-DLzpb2Xz.js +52 -0
  178. package/dist/provider-store-DNyC1y48.js +43 -0
  179. package/dist/react/index.d.ts +7 -5
  180. package/dist/react/index.js +5 -4
  181. package/dist/react/provider-client.d.ts +1 -1
  182. package/dist/react/provider-client.js +1 -1
  183. package/dist/react-native/index.d.ts +166 -10
  184. package/dist/react-native/index.js +607 -85
  185. package/dist/{refs-ChLSxbST.js → refs-KYb4ntaz.js} +4 -3
  186. package/dist/{relations-r4soIFZB.js → relations-cjOL01hZ.js} +110 -31
  187. package/dist/replay-BsOyTrdV.js +28 -0
  188. package/dist/replay-sqBGMnNs.d.ts +5 -0
  189. package/dist/resource-ref-CaS9yVPi.js +20 -0
  190. package/dist/revocations-Bhr0aMIC.js +27 -0
  191. package/dist/rls-BMNydpHk.js +2521 -0
  192. package/dist/{rls-BOFU3chG.js → rls-CEvs64Kj.js} +8 -3
  193. package/dist/rls-fields-BMasREhR.js +3502 -0
  194. package/dist/{rls-graph-DxQ39PJj.js → rls-graph-pc9fuXYm.js} +100 -36
  195. package/dist/{rls-import-CXV6LBlS.js → rls-import-D8F7j35Q.js} +7 -6
  196. package/dist/{rls-migrate-DrFPbf8p.js → rls-migrate-7wikfrVI.js} +6 -5
  197. package/dist/rls-ownership-B5Lkq62W.js +843 -0
  198. package/dist/rls-shared-aOQ4hGTO.js +493 -0
  199. package/dist/rls-verify-D8B7dOTh.js +745 -0
  200. package/dist/{row-check-BajTgQZ-.d.ts → row-check-Dt35czLy.d.ts} +12 -15
  201. package/dist/rpc-DOK54_CS.js +89 -0
  202. package/dist/{run-CJ6UvS3a.js → run-YXCJDNYk.js} +31 -12
  203. package/dist/runtime-CB8gQFvS.js +11 -0
  204. package/dist/{saas-BRrZzJkM.js → saas-Bj_FFkjN.js} +17 -7
  205. package/dist/{schema-P8yoma__.js → schema-D3MnDMxa.js} +8 -4
  206. package/dist/scim/index.d.ts +1 -1
  207. package/dist/scim/index.js +1 -1
  208. package/dist/{scim-9NFa0XVZ.js → scim-BFGBBAqR.js} +1 -1
  209. package/dist/{scopes-cKVp_WTw.js → scopes-CVdPrWN-.js} +35 -8
  210. package/dist/server/index.d.ts +22 -11
  211. package/dist/server/index.js +11 -8
  212. package/dist/{credentials-BgRX3WEg.js → server-DlZ28Oz5.js} +1 -1
  213. package/dist/shared-DRu8VFVM.js +123 -0
  214. package/dist/{sink-Cfr9-7YC.d.ts → sink-Gs6TTVa-.d.ts} +1 -1
  215. package/dist/skills-Biq5uup3.js +192 -0
  216. package/dist/{skills-C_lpV4Jx.js → skills-JaymNCdK.js} +10 -4
  217. package/dist/{snapshot-DE8dE_hz.js → snapshot-Enxd0n-s.js} +138 -214
  218. package/dist/snapshot-cache-D6jLelln.js +44 -0
  219. package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
  220. package/dist/solid/index.d.ts +39 -9
  221. package/dist/solid/index.js +76 -85
  222. package/dist/sources-B0UvrJ21.js +534 -0
  223. package/dist/sources-BcJgw0lt.d.ts +192 -0
  224. package/dist/{sql-Bll1d7y0.js → sql-xdg5f4Fi.js} +6 -1
  225. package/dist/{src-CTNT-PBW.js → src-CSbUiozF.js} +149 -11
  226. package/dist/ssf/index.d.ts +3 -2
  227. package/dist/ssf/index.js +3 -29
  228. package/dist/store-DMAWwAJV.js +371 -0
  229. package/dist/{store-Bq90395i.d.ts → store-D_pjn91-.d.ts} +13 -4
  230. package/dist/store-options-yO0V6gRn.js +716 -0
  231. package/dist/{stores-CkG2HrSg.js → stores-4_sqiOA1.js} +10 -63
  232. package/dist/{stores-CvOnu_2T.d.ts → stores-DVR5NHLE.d.ts} +20 -9
  233. package/dist/{stream-Q_xlB6Ko.js → stream-DDpvynSB.js} +16 -2
  234. package/dist/{stream-BhMfZOwr.d.ts → stream-DlvG2hs-.d.ts} +2 -2
  235. package/dist/subject-settings-BwBmCdTR.js +128 -0
  236. package/dist/supabase/index.d.ts +122 -6
  237. package/dist/supabase/index.js +4 -3
  238. package/dist/supabase/middleware.d.ts +32 -27
  239. package/dist/supabase/middleware.js +56 -22
  240. package/dist/{supabase-D8UlBA7Z.js → supabase-CwafwxxF.js} +3 -3
  241. package/dist/{supabase-DTxGtYdi.js → supabase-DTBaC20O.js} +345 -367
  242. package/dist/supabase-config-Bs44dare.js +472 -0
  243. package/dist/{supabase-hook-D_OqGb_V.js → supabase-hook-BuxLQLpU.js} +994 -708
  244. package/dist/supabase-hook-D5qVd_D8.js +2 -0
  245. package/dist/supautils-DYZnzRWV.js +91 -0
  246. package/dist/svelte/PermissionBoundary.svelte +37 -0
  247. package/dist/svelte/Protected.svelte +8 -2
  248. package/dist/svelte/index.d.ts +9 -6
  249. package/dist/svelte/index.js +61 -7
  250. package/dist/svelte/runtime.d.ts +4 -3
  251. package/dist/svelte/runtime.js +4 -3
  252. package/dist/svelte/source.d.ts +9 -6
  253. package/dist/svelte/source.js +7 -4
  254. package/dist/terminal/index.d.ts +6 -14
  255. package/dist/terminal/index.js +44 -32
  256. package/dist/testing/index.d.ts +105 -16
  257. package/dist/testing/index.js +504 -40
  258. package/dist/testing/saas/index.d.ts +4 -4
  259. package/dist/testing/saas/index.js +2 -2
  260. package/dist/testing/saas/permissions.d.ts +1 -1
  261. package/dist/testing/saas/permissions.js +1 -1
  262. package/dist/token-CIWxJOCh.js +50 -0
  263. package/dist/trpc/index.d.ts +7 -26
  264. package/dist/trpc/index.js +17 -100
  265. package/dist/types-9AWO9EGt.d.ts +197 -0
  266. package/dist/{types-D6Z6-rKJ.d.ts → types-BPxgszlT.d.ts} +260 -22
  267. package/dist/{types-BvBk1wgn.d.ts → types-BVyImy5I.d.ts} +5 -3
  268. package/dist/{types-CxquUByI.d.ts → types-Bvc4oWT6.d.ts} +1 -1
  269. package/dist/types-C3s9xVJG.d.ts +48 -0
  270. package/dist/{types-BBK-exvJ.d.ts → types-Dnemwd77.d.ts} +7 -1
  271. package/dist/types-kxznc7cn.d.ts +52 -0
  272. package/dist/{types-B8w5PFtS.d.ts → types-vKyAMtcX.d.ts} +17 -1
  273. package/dist/{types-B9dmiiab.d.ts → types-vNSDF7Dq.d.ts} +1 -1
  274. package/dist/{sources-DOpW5Ila.d.ts → types-yF5LmQVD.d.ts} +86 -127
  275. package/dist/unplugin/index.d.ts +1 -1
  276. package/dist/unplugin/index.js +10 -9
  277. package/dist/{usage-1ozMubLY.js → usage-D07N9QJ3.js} +2 -2
  278. package/dist/usage-D82l1CwK.js +2 -0
  279. package/dist/{usage-CUnK6Ou9.js → usage-DG1oeCca.js} +225 -62
  280. package/dist/validation-error-CnjZ4t92.js +33 -0
  281. package/dist/validation-error-CtF23SrC.d.ts +26 -0
  282. package/dist/{validity-D0uRmJKJ.js → validity-uOp8UpYn.js} +57 -36
  283. package/dist/{verifier-B90agnhl.js → verifier-BxBo6I44.js} +10 -5
  284. package/dist/version-BvacVTZR.js +17 -0
  285. package/dist/views-Soe7bGSC.js +95 -0
  286. package/dist/{vocabulary-Dk0fs-Jk.d.ts → vocabulary-DA8a8zif.d.ts} +1 -1
  287. package/dist/vue/index.d.ts +35 -13
  288. package/dist/vue/index.js +86 -93
  289. package/dist/watch-Etoa_Mvr.js +2 -0
  290. package/dist/watch-UihESpsJ.js +128 -0
  291. package/dist/webmcp/index.d.ts +2 -2
  292. package/dist/webmcp/index.js +7 -13
  293. package/package.json +62 -36
  294. package/schemas/approval-request-v1.json +175 -0
  295. package/schemas/catalog-v1.json +29 -1
  296. package/schemas/supabase-claims-v1.json +6 -1
  297. package/schemas/supabase-manifest-v1.json +150 -6
  298. package/skills/permdock/SKILL.md +7 -7
  299. package/skills/permdock-agents/SKILL.md +5 -5
  300. package/skills/permdock-agents/references/runtimes.md +12 -10
  301. package/skills/permdock-approvals/SKILL.md +4 -4
  302. package/skills/permdock-approvals/references/stores-and-resume.md +15 -4
  303. package/skills/permdock-audit/SKILL.md +3 -3
  304. package/skills/permdock-credentials/SKILL.md +4 -4
  305. package/skills/permdock-credentials/references/tokens-keys-links.md +7 -2
  306. package/skills/permdock-data/SKILL.md +4 -4
  307. package/skills/permdock-data/references/queries-and-rls.md +14 -6
  308. package/skills/permdock-data/references/relationships.md +5 -3
  309. package/skills/permdock-tenancy/SKILL.md +9 -6
  310. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +14 -8
  311. package/skills/permdock-wire/SKILL.md +4 -4
  312. package/skills/permdock-wire/references/adapters.md +42 -30
  313. package/skills/permdock-wire/references/policy-options.md +5 -3
  314. package/dist/approvers-aH0PJkmf.js +0 -20
  315. package/dist/catalog-idsHc0vo.js +0 -2
  316. package/dist/collect-B7_TIfmg.js +0 -49
  317. package/dist/collect-fRPAQIWb.js +0 -2
  318. package/dist/compile-CQbvyIBr.d.ts +0 -30
  319. package/dist/config-BPYmjTOp.js +0 -26
  320. package/dist/context-gtAwAILx.js +0 -6
  321. package/dist/create-BKF3dgFk.d.ts +0 -162
  322. package/dist/create-CSkhDU9T.js +0 -222
  323. package/dist/doctor-BGle8Gqi.js +0 -1314
  324. package/dist/helpers-DnSOrhB9.js +0 -682
  325. package/dist/index-fG6NSXlc.d.ts +0 -9
  326. package/dist/kernel-YOGCWNLf.js +0 -211
  327. package/dist/load-QOOm1z70.js +0 -2
  328. package/dist/manifest-DDQbC6K0.d.ts +0 -118
  329. package/dist/map-error-RJ3ZsUyA.js +0 -16
  330. package/dist/may-use-CnFEjVEp.js +0 -37
  331. package/dist/pg-4GJWDUxG.js +0 -953
  332. package/dist/plugin-4gr7IxFJ.js +0 -65
  333. package/dist/protected-B4K3BKoX.js +0 -138
  334. package/dist/protected-wY7nXhY9.d.ts +0 -23
  335. package/dist/provider-_wx46HpB.js +0 -48
  336. package/dist/rls-CJVja9Ww.js +0 -2119
  337. package/dist/rls-helpers-BxRuif0l.js +0 -1346
  338. package/dist/runtime-DP9ttFh1.js +0 -27
  339. package/dist/skills-Dx3QLnMY.js +0 -110
  340. package/dist/source-DoBBYJi2.js +0 -6
  341. package/dist/sources-DVHM3Mwq.js +0 -284
  342. package/dist/store-C6hFW6ta.js +0 -508
  343. package/dist/subject-settings-xt7V845g.js +0 -82
  344. package/dist/supabase-hook-DW-xP4hU.js +0 -2
  345. package/dist/types-DbWdEfcm.d.ts +0 -87
  346. package/dist/types-bva3i4Gf.d.ts +0 -98
  347. package/dist/types-i4BAOvdb.d.ts +0 -97
  348. package/dist/usage-PyEor6GA.js +0 -2
  349. package/dist/version-CnSh33Fj.js +0 -16
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://permdock.dev/schemas/supabase-manifest-v1.json",
3
+ "$id": "https://permdock.com/schemas/supabase-manifest-v1.json",
4
4
  "title": "PermDock Supabase hook manifest v1",
5
5
  "description": "What `permdock supabase inspect --json` prints and `--out` writes: the generated hook, the SQL helpers, the claims, the membership sources and the columns that decide them. Fields are only added within v1.",
6
6
  "type": "object",
@@ -20,7 +20,7 @@
20
20
  ],
21
21
  "properties": {
22
22
  "$schema": {
23
- "const": "https://permdock.dev/schemas/supabase-manifest-v1.json"
23
+ "const": "https://permdock.com/schemas/supabase-manifest-v1.json"
24
24
  },
25
25
  "version": { "const": 1 },
26
26
  "hook": {
@@ -29,7 +29,14 @@
29
29
  "properties": {
30
30
  "schema": { "$ref": "#/$defs/identifier" },
31
31
  "function": { "const": "custom_access_token_hook" },
32
- "out": { "type": "string" }
32
+ "out": { "type": "string" },
33
+ "before": {
34
+ "type": "array",
35
+ "items": {
36
+ "type": "string",
37
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*\\.[A-Za-z_][A-Za-z0-9_]*$"
38
+ }
39
+ }
33
40
  }
34
41
  },
35
42
  "helpers": {
@@ -128,6 +135,69 @@
128
135
  "memberships": {
129
136
  "type": "array",
130
137
  "items": { "$ref": "#/$defs/membership" }
138
+ },
139
+ "customRoles": { "type": "boolean" },
140
+ "roles": {
141
+ "type": "object",
142
+ "required": ["table", "user", "role"],
143
+ "additionalProperties": false,
144
+ "properties": {
145
+ "table": { "type": "string" },
146
+ "user": { "$ref": "#/$defs/column" },
147
+ "role": {
148
+ "oneOf": [
149
+ { "$ref": "#/$defs/role" },
150
+ {
151
+ "type": "array",
152
+ "minItems": 2,
153
+ "items": { "$ref": "#/$defs/role" }
154
+ }
155
+ ]
156
+ }
157
+ }
158
+ },
159
+ "suspension": {
160
+ "type": "object",
161
+ "additionalProperties": false,
162
+ "properties": {
163
+ "users": { "$ref": "#/$defs/activeRow" },
164
+ "scopes": {
165
+ "type": "object",
166
+ "additionalProperties": { "$ref": "#/$defs/activeRow" }
167
+ },
168
+ "memberships": {
169
+ "type": "object",
170
+ "required": ["keep"],
171
+ "additionalProperties": false,
172
+ "properties": {
173
+ "keep": {
174
+ "description": "The permission keys a membership whose disabledAt column is set still holds.",
175
+ "type": "array",
176
+ "items": { "type": "string" }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ },
182
+ "assignments": {
183
+ "type": "object",
184
+ "required": ["tables"],
185
+ "additionalProperties": false,
186
+ "properties": {
187
+ "tables": { "type": "array", "items": { "type": "string" } }
188
+ }
189
+ },
190
+ "apiKeys": {
191
+ "type": "object",
192
+ "required": ["claim", "scopes", "tenant", "roles", "serviceRoles"],
193
+ "additionalProperties": false,
194
+ "properties": {
195
+ "claim": { "type": "string" },
196
+ "scopes": { "type": "string" },
197
+ "tenant": { "type": "string" },
198
+ "roles": { "type": "string" },
199
+ "serviceRoles": { "type": "array", "items": { "type": "string" } }
200
+ }
131
201
  }
132
202
  }
133
203
  },
@@ -145,6 +215,26 @@
145
215
  "hook": { "const": "v1" },
146
216
  "grants": { "const": "v1" }
147
217
  }
218
+ },
219
+ "requires": {
220
+ "description": "The supabase/sdk capability-matrix feature ids the hook, the helpers and subjectFromSupabase depend on, as of the matrix release tag.",
221
+ "type": "object",
222
+ "required": ["matrix", "capabilities"],
223
+ "additionalProperties": false,
224
+ "properties": {
225
+ "matrix": {
226
+ "type": "string",
227
+ "pattern": "^capability-matrix-v1\\.[0-9]+\\.[0-9]+$"
228
+ },
229
+ "capabilities": {
230
+ "type": "array",
231
+ "uniqueItems": true,
232
+ "items": {
233
+ "type": "string",
234
+ "pattern": "^[a-z][a-z0-9_]*\\.[a-z0-9_]+\\.[a-z0-9_]+$"
235
+ }
236
+ }
237
+ }
148
238
  }
149
239
  },
150
240
  "$defs": {
@@ -156,10 +246,19 @@
156
246
  "type": "string",
157
247
  "pattern": "^[A-Za-z_][A-Za-z0-9_]*\\.[A-Za-z_][A-Za-z0-9_]*$"
158
248
  },
159
- "user": { "$ref": "#/$defs/column" },
249
+ "user": { "$ref": "#/$defs/user" },
160
250
  "scope": { "$ref": "#/$defs/value" },
161
251
  "id": { "$ref": "#/$defs/column" },
162
- "role": { "$ref": "#/$defs/value" },
252
+ "role": {
253
+ "oneOf": [
254
+ { "$ref": "#/$defs/role" },
255
+ {
256
+ "type": "array",
257
+ "minItems": 2,
258
+ "items": { "$ref": "#/$defs/role" }
259
+ }
260
+ ]
261
+ },
163
262
  "within": {
164
263
  "oneOf": [
165
264
  { "$ref": "#/$defs/column" },
@@ -178,6 +277,7 @@
178
277
  },
179
278
  "via": { "$ref": "#/$defs/value" },
180
279
  "expiresAt": { "$ref": "#/$defs/column" },
280
+ "disabledAt": { "$ref": "#/$defs/column" },
181
281
  "columns": {
182
282
  "type": "array",
183
283
  "items": { "$ref": "#/$defs/identifier" }
@@ -185,9 +285,26 @@
185
285
  }
186
286
  },
187
287
  "identifier": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
288
+ "activeRow": {
289
+ "type": "object",
290
+ "required": ["table", "id"],
291
+ "additionalProperties": false,
292
+ "properties": {
293
+ "table": { "type": "string" },
294
+ "id": { "$ref": "#/$defs/identifier" },
295
+ "disabledAt": { "$ref": "#/$defs/identifier" },
296
+ "status": { "$ref": "#/$defs/identifier" },
297
+ "active": { "type": "array", "items": { "type": "string" } },
298
+ "keep": {
299
+ "description": "A scope only: the permission keys members of a suspended instance still hold.",
300
+ "type": "array",
301
+ "items": { "type": "string" }
302
+ }
303
+ }
304
+ },
188
305
  "helperName": {
189
306
  "type": "string",
190
- "pattern": "^(permdock_has|permitted_[a-z][a-z0-9_]*_ids|member_[a-z][a-z0-9_]*_ids(_for)?)$"
307
+ "pattern": "^(permdock_has(_for)?|permitted_[a-z][a-z0-9_]*_(ids|permission_keys)(_for)?|member_[a-z][a-z0-9_]*_ids(_for)?|permdock_can_assign(_any|_custom_role)?(_for)?|permdock_api_key_allows|permdock_user_id)$"
191
308
  },
192
309
  "column": {
193
310
  "type": "object",
@@ -195,6 +312,33 @@
195
312
  "additionalProperties": false,
196
313
  "properties": { "column": { "$ref": "#/$defs/identifier" } }
197
314
  },
315
+ "role": {
316
+ "oneOf": [{ "$ref": "#/$defs/value" }, { "$ref": "#/$defs/through" }]
317
+ },
318
+ "user": {
319
+ "oneOf": [{ "$ref": "#/$defs/column" }, { "$ref": "#/$defs/through" }]
320
+ },
321
+ "through": {
322
+ "type": "object",
323
+ "required": ["column", "through"],
324
+ "additionalProperties": false,
325
+ "properties": {
326
+ "column": { "$ref": "#/$defs/identifier" },
327
+ "through": {
328
+ "type": "object",
329
+ "required": ["table", "id", "column"],
330
+ "additionalProperties": false,
331
+ "properties": {
332
+ "table": {
333
+ "type": "string",
334
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*\\.[A-Za-z_][A-Za-z0-9_]*$"
335
+ },
336
+ "id": { "$ref": "#/$defs/identifier" },
337
+ "column": { "$ref": "#/$defs/identifier" }
338
+ }
339
+ }
340
+ }
341
+ },
198
342
  "value": {
199
343
  "oneOf": [
200
344
  { "$ref": "#/$defs/column" },
@@ -4,13 +4,13 @@ description: Explains how PermDock decides and routes to the right PermDock skil
4
4
  license: MIT
5
5
  metadata:
6
6
  author: ScaleDockHQ
7
- homepage: https://permdock.dev/docs/for-ai-agents
7
+ homepage: https://permdock.com/docs/for-ai-agents
8
8
  repository: https://github.com/ScaleDockHQ/permdock
9
9
  ---
10
10
 
11
11
  # PermDock
12
12
 
13
- PermDock is typed permissions for TypeScript apps, APIs, databases and AI agents. Permissions are defined once, decided in process, compiled to queries and RLS, and serialised to client snapshots ([for AI agents](https://permdock.dev/docs/for-ai-agents)). This skill holds the model every other PermDock skill assumes, and says which one to load.
13
+ PermDock is typed permissions for TypeScript apps, APIs, databases and AI agents. Permissions are defined once, decided in process, compiled to queries and RLS, and serialised to client snapshots ([for AI agents](https://permdock.com/docs/for-ai-agents)). This skill holds the model every other PermDock skill assumes, and says which one to load.
14
14
 
15
15
  ## Inputs (find out before starting)
16
16
 
@@ -44,13 +44,13 @@ PermDock is typed permissions for TypeScript apps, APIs, databases and AI agents
44
44
 
45
45
  ✓ The skill for the task is loaded, and `permdock-wire` has run first if the app has no factory file.
46
46
 
47
- 2. **Look identifiers up, never guess them.** Read the owning page through the docs MCP (`https://permdock.dev/mcp`, tools `search`, `list_pages` and `get_page`), or append `.md` to any `https://permdock.dev/docs/...` URL. Every public name follows the [naming convention](https://permdock.dev/docs/getting-started/naming).
47
+ 2. **Look identifiers up, never guess them.** Read the owning page through the docs MCP (`https://permdock.com/mcp`, tools `search`, `list_pages` and `get_page`), or append `.md` to any `https://permdock.com/docs/...` URL. Every public name follows the [naming convention](https://permdock.com/docs/getting-started/naming).
48
48
  ✓ Each identifier written into the app appears on a docs page or in `node_modules/permdock`.
49
- 3. **Read a decision.** `decide()` returns `{ outcome, denials: [{ reason, ... }], alternatives }`. `reason` is one of the closed list on [decisions](https://permdock.dev/docs/concepts/decisions); `alternatives` are permissions on the same resource the subject does hold. HTTP adapters answer RFC 9457 Problem Details ([errors](https://permdock.dev/docs/concepts/errors)); for the format, defer to the `problem-details` spec skill (`npx skills add ScaleDockHQ/scaledock-skills --skill problem-details`).
49
+ 3. **Read a decision.** `decide()` returns `{ outcome, denials: [{ reason, ... }], alternatives }`. `reason` is one of the closed list on [decisions](https://permdock.com/docs/concepts/decisions); `alternatives` are permissions on the same resource the subject does hold. HTTP adapters answer RFC 9457 Problem Details ([errors](https://permdock.com/docs/concepts/errors)); for the format, defer to the `problem-details` spec skill (`npx skills add ScaleDockHQ/scaledock-skills --skill problem-details`).
50
50
  ✓ Each denial the user asked about is named by its reason.
51
- 4. **Explain an unexpected denial.** Run `permdock.explain(permission, data)` in a test or a script. `trace.denies[0]` is the deny that won (give denies a `name` so it reads as a rule), `trace.allows` the allows it overrode, `trace.skipped` the grants passed over and why ([explain](https://permdock.dev/docs/concepts/decisions#explain)). The trace never reaches the decision log. To preview a plan before acting, `simulate([[permission, data], ...])` returns every decision.
51
+ 4. **Explain an unexpected denial.** Run `permdock.explain(permission, data)` in a test or a script. `trace.denies[0]` is the deny that won (give denies a `name` so it reads as a rule), `trace.allows` the allows it overrode, `trace.skipped` the grants passed over and why ([explain](https://permdock.com/docs/concepts/decisions#explain)). The trace never reaches the decision log. To preview a plan before acting, `simulate([[permission, data], ...])` returns every decision.
52
52
  ✓ The cause is a named grant, condition or missing input, not a guess.
53
- 5. **Check the project.** Run `pnpm exec permdock doctor` (`--json` for machine output). Each finding has a stable `PD0xx` code and a one-line fix ([doctor](https://permdock.dev/docs/cli/doctor)); the topic skills name the codes for their area.
53
+ 5. **Check the project.** Run `pnpm exec permdock doctor` (`--json` for machine output). Each finding has a stable `PD0xx` code and a one-line fix ([doctor](https://permdock.com/docs/cli/doctor)); the topic skills name the codes for their area.
54
54
  ✓ `permdock doctor` reports no error.
55
55
 
56
56
  ## Verify before done
@@ -63,4 +63,4 @@ PermDock is typed permissions for TypeScript apps, APIs, databases and AI agents
63
63
  ## Reference index
64
64
 
65
65
  - Skills: `permdock-wire`, `permdock-audit`, `permdock-agents`, `permdock-approvals`, `permdock-tenancy`, `permdock-data`, `permdock-credentials`, all from `npx skills add ScaleDockHQ/PermDock --skill <name>`.
66
- - Docs: [for AI agents](https://permdock.dev/docs/for-ai-agents), [naming](https://permdock.dev/docs/getting-started/naming), [policies](https://permdock.dev/docs/concepts/policies), [decisions](https://permdock.dev/docs/concepts/decisions), [threat model](https://permdock.dev/docs/security/threat-model), [doctor](https://permdock.dev/docs/cli/doctor), `https://permdock.dev/llms.txt`.
66
+ - Docs: [for AI agents](https://permdock.com/docs/for-ai-agents), [naming](https://permdock.com/docs/getting-started/naming), [policies](https://permdock.com/docs/concepts/policies), [decisions](https://permdock.com/docs/concepts/decisions), [threat model](https://permdock.com/docs/security/threat-model), [doctor](https://permdock.com/docs/cli/doctor), `https://permdock.com/llms.txt`.
@@ -4,13 +4,13 @@ description: Guards AI agent tool calls with PermDock subjects, actors and deleg
4
4
  license: MIT
5
5
  metadata:
6
6
  author: ScaleDockHQ
7
- homepage: https://permdock.dev/docs/security/delegation
7
+ homepage: https://permdock.com/docs/security/delegation
8
8
  repository: https://github.com/ScaleDockHQ/permdock
9
9
  ---
10
10
 
11
11
  # PermDock agents
12
12
 
13
- An agent call has a principal (the user whose grants are evaluated), an actor (the agent making the call) and a delegation (what the user handed over). The decision is the principal's grants intersected with the delegation ([delegation](https://permdock.dev/docs/security/delegation)). Set up `permissions.ts`, `policy.ts` and the factory first with the `permdock-wire` skill (`npx skills add ScaleDockHQ/PermDock --skill permdock-wire`).
13
+ An agent call has a principal (the user whose grants are evaluated), an actor (the agent making the call) and a delegation (what the user handed over). The decision is the principal's grants intersected with the delegation ([delegation](https://permdock.com/docs/security/delegation)). Set up `permissions.ts`, `policy.ts` and the factory first with the `permdock-wire` skill (`npx skills add ScaleDockHQ/PermDock --skill permdock-wire`).
14
14
 
15
15
  ## Inputs (find out, or ask before starting)
16
16
 
@@ -32,7 +32,7 @@ An agent call has a principal (the user whose grants are evaluated), an actor (t
32
32
 
33
33
  ## Workflow
34
34
 
35
- 1. **Name the three parts per surface.** Write down the principal source, the actor source and the delegation source for each runtime from the Inputs. The adapter table on [delegation](https://permdock.dev/docs/security/delegation#how-adapters-fill-actor-and-delegation) shows what each adapter fills itself (MCP and A2A read token scopes; in-process runtimes take a `delegation` option).
35
+ 1. **Name the three parts per surface.** Write down the principal source, the actor source and the delegation source for each runtime from the Inputs. The adapter table on [delegation](https://permdock.com/docs/security/delegation#how-adapters-fill-actor-and-delegation) shows what each adapter fills itself (MCP and A2A read token scopes; in-process runtimes take a `delegation` option).
36
36
  ✓ Every surface has all three, and none reads from model-controlled input.
37
37
  2. **Map the tools.** Use the runtime's `createPermDock` with `subject`, `actor` and a `tools` map, and pass the returned hook to the runtime. -> [references/runtimes.md](references/runtimes.md)
38
38
  ✓ Every tool the agent can call has a `permission`, and every instance permission has a `data` loader that parses its arguments.
@@ -59,7 +59,7 @@ An agent call has a principal (the user whose grants are evaluated), an actor (t
59
59
  ✓ A destructive tool returns the runtime's approval outcome instead of running.
60
60
  5. **Wire the agent-facing surfaces.** A2A: serve `agentCard()` publicly, `extendedAgentCard(auth)` behind auth, and `protectSkill` on the task endpoint. WebMCP: `registerTools` from a snapshot, with the server re-checking. Web Bot Auth: `webBotAuth: (request) => verifyWebBotAuth(request, { verify: true, keys })` on the HTTP adapter. -> [references/runtimes.md](references/runtimes.md)
61
61
  ✓ Each surface passes the Verify list of its spec skill.
62
- 6. **Test.** Add scenario tests with `permdock/testing` for one delegated grant, one `not-delegated` denial and one approval per destructive tool ([scenario testing](https://permdock.dev/docs/guides/scenario-testing)). Then review with the `permdock-audit` skill, which reports ASI02 and ASI03 per adapter.
62
+ 6. **Test.** Add scenario tests with `permdock/testing` for one delegated grant, one `not-delegated` denial and one approval per destructive tool ([scenario testing](https://permdock.com/docs/guides/scenario-testing)). Then review with the `permdock-audit` skill, which reports ASI02 and ASI03 per adapter.
63
63
  ✓ The tests pass and the audit has no blocker.
64
64
 
65
65
  ## Verify before done
@@ -74,4 +74,4 @@ An agent call has a principal (the user whose grants are evaluated), an actor (t
74
74
  ## Reference index
75
75
 
76
76
  - [references/runtimes.md](references/runtimes.md): factory shapes and outcome mapping for AI SDK, Claude Agent SDK, Eve, OpenAI Agents SDK, MCP, A2A, WebMCP, Web Bot Auth and `permdock/terminal`.
77
- - Docs: [delegation](https://permdock.dev/docs/security/delegation), [subject](https://permdock.dev/docs/concepts/subject), [OWASP Agentic mapping](https://permdock.dev/docs/security/owasp-agentic), adapter pages under `https://permdock.dev/docs/adapters/<name>`.
77
+ - Docs: [delegation](https://permdock.com/docs/security/delegation), [subject](https://permdock.com/docs/concepts/subject), [OWASP Agentic mapping](https://permdock.com/docs/security/owasp-agentic), adapter pages under `https://permdock.com/docs/adapters/<name>`.
@@ -1,6 +1,6 @@
1
1
  # Agent runtimes
2
2
 
3
- Every agent adapter exports `createPermDock` from `permdock/<runtime>` and takes `subject`, `actor`, `delegation`, `tools` and `store`. One permission per tool. Instance actions load the row through `data`; tool input arrives as `unknown`, so parse it before loading. The current adapter page is `https://permdock.dev/docs/adapters/<name>`.
3
+ Every agent adapter exports `createPermDock` from `permdock/<runtime>` and takes `subject`, `actor`, `delegation`, `tools` and `store`. One permission per tool. Instance actions load the row through `data`; tool input arrives as `unknown`, so parse it before loading. The current adapter page is `https://permdock.com/docs/adapters/<name>`.
4
4
 
5
5
  ## AI SDK — `permdock/ai-sdk`
6
6
 
@@ -27,7 +27,7 @@ export const { toolApproval, capabilityMiddleware, needsApproval } =
27
27
  });
28
28
  ```
29
29
 
30
- Pass `toolApproval` into `generateText` / `ToolLoopAgent`. Wrap the model with `wrapLanguageModel({ model, middleware: capabilityMiddleware({ user }) })` per caller. Use `needsApproval(permissions.post.delete)` only on `WorkflowAgent`. `denied` maps to `'denied'`, `approval-required` to `'user-approval'`, and `'not-applicable'` is never returned ([AI SDK adapter](https://permdock.dev/docs/adapters/ai-sdk)).
30
+ Pass `toolApproval` into `generateText` / `ToolLoopAgent`. Wrap the model with `wrapLanguageModel({ model, middleware: capabilityMiddleware({ user }) })` per caller. Use `needsApproval(permissions.post.delete)` only on `WorkflowAgent`. `denied` maps to `'denied'`, `approval-required` to `'user-approval'`, and `'not-applicable'` is never returned ([AI SDK adapter](https://permdock.com/docs/adapters/ai-sdk)). Tools without a permission are hidden and denied unless `unmapped: 'allow'`; to combine PermDock with the app's own confirmation, pass `composeToolApproval(appApproval)` as `toolApproval` instead of wrapping the adapter: the app's function is asked only for calls PermDock grants, and its answer passes through (`undefined` stays not applicable; an unreadable answer denies).
31
31
 
32
32
  ## Claude Agent SDK — `permdock/claude-agent`
33
33
 
@@ -47,7 +47,7 @@ export const { canUseTool, permissionRequestHook } = createPermDock(policy, {
47
47
  });
48
48
  ```
49
49
 
50
- `canUseTool` returns `{ behavior: 'allow', updatedInput }` or `{ behavior: 'deny', message }`; approval-required is a deny whose message carries the pending token. Pass a `store`: once a reviewer approves, the retried call is allowed exactly once. `mcp__` tools are trusted only from `mcpSources` (default `['sdk']`). Pass `permissionRequestHook` under `hooks.PermissionRequest` ([Claude Agent adapter](https://permdock.dev/docs/adapters/claude-agent)).
50
+ `canUseTool` returns `{ behavior: 'allow', updatedInput }` or `{ behavior: 'deny', message }`; approval-required is a deny whose message carries the pending token. Pass a `store`: once a reviewer approves, the retried call is allowed exactly once. `mcp__` tools are trusted only from `mcpSources` (default `['sdk']`). Pass `permissionRequestHook` under `hooks.PermissionRequest` ([Claude Agent adapter](https://permdock.com/docs/adapters/claude-agent)).
51
51
 
52
52
  ## Eve — `permdock/eve`
53
53
 
@@ -65,7 +65,7 @@ export const { approval, approvalFor, permdock } = createPermDock(policy, {
65
65
  });
66
66
  ```
67
67
 
68
- Pass `approval` as the tool's `approval`. Default subject and actor read `session.auth.initiator` / `current`. `approval.request(ctx)` maps granted to Eve's `not-applicable` (continue), approval-required to `user-approval`, denied to `{ type: 'denied', reason }`; Eve's re-check of a call nobody approved is denied. `approval.response(ctx)` maps the responder through the same `subject`. Use a durable `store` when replicas share sessions ([Eve adapter](https://permdock.dev/docs/adapters/eve)).
68
+ Pass `approval` as the tool's `approval`. Default subject and actor read `session.auth.initiator` / `current`. `approval.request(ctx)` maps granted to Eve's `not-applicable` (continue), approval-required to `user-approval`, denied to `{ type: 'denied', reason }`; Eve's re-check of a call nobody approved is denied. `approval.response(ctx)` maps the responder through the same `subject`. Use a durable `store` when replicas share sessions ([Eve adapter](https://permdock.com/docs/adapters/eve)).
69
69
 
70
70
  ## OpenAI Agents SDK — `permdock/openai`
71
71
 
@@ -86,7 +86,7 @@ export const { needsApproval, guardTools, resolveInterruptions, permdock } =
86
86
  });
87
87
  ```
88
88
 
89
- `needsApproval(permission)` is the tool's `needsApproval`; it reads `runContext.context` and is true unless granted. `guardTools` drops tools with no grant. `resolveInterruptions(state, interruptions, { context })` approves or rejects each pause and returns the still-pending `ApprovalRequest`s. On resume, rebuild the context from the session and use `RunState.fromStringWithContext` ([OpenAI adapter](https://permdock.dev/docs/adapters/openai)).
89
+ `needsApproval(permission)` is the tool's `needsApproval`; it reads `runContext.context` and is true unless granted. `guardTools` drops tools with no grant. `resolveInterruptions(state, interruptions, { context })` approves or rejects each pause and returns the still-pending `ApprovalRequest`s. On resume, rebuild the context from the session and use `RunState.fromStringWithContext` ([OpenAI adapter](https://permdock.com/docs/adapters/openai)).
90
90
 
91
91
  ## MCP — `permdock/mcp`
92
92
 
@@ -113,10 +113,12 @@ server.registerTool(
113
113
  );
114
114
  ```
115
115
 
116
- `actor.kind` is `'mcp-client'`, and `delegation` comes from the token's scopes and `authorization_details`. Every `registerTool` / `registerResource` / `registerPrompt` needs a `permission`. Lists are filtered per caller. A missing scope is an `insufficient_scope` step-up (HTTP `403`) naming only the scope the call needs. Set `resource` to the server's URL so tokens for another audience are refused. Denied calls return `isError: true` with Decision `structuredContent`. `approval-required` parks the call in `store` and returns `isError: true` with the token, or an `input_required` URL request when `approval.at` is set and the client declares URL elicitation; the retried call runs once after approval (token optional under `_meta["dev.permdock/approval"]`, never from tool arguments) ([MCP adapter](https://permdock.dev/docs/adapters/mcp)).
116
+ `actor.kind` is `'mcp-client'` unless `actorKind` sets another (`'oauth-client'` makes the token the same actor kind `permdock/supabase` and `permdock/jwt` give it, so one delegation covers both), and `delegation` comes from the token's scopes and `authorization_details`. Every `registerTool` / `registerResource` / `registerPrompt` needs a `permission`. Lists are filtered per caller. A missing scope is an `insufficient_scope` step-up (HTTP `403`) naming only the scope the call needs. When the authorization server issues coarse scopes (`mcp:read`), declare them in `definePolicy({ oauthScopes })` instead of expanding scopes yourself: they are expanded into the delegation and named in challenges. Set `resource` to the server's URL so tokens for another audience are refused. Denied calls return `isError: true` with Decision `structuredContent`. `approval-required` parks the call in `store` and returns `isError: true` with the token, or an `input_required` URL request when `approval.at` is set and the client declares URL elicitation; the retried call runs once after approval (token optional under `_meta["dev.permdock/approval"]`, never from tool arguments) ([MCP adapter](https://permdock.com/docs/adapters/mcp)).
117
117
 
118
118
  An MCP server that is not an SDK `McpServer` cannot be wrapped: narrow the tool's `meta` with `isPermission`, filter its tool list with `mayUse(permdock, permission)` from `permdock`, and decide each call with `permdock.decide(permission, args)` in its `authorize` hook. `mayUse` is a listing hint, never a decision.
119
119
 
120
+ When a tool's handler calls an oRPC procedure that runs `protect`, use `protectServer(server, { enforce: 'procedure', permissionFor: (name) => permissionOf(procedures.get(name)) })` with `permissionOf` from `permdock/orpc`. `tools/list` and annotations follow the permission; the call is not guarded, so each call decides once, in the procedure. `data` and `longRunning` throw in this mode, and the mode covers the whole server. When the same operations are REST routes, declare each permission once with `operationPermissions({ 'GET /customers/{id}': { permission, operationId } })` from `permdock/openapi` and pass `permissionFor: operations.forOperation`; the HTTP gate reads `operations.forRequest(method, path)` from the same object. When two operations share a permission but need different coarse scopes (reading an export with `mcp:read`, creating one with `mcp:write`), list the permission under both in `oauthScopes`, then narrow each operation with `oauthScopes: ['mcp:read']` on its entry (or on the tool config): pass `oauthScopesFor: operations.oauthScopesForOperation` to `protectServer`, and `operations` to `permdock/server` (or `protect`'s `oauthScopes`) for the REST routes, which then answer `insufficient_scope` naming that scope. A route that checks no permission but should still require a scope (a chat endpoint, setting the active organization) uses `protect(null, undefined, { oauthScopes: ['api:chat'] })` or an operation entry with only `oauthScopes`; never write an app-side rule that maps HTTP methods to scopes.
121
+
120
122
  ## A2A — `permdock/a2a`
121
123
 
122
124
  ```ts
@@ -151,7 +153,7 @@ app.post(
151
153
  );
152
154
  ```
153
155
 
154
- Identity comes from transport auth, never the task body. `actor.kind` is `'a2a'`, with `delegation` from the caller's token. Each skill's `securityRequirements` name the permission's `scope`. The public card is never filtered; `extendedAgentCard(auth)` keeps only skills the caller has a grant for. An instance-level skill without `data` throws at startup ([A2A adapter](https://permdock.dev/docs/adapters/a2a)).
156
+ Identity comes from transport auth, never the task body. `actor.kind` is `'a2a'`, with `delegation` from the caller's token. Each skill's `securityRequirements` name the permission's `scope`. The public card is never filtered; `extendedAgentCard(auth)` keeps only skills the caller has a grant for. An instance-level skill without `data` throws at startup ([A2A adapter](https://permdock.com/docs/adapters/a2a)).
155
157
 
156
158
  ## WebMCP — `permdock/webmcp`
157
159
 
@@ -173,7 +175,7 @@ registerTools(document.modelContext, permissions.post, {
173
175
  });
174
176
  ```
175
177
 
176
- Never import a policy into this entry. A missing `document.modelContext` is a no-op. Tools re-register when the snapshot changes. The client check is a filter: the server adapter behind `api.posts` makes the decision. `onApprovalRequired` opens the page's own confirmation dialog ([WebMCP adapter](https://permdock.dev/docs/adapters/webmcp)).
178
+ Never import a policy into this entry. A missing `document.modelContext` is a no-op. Tools re-register when the snapshot changes. The client check is a filter: the server adapter behind `api.posts` makes the decision. `onApprovalRequired` opens the page's own confirmation dialog ([WebMCP adapter](https://permdock.com/docs/adapters/webmcp)).
177
179
 
178
180
  ## Web Bot Auth on HTTP adapters
179
181
 
@@ -192,7 +194,7 @@ export const { permdock, protect } = createPermDock(policy, {
192
194
  });
193
195
  ```
194
196
 
195
- A verified RFC 9421 signer becomes the actor with `kind: 'web-bot-auth'`; `delegation` comes from a bearer token on the same request, otherwise it is empty. A failed signature throws `InvalidSignatureError`, never an anonymous actor ([Web Bot Auth](https://permdock.dev/docs/standards/web-bot-auth)).
197
+ A verified RFC 9421 signer becomes the actor with `kind: 'web-bot-auth'`; `delegation` comes from a bearer token on the same request, otherwise it is empty. A failed signature throws `InvalidSignatureError`, never an anonymous actor ([Web Bot Auth](https://permdock.com/docs/standards/web-bot-auth)).
196
198
 
197
199
  ## Terminal — `permdock/terminal`
198
200
 
@@ -208,4 +210,4 @@ export const { permdock, protect, filterCommands, format, exitCode } =
208
210
  });
209
211
  ```
210
212
 
211
- For the app's own CLI; not the `permdock` binary. Never accept `--user` or `--actor` as identity. In CI, verify the job token with `subjectFromCiOidc(jwt, { provider: 'github', audience })` from `permdock/jwt`, which returns a `workload` principal, never a user. A `destructive` permission asks for the resource id to be typed, and exits `64` without a terminal unless `--yes` is passed; `--yes` never approves an `approval-required` call. `--dry-run` decides and exits with the outcome's code without running the action ([terminal adapter](https://permdock.dev/docs/adapters/terminal)).
213
+ For the app's own CLI; not the `permdock` binary. Never accept `--user` or `--actor` as identity. In CI, verify the job token with `subjectFromCiOidc(jwt, { provider: 'github', audience })` from `permdock/jwt`, which returns a `workload` principal, never a user. A `destructive` permission asks for the resource id to be typed, and exits `64` without a terminal unless `--yes` is passed; `--yes` never approves an `approval-required` call. `--dry-run` decides and exits with the outcome's code without running the action ([terminal adapter](https://permdock.com/docs/adapters/terminal)).
@@ -4,13 +4,13 @@ description: Requires human approval on PermDock grants and resumes the approved
4
4
  license: MIT
5
5
  metadata:
6
6
  author: ScaleDockHQ
7
- homepage: https://permdock.dev/docs/security/approvals
7
+ homepage: https://permdock.com/docs/security/approvals
8
8
  repository: https://github.com/ScaleDockHQ/permdock
9
9
  ---
10
10
 
11
11
  # PermDock approvals
12
12
 
13
- `approval-required` is the third outcome: the subject may do it, but a person other than the requester confirms each call. An approval never grants something the subject could not do, and a `deny` still wins ([approval security](https://permdock.dev/docs/security/approvals)). Set up the policy and factory first with the `permdock-wire` skill (`npx skills add ScaleDockHQ/PermDock --skill permdock-wire`).
13
+ `approval-required` is the third outcome: the subject may do it, but a person other than the requester confirms each call. An approval never grants something the subject could not do, and a `deny` still wins ([approval security](https://permdock.com/docs/security/approvals)). Set up the policy and factory first with the `permdock-wire` skill (`npx skills add ScaleDockHQ/PermDock --skill permdock-wire`).
14
14
 
15
15
  ## Inputs (find out, or ask before starting)
16
16
 
@@ -61,7 +61,7 @@ metadata:
61
61
  ✓ `testApprovalPolicySource` from `permdock/testing` passes on the source.
62
62
  6. **Surface and resume.** Map the outcome to each runtime's approval hook and resume with the token: the `PermDock-Approval` header over HTTP, the runtime's own resume for agents. -> [references/stores-and-resume.md](references/stores-and-resume.md#surfaces)
63
63
  ✓ The approved call runs once; a second resume is denied with `approval-consumed`.
64
- 7. **Test.** Add a scenario test per approval grant: the ask, an approval by an eligible user, a refused self-approval, and the single resume ([scenario testing](https://permdock.dev/docs/guides/scenario-testing)). Run `testApprovalStore` on a custom store.
64
+ 7. **Test.** Add a scenario test per approval grant: the ask, an approval by an eligible user, a refused self-approval, and the single resume ([scenario testing](https://permdock.com/docs/guides/scenario-testing)). Run `testApprovalStore` on a custom store.
65
65
  ✓ The tests pass.
66
66
 
67
67
  ## Verify before done
@@ -77,4 +77,4 @@ metadata:
77
77
  ## Reference index
78
78
 
79
79
  - [references/stores-and-resume.md](references/stores-and-resume.md): `approvalsHandler` routes, custom stores, relation approvers, approval policies as data, the token, resume details and denial causes, the runtime surfaces table, delivery to chat and email.
80
- - Docs: [approval security](https://permdock.dev/docs/security/approvals), [approvals adapter](https://permdock.dev/docs/adapters/approvals), [wire formats](https://permdock.dev/docs/concepts/wire-formats).
80
+ - Docs: [approval security](https://permdock.com/docs/security/approvals), [approvals adapter](https://permdock.com/docs/adapters/approvals), [wire formats](https://permdock.com/docs/concepts/wire-formats).
@@ -1,6 +1,6 @@
1
1
  # Approval stores and the resume flow
2
2
 
3
- The API and the store contract are on the [approvals adapter](https://permdock.dev/docs/adapters/approvals); the token and the runtime table are on [approval security](https://permdock.dev/docs/security/approvals).
3
+ The API and the store contract are on the [approvals adapter](https://permdock.com/docs/adapters/approvals); the token and the runtime table are on [approval security](https://permdock.com/docs/security/approvals).
4
4
 
5
5
  ## Store and handler
6
6
 
@@ -22,8 +22,11 @@ const handler = approvalsHandler(store, {
22
22
  app.all("/permdock/approvals/*", (c) => handler(c.req.raw));
23
23
  ```
24
24
 
25
- - `memoryApprovalStore` is per process. On serverless or with several replicas, implement `ApprovalStore` over the app's database; the Drizzle recipe on the adapter page is the template, and `cloud().approvals` from `permdock/cloud` is the hosted implementation of the same interface.
25
+ The store's `ttl` is the window a request stays open when the call sets none; `resumeDecision({ ..., ttl })` sets it per call (milliseconds). A grant's `approval.ttl` only shortens either.
26
+
27
+ - `memoryApprovalStore` is per process. On serverless or with several replicas, implement `ApprovalStore` over the app's database; the Drizzle recipe on the adapter page is the template, and `cloud().approvals` from `permdock/cloud` is the hosted implementation of the same interface. On Postgres or Supabase, set `rls.approvals: true` and use `supabaseApprovalStore(admin, { onOpen })` from `permdock/supabase` over the generated table and functions; grant the functions to the server's role, and put notifications and superseding older requests in `onOpen`.
26
28
  - A custom store calls `assertApprover(request, by, requireDistinct, now, verdict.relations)` in `resolve` and computes the next record with `applyApprovalVerdict`, which records each signature's `stage`. `verdict.relations` holds `approverRelationKey` values that the handler, or `resolveApproval(store, token, verdict, { relations, permissions })`, computed with `approverRelations`; a store never derives them. `consume` must be atomic: two concurrent calls never both succeed.
29
+ - When the app's own rules decide who approves (a manager chain, delegates, a quorum it counts), record their verdict with `vouchApproval(store, token, { status, by, rule })` from `permdock/approvals` instead of mirroring those rules in `approvers` or copying the verdict into the request by hand. It resolves the request at once and records `vouched: rule`; the actor, requester and repeat checks still apply. Never take `vouched` from a request body.
27
30
  - Run `testApprovalStore(store, { reopen })` from `permdock/testing` on every custom store.
28
31
  - `cancelApprovals` rejects matching pending requests (for example when a session ends).
29
32
 
@@ -39,14 +42,16 @@ const permdock = await createPermDock(policy, user, {
39
42
  tenant: "o_acme", // absent: every tenant
40
43
  actors: ["agent"], // absent: every call
41
44
  where: { op: "gt", field: "amount", value: 1000 },
42
- approval: { by: "finance" }, // no escalation in data
45
+ approval: { by: "finance" }, // an escalation here widens only this entry's stages
43
46
  },
44
47
  ]),
45
48
  });
46
49
  ```
47
50
 
51
+ - Every adapter's `createPermDock` takes `approvalPolicies` (HTTP, MCP, A2A, AuthZEN, terminal and the agent adapters), so an entry also turns an agent call into `user-approval` or an MCP call into `approval-required`.
48
52
  - Entries are read once per instance and combine with the grant's own approval as stages (`sequential` if any part is, else `all`); the shortest `ttl` wins.
49
53
  - A throw or an invalid entry denies with detail `approval-policy-unavailable`. An unknown permission applies to nothing.
54
+ - `where` reads the row, so it works only on instance permissions; on a collection permission the entry does not load. Use `check` (the proposed row) there. Validate entries where they are saved with `validateApprovalPolicy(policy, entry)` (`{ ok: false, problem }` names `unknown-permission`, `invalid`, `where-on-collection` or `stale-on-without-version`).
50
55
  - Client snapshots do not see the entries; the server's `decide` adds the approval.
51
56
 
52
57
  ## Resume
@@ -57,6 +62,8 @@ const permdock = await createPermDock(policy, user, {
57
62
 
58
63
  The token binds the permission key, the resource id (or a digest of the data when there is no id), the principal, the tenant, the actor and the matched grant's conditions. Under `staleOn: 'resource-change'` it also binds the row's `version`.
59
64
 
65
+ A gate in your own code resumes the same way with `resumeDecision` from `permdock/approvals`, passing `token: carried ?? (await storedApprovalToken(store, decision))`: `storedApprovalToken` finds an approved or rejected request for the recomputed token, so the caller need not carry it. Do not reimplement it.
66
+
60
67
  Over HTTP, the client retries the same request with the `PermDock-Approval: <token>` header. In React, `approvalHeaders(token)` builds that header and `useApproval(decision)` requests and polls an approval from the UI.
61
68
 
62
69
  A bad resume is denied with detail `approval-not-found`, `approval-pending`, `approval-rejected`, `approval-expired`, `approval-consumed` or `approval-mismatch`; a changed row is `stale-approval`. `approvalsHandler` answers `403` for an ineligible approver (`approver-not-eligible`, the actor, or the principal without `distinct: false`) and `409` for a repeated one (`approver-repeated`).
@@ -80,4 +87,8 @@ For AG-UI event shapes, defer to the `ag-ui` spec skill (`npx skills add ScaleDo
80
87
 
81
88
  ## Delivery
82
89
 
83
- Notifying an approver is a listener on the `approval` event (`permdock.on('approval', …)`), never a package. A message or email carries only the token and links to a page where the approver signs in; the verdict goes through `approvalsHandler` with that session's subject. A link never approves on its own ([approvals adapter, Delivery](https://permdock.dev/docs/adapters/approvals#delivery)).
90
+ Notifying an approver is a listener on the `approval` event (`permdock.on('approval', …)`), never a package. A message or email carries only the token and links to a page where the approver signs in; the verdict goes through `approvalsHandler` with that session's subject. A link never approves on its own ([approvals adapter, Delivery](https://permdock.com/docs/adapters/approvals#delivery)).
91
+
92
+ ## Approvers
93
+
94
+ `by` takes roles, `user(id)`, `relation()`, `holder(permission)` and `anyOf(...)`. A list is all-of; use `anyOf(user(id), holder(permissions.x.approve))` for "this person or anyone who holds the permission". `holder()` needs `approvalsHandler(store, { permdockFor: (approver, request) => createPermDock(policy, approver, { customRoles }) })`, so custom roles count. Stages may carry their own `escalation`.
@@ -4,7 +4,7 @@ description: Reviews an existing PermDock setup or a pull request that changes i
4
4
  license: MIT
5
5
  metadata:
6
6
  author: ScaleDockHQ
7
- homepage: https://permdock.dev/docs/for-ai-agents
7
+ homepage: https://permdock.com/docs/for-ai-agents
8
8
  repository: https://github.com/ScaleDockHQ/permdock
9
9
  ---
10
10
 
@@ -42,7 +42,7 @@ Read the app's `permissions.ts`, `policy.ts`, factory file and every adapter gua
42
42
  ✓ Every item of every applicable Verify list has a pass or a finding.
43
43
  5. **Tests.** No `describePolicy` suite, or one with `exhaustive: false`, is a finding: a new permission can ship untested. A custom `ApprovalStore`, `DecisionSink`, `MembershipSource`, `RoleSource`, `SnapshotSource`, `LimitStore`, `RelationSource` or `DirectoryStore` without its `test<Interface>` runner from `permdock/testing` is a finding.
44
44
  ✓ Every policy and custom store has its runner, or a finding.
45
- 6. **ASI02 and ASI03.** Map the inventory onto [OWASP Agentic](https://permdock.dev/docs/security/owasp-agentic); for the threat list itself, defer to the `owasp-agentic` spec skill (`npx skills add ScaleDockHQ/scaledock-skills --skill owasp-agentic`).
45
+ 6. **ASI02 and ASI03.** Map the inventory onto [OWASP Agentic](https://permdock.com/docs/security/owasp-agentic); for the threat list itself, defer to the `owasp-agentic` spec skill (`npx skills add ScaleDockHQ/scaledock-skills --skill owasp-agentic`).
46
46
  - **ASI02** (tool misuse): unmapped tools, a collection permission on a row handler, a destructive tool without `approval`, capability lists that include denied tools.
47
47
  - **ASI03** (identity and privilege abuse): a model-supplied subject or actor, an actor used as approver, `distinct: false` on a sensitive action, a resume token not bound to permission, resource, subject and actor, API keys stored in plain text or created outside `decideCredential`, keys without expiry (PD029), and a `memberships` source applied to service-key subjects.
48
48
  ✓ Each agent adapter in the app has an ASI02 line and an ASI03 line.
@@ -64,4 +64,4 @@ Read the app's `permissions.ts`, `policy.ts`, factory file and every adapter gua
64
64
  ## Reference index
65
65
 
66
66
  - Topic Verify lists: the `permdock-agents`, `permdock-approvals`, `permdock-tenancy`, `permdock-data` and `permdock-credentials` skills.
67
- - Docs: [OWASP Agentic mapping](https://permdock.dev/docs/security/owasp-agentic), [threat model](https://permdock.dev/docs/security/threat-model), [`permdock doctor`](https://permdock.dev/docs/cli/doctor), [`permdock usage`](https://permdock.dev/docs/cli/usage), [testing](https://permdock.dev/docs/adapters/testing).
67
+ - Docs: [OWASP Agentic mapping](https://permdock.com/docs/security/owasp-agentic), [threat model](https://permdock.com/docs/security/threat-model), [`permdock doctor`](https://permdock.com/docs/cli/doctor), [`permdock usage`](https://permdock.com/docs/cli/usage), [testing](https://permdock.com/docs/adapters/testing).
@@ -4,13 +4,13 @@ description: Resolves PermDock subjects from access tokens, API keys and share l
4
4
  license: MIT
5
5
  metadata:
6
6
  author: ScaleDockHQ
7
- homepage: https://permdock.dev/docs/concepts/authentication
7
+ homepage: https://permdock.com/docs/concepts/authentication
8
8
  repository: https://github.com/ScaleDockHQ/permdock
9
9
  ---
10
10
 
11
11
  # PermDock credentials
12
12
 
13
- Authentication is upstream: core never verifies a token. A `subjectFrom*` resolver verifies the material and hands core a `Subject`, and anything it cannot verify becomes the anonymous subject, never a throw ([authentication](https://permdock.dev/docs/concepts/authentication)). Set up the policy and factory first with the `permdock-wire` skill (`npx skills add ScaleDockHQ/PermDock --skill permdock-wire`).
13
+ Authentication is upstream: core never verifies a token. A `subjectFrom*` resolver verifies the material and hands core a `Subject`, and anything it cannot verify becomes the anonymous subject, never a throw ([authentication](https://permdock.com/docs/concepts/authentication)). Set up the policy and factory first with the `permdock-wire` skill (`npx skills add ScaleDockHQ/PermDock --skill permdock-wire`).
14
14
 
15
15
  ## Inputs (find out, or ask before starting)
16
16
 
@@ -38,7 +38,7 @@ Authentication is upstream: core never verifies a token. A `subjectFrom*` resolv
38
38
  ✓ A revoked or expired key is anonymous, and a user key never exceeds its owner's current rights.
39
39
  4. **Share links, when the product has them.** Declare the link's roles on the resource, mint with `signCapability` behind a guard of its own, and resolve with `subjectFromCapability` and the tenant's `linkPolicy`. With Supabase RLS, exchange the link with `exchangeCapability` and generate with `--capabilities`. -> [references/tokens-keys-links.md](references/tokens-keys-links.md#share-links)
40
40
  ✓ An expired, revoked or replayed (`once`) link resolves to the anonymous subject.
41
- 5. **Test.** Add scenario tests for each credential kind: a valid one, a forged or expired one, and a key or link used past its permissions ([scenario testing](https://permdock.dev/docs/guides/scenario-testing)). Run `permdock doctor`.
41
+ 5. **Test.** Add scenario tests for each credential kind: a valid one, a forged or expired one, and a key or link used past its permissions ([scenario testing](https://permdock.com/docs/guides/scenario-testing)). Run `permdock doctor`.
42
42
  ✓ The tests pass and PD029 is clean.
43
43
 
44
44
  ## Verify before done
@@ -52,4 +52,4 @@ Authentication is upstream: core never verifies a token. A `subjectFrom*` resolv
52
52
  ## Reference index
53
53
 
54
54
  - [references/tokens-keys-links.md](references/tokens-keys-links.md): `subjectFromJwt` options, introspection, CI OIDC, `decideCredential`, key storage and resolution, tenant settings, `signCapability`, `subjectFromCapability`, `exchangeCapability`.
55
- - Docs: [authentication](https://permdock.dev/docs/concepts/authentication), [subject](https://permdock.dev/docs/concepts/subject), [JWT adapter](https://permdock.dev/docs/adapters/jwt), [API keys](https://permdock.dev/docs/concepts/credentials), [link capabilities](https://permdock.dev/docs/concepts/capabilities), [JOSE](https://permdock.dev/docs/standards/jose).
55
+ - Docs: [authentication](https://permdock.com/docs/concepts/authentication), [subject](https://permdock.com/docs/concepts/subject), [JWT adapter](https://permdock.com/docs/adapters/jwt), [API keys](https://permdock.com/docs/concepts/credentials), [link capabilities](https://permdock.com/docs/concepts/capabilities), [JOSE](https://permdock.com/docs/standards/jose).
@@ -1,6 +1,6 @@
1
1
  # Tokens, API keys and share links
2
2
 
3
- Owning pages: [JWT adapter](https://permdock.dev/docs/adapters/jwt), [authentication](https://permdock.dev/docs/concepts/authentication), [API keys](https://permdock.dev/docs/concepts/credentials), [link capabilities](https://permdock.dev/docs/concepts/capabilities).
3
+ Owning pages: [JWT adapter](https://permdock.com/docs/adapters/jwt), [authentication](https://permdock.com/docs/concepts/authentication), [API keys](https://permdock.com/docs/concepts/credentials), [link capabilities](https://permdock.com/docs/concepts/capabilities).
4
4
 
5
5
  ## Access tokens — `permdock/jwt`
6
6
 
@@ -18,6 +18,7 @@ const subject = await subjectFromJwt(token, {
18
18
  - `jose` is an optional peer. A failure is the anonymous subject, never a throw; the cause is reported through `on('auth')`. A claimed `act` chain that does not nest is anonymous with cause `invalid-chain`.
19
19
  - When the app already called RFC 7662 or RFC 9767 introspection, pass the response JSON to `subjectFromIntrospection`. `active` other than `true` is anonymous, and the HTTP call stays the app's.
20
20
  - In CI, `subjectFromCiOidc(jwt, { provider: 'github', audience })` returns a `workload` principal, never a user.
21
+ - A Supabase OAuth server token is an `oauth-client` actor. `subjectFromSupabase` drops the OpenID Connect identity scopes (`openid`, `profile`, `email`, `address`, `phone`, `offline_access`) from its delegation, so a token with only those reaches nothing. Let a client act for users with a policy `delegations` entry whose `to` is `{ kind: 'oauth-client', client: '<name>' }`, and map the verified id to that name with `subjectFromSupabase(claims, { clients: { <name>: env.CLIENT_ID } })` (or a function for dynamically registered clients); a literal `{ kind, id }` also works but ties the policy to one environment, never by reading identity scopes as permissions ([Supabase provider](https://permdock.com/docs/adapters/supabase#oauth-server-tokens)).
21
22
 
22
23
  ## API keys and service accounts
23
24
 
@@ -49,7 +50,7 @@ if (decision.outcome === "granted") {
49
50
  ```
50
51
 
51
52
  - Guard the endpoint that creates keys with its own permission (`apiKey.create`).
52
- - Every key lists 1 to 64 permissions. A `user` key is its owner's live rights narrowed to the key; a `service` key is a `kind: 'service'` principal whose tenant, roles and permissions must be within the creator's `assignableRoles` / `assignablePermissions` (otherwise `exceeds-creator`). A key cannot mint keys.
53
+ - Every key lists at least one permission, with no upper bound. A `user` key is its owner's live rights narrowed to the key, and with `tenant` to the owner's memberships inside that tenant and no global role (never put a tenant id in `ids`, which holds resource ids); a `service` key is a `kind: 'service'` principal whose tenant, roles and permissions must be within the creator's `assignableRoles` / `assignablePermissions` (otherwise `exceeds-creator`). A key cannot mint keys.
53
54
  - Tenant rules come from a `SettingsSource` (`memorySettings({ o_1: { credentials: { maxTtl, kinds, approval, allowNoExpiry } } })`). A key without `expiresAt` needs `allowNoExpiry`. `approval: true` makes creation `approval-required`; after approval, call `decideCredential` again with `approved: token`.
54
55
  - Store only `hashApiKey(key)`. The key is `pdk_<id>_<secret><checksum>`; `parseApiKey` rejects a bad checksum before any lookup.
55
56
 
@@ -72,6 +73,10 @@ const subject = await resolveKey(bearer, { tenant });
72
73
 
73
74
  Never pass a `memberships` source to `createPermDock` for a service-key subject: its one membership comes from the credential. `memoryCredentials()` is an in-process store for tests.
74
75
 
76
+ When the backend then queries Postgres for the key, put the key's permission keys (and, for a service key, its tenant and roles) in an `api_key` claim and set `rls.apiKeys` in `permdock.config.ts`: the generated helpers cap every allow at the key's permissions and hold a key that names a tenant to that tenant, so RLS agrees with `can()`. The key itself never goes to the database.
77
+
78
+ When the keys live in better-supabase's `api_keys` table, use `apiKeyVerifier({ keys, manifest, allPermissions })` from `permdock/better-supabase` instead, and create the keys with `createApiKeys({ transport, prefix: "pdk" })`: PermDock parses only its own prefix. A third-party token that better-supabase's `CredentialProvider` hands out goes through `credentialGuard(provider, { permdock, use, revoke? })` from the same entry, so PermDock decides each use.
79
+
75
80
  ## Share links
76
81
 
77
82
  ```ts