permdock 0.3.0 → 0.4.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 (323) hide show
  1. package/dist/a2a/index.d.ts +7 -5
  2. package/dist/a2a/index.js +14 -21
  3. package/dist/ai-sdk/index.d.ts +18 -6
  4. package/dist/ai-sdk/index.js +8 -5
  5. package/dist/app-data-CV8pqqMi.js +59 -0
  6. package/dist/approvals/index.d.ts +2 -2
  7. package/dist/approvals/index.js +3 -3
  8. package/dist/{approvals-DbYAuNkG.js → approvals-DZL76lKW.js} +35 -19
  9. package/dist/{approvers-DT4AVyIg.js → approvers-CqPOLD-o.js} +1 -1
  10. package/dist/{arazzo-BAgw9ap6.js → arazzo-C4BcskbX.js} +6 -5
  11. package/dist/{arazzo-CKwwqFWz.js → arazzo-CD8d0WLb.js} +2 -2
  12. package/dist/authzen/index.d.ts +3 -3
  13. package/dist/authzen/index.js +161 -23
  14. package/dist/better-auth/index.d.ts +2 -2
  15. package/dist/better-auth/index.js +6 -19
  16. package/dist/better-supabase/index.d.ts +112 -87
  17. package/dist/better-supabase/index.js +257 -156
  18. package/dist/{bind-C_ob3LKa.d.ts → bind-BzqG8SMb.d.ts} +16 -5
  19. package/dist/{bind-CuzGytRf.js → bind-kk-uyCwH.js} +14 -6
  20. package/dist/build-instance-DIIV9DbC.js +51 -0
  21. package/dist/{canonical-json-DemiK4Vp.js → canonical-json-CFKyFOke.js} +1 -3
  22. package/dist/{capability-2kYTMWDv.d.ts → capability-CksyCWDH.d.ts} +2 -2
  23. package/dist/{capability-4qPdO9gk.js → capability-txATtKV4.js} +3 -2
  24. package/dist/catalog/index.d.ts +1 -1
  25. package/dist/catalog/index.js +1 -1
  26. package/dist/catalog-6yWAX6Ps.js +2 -0
  27. package/dist/{catalog-dFZdWCGN.js → catalog-WHG4kBq7.js} +2 -2
  28. package/dist/{catalog-doc-DdGm82XT.js → catalog-doc-DWtg0gGR.js} +17 -10
  29. package/dist/{catalog-DWF5cYqB.js → catalog-tZUyOfOv.js} +4 -4
  30. package/dist/claude-agent/index.d.ts +4 -4
  31. package/dist/claude-agent/index.js +4 -5
  32. package/dist/clerk/index.d.ts +3 -3
  33. package/dist/clerk/index.js +8 -33
  34. package/dist/cli/bin.js +1 -1
  35. package/dist/cli/index.d.ts +3 -3
  36. package/dist/cli/index.js +3 -3
  37. package/dist/cloud/index.d.ts +4 -4
  38. package/dist/cloud/index.js +9 -15
  39. package/dist/{cloud-CB_ELYuX.js → cloud-C7bSDgX4.js} +2 -2
  40. package/dist/{cloud-DWLXO2af.js → cloud-PeBN3IEn.js} +5 -5
  41. package/dist/{collect-DSTE3ml9.js → collect-2SrB7lfk.js} +6 -8
  42. package/dist/collect-Bw2Jdq1q.js +2 -0
  43. package/dist/{collect-DClJsheJ.js → collect-CQx4hX4N.js} +3 -3
  44. package/dist/{commands-DSxCqG9A.js → commands-Cpip4ULx.js} +13 -13
  45. package/dist/{compact-y6vfu2_f.js → compact-CAf557ZB.js} +11 -1
  46. package/dist/compile/index.d.ts +1 -1
  47. package/dist/compile/index.js +1 -1
  48. package/dist/{compile-Ba4blROR.js → compile-CcEu2ZQ1.js} +6 -5
  49. package/dist/{compile-BkRyBDBw.d.ts → compile-CtTP7eur.d.ts} +2 -2
  50. package/dist/{config-BJiM-xAm.js → config-BIjREpyE.js} +4 -4
  51. package/dist/{config-Dnszbv-6.js → config-DLt6BvV7.js} +2 -2
  52. package/dist/{config-report-DMvWKUxL.js → config-report--Xb9APJS.js} +5 -6
  53. package/dist/{connection-CU8MQxRi.js → connection-DUsczpB5.js} +3 -2
  54. package/dist/constants-DcJABbLW.js +20 -0
  55. package/dist/{context-Bcy85rGi.js → context-DieZVJXu.js} +16 -5
  56. package/dist/convex/index.d.ts +4 -4
  57. package/dist/convex/index.js +14 -16
  58. package/dist/create-BBO24vj6.js +324 -0
  59. package/dist/{credential-8P81ff4u.js → credential-kue0qpbm.js} +4 -4
  60. package/dist/deciding-columns-Sq12mEA6.js +123 -0
  61. package/dist/delegation-input-FTxMK3ji.js +19 -0
  62. package/dist/denied-text-DfRk15uw.d.ts +19 -0
  63. package/dist/{describe-DMYiCjJV.d.ts → describe-C3ldA9os.d.ts} +11 -2
  64. package/dist/{describe-B_gVZEVi.js → describe-Cgkp7eP0.js} +5 -4
  65. package/dist/{diff-DBIhz_f2.js → diff-Cnghh_Ip.js} +2 -2
  66. package/dist/{diff-2VaeChzX.js → diff-rpqoe7Ag.js} +9 -9
  67. package/dist/{doctor-BwCAMLx_.js → doctor-CuVJvhV_.js} +2 -2
  68. package/dist/doctor-owlv6ddh.js +2166 -0
  69. package/dist/drizzle/index.d.ts +2 -2
  70. package/dist/drizzle/index.js +6 -14
  71. package/dist/elysia/index.d.ts +4 -4
  72. package/dist/elysia/index.js +7 -7
  73. package/dist/{errors-DPdqI50v.d.ts → errors-OD_4c__H.d.ts} +2 -2
  74. package/dist/{errors-Cz5zn0mW.js → errors-drnfxYtm.js} +3 -3
  75. package/dist/{evaluations-tz6D9A2G.js → evaluations-C9YJsv3H.js} +45 -7
  76. package/dist/eve/index.d.ts +5 -5
  77. package/dist/eve/index.js +5 -5
  78. package/dist/express/index.d.ts +4 -4
  79. package/dist/express/index.js +8 -7
  80. package/dist/fastify/index.d.ts +15 -5
  81. package/dist/fastify/index.js +9 -29
  82. package/dist/fields-fwfXN01n.js +1016 -0
  83. package/dist/{files-DWUN9PzI.js → files-D_JIzUrP.js} +12 -3
  84. package/dist/{fixtures-ht28Cplr.js → fixtures-h2eG2OZV.js} +5 -6
  85. package/dist/{from-snapshot-CTLijvdm.js → from-snapshot-7REQZe0H.js} +32 -22
  86. package/dist/{generate-CH7ThJ14.js → generate-CNU1pIOo.js} +1 -3
  87. package/dist/grantee-CXY-0C87.js +254 -0
  88. package/dist/grantee-conditions-MQs5NIuX.js +270 -0
  89. package/dist/grantee-match-fxYp9Nmt.js +141 -0
  90. package/dist/{helpers-H_KARDVC.js → helpers-C9YmyBIa.js} +7 -6
  91. package/dist/hono/index.d.ts +4 -4
  92. package/dist/hono/index.js +8 -8
  93. package/dist/hosted-CBHgkzDl.js +655 -0
  94. package/dist/{http-SO7qGttf.js → http-BBoKefeS.js} +35 -2
  95. package/dist/{http-BIhmLfCc.js → http-BEbdMZ05.js} +2 -24
  96. package/dist/{rls-import-BTFVk3jH.js → import-BFIlhetD.js} +86 -80
  97. package/dist/{openapi-import-cmwetbzw.js → import-UHk1N7vH.js} +6 -7
  98. package/dist/{index-C8z4RjQV.d.ts → index-BwMe94Xq.d.ts} +1 -1
  99. package/dist/{index-0nNqHspG.d.ts → index-DgM7w96K.d.ts} +2 -2
  100. package/dist/{index-C7Tw7MaW.d.ts → index-Dz7didpC.d.ts} +3 -3
  101. package/dist/{index-BNc7Wer_.d.ts → index-UdVQgq48.d.ts} +105 -38
  102. package/dist/index.d.ts +15 -13
  103. package/dist/index.js +22 -22
  104. package/dist/{instance-options-jARdwfPN.d.ts → instance-options-plkrsAog.d.ts} +1 -1
  105. package/dist/{json-schema-BsAflUGW.js → json-schema-DBkdUuCO.js} +1 -3
  106. package/dist/jwt/index.d.ts +4 -4
  107. package/dist/jwt/index.js +13 -13
  108. package/dist/{kernel-_RRHmnMY.js → kernel-CB3LrIJM.js} +81 -32
  109. package/dist/kysely/index.d.ts +2 -2
  110. package/dist/kysely/index.js +6 -14
  111. package/dist/{live-options-H2eG8dfJ.js → live-options-BaAFCIiu.js} +16 -3
  112. package/dist/load-B_shHrmd.js +2 -0
  113. package/dist/{load-DhWEB9P1.js → load-C3_oTHyO.js} +11 -3
  114. package/dist/{manifest-iaoBXHKc.js → manifest-BngWKryL.js} +5 -18
  115. package/dist/{map-claims-Z4QZOiFF.js → map-claims-AVlBaJoa.js} +7 -16
  116. package/dist/{map-error-pgUWNNtG.js → map-error-BE27PYkE.js} +5 -5
  117. package/dist/{markers-B0hYLvMD.js → markers-CiwAOZtO.js} +6 -2
  118. package/dist/{may-use-DndQ5tQ-.js → may-use-BOn_dR_w.js} +4 -3
  119. package/dist/mcp/index.d.ts +26 -9
  120. package/dist/mcp/index.js +456 -446
  121. package/dist/{rls-migrate-CN4TlJTO.js → migrate-BwlB5-Wk.js} +75 -15
  122. package/dist/nest/index.d.ts +4 -4
  123. package/dist/nest/index.js +11 -12
  124. package/dist/next/index.d.ts +31 -8
  125. package/dist/next/index.js +29 -33
  126. package/dist/next/plugin.d.ts +1 -1
  127. package/dist/next/plugin.js +1 -1
  128. package/dist/node/index.d.ts +4 -4
  129. package/dist/node/index.js +4 -4
  130. package/dist/ocsf-uYFXGVw2.js +115 -0
  131. package/dist/openai/index.d.ts +5 -5
  132. package/dist/openai/index.js +4 -4
  133. package/dist/openapi/index.d.ts +3 -3
  134. package/dist/openapi/index.js +1 -1
  135. package/dist/{openapi-CqqEbHsL.js → openapi-BJdBmYDG.js} +19 -23
  136. package/dist/{openapi-BqRBvAng.js → openapi-DBzHQbov.js} +2 -5
  137. package/dist/{openapi-l0xYHkcv.js → openapi-DcQ1Kg40.js} +3 -3
  138. package/dist/orpc/index.d.ts +5 -5
  139. package/dist/orpc/index.js +9 -11
  140. package/dist/otel/index.d.ts +2 -2
  141. package/dist/otel/index.js +26 -23
  142. package/dist/output-files-CgIsvdSa.js +140 -0
  143. package/dist/{rls-ownership-RuFqaqGz.js → ownership-BgnbOJFT.js} +387 -379
  144. package/dist/{package-root-zGkxO3oN.js → package-root-DtNnpmUd.js} +3 -2
  145. package/dist/{parse-BuyjxhZV.js → parse-CVFQHk6c.js} +3 -3
  146. package/dist/{parse-local-manifest-BrMozJCo.js → parse-local-manifest-C-q02Pal.js} +2 -4
  147. package/dist/{parse-local-manifest-JLnaBH0S.d.ts → parse-local-manifest-DvYUR0QL.d.ts} +1 -1
  148. package/dist/pdp/index.d.ts +2 -2
  149. package/dist/pdp/index.js +8 -9
  150. package/dist/{permdock-CbgvLnuo.js → permdock-L26udHSk.js} +1387 -1220
  151. package/dist/{rls-fields-74oZPXWL.js → permission-keys-B26jeyUv.js} +1289 -2066
  152. package/dist/permission-registry-BsblpB-z.js +385 -0
  153. package/dist/{permissions-DttnqqxC.d.ts → permission-types-Dg39z9Kv.d.ts} +59 -31
  154. package/dist/{permissions-RJrovw98.js → permissions-CCJ6lmxB.js} +3 -3
  155. package/dist/{permissions-CDgvKG5L.d.ts → permissions-COH-KRgT.d.ts} +2 -2
  156. package/dist/{policy-IB6yxpC3.d.ts → policy-types-sp9P1iIV.d.ts} +661 -582
  157. package/dist/{policy-D2W7uv19.d.ts → policy-ur0BBK_e.d.ts} +2 -2
  158. package/dist/{powersync-DliZK_-y.js → powersync-BFSbSElQ.js} +2 -2
  159. package/dist/powersync-DCDgZgfZ.js +2 -0
  160. package/dist/{powersync-BylawD_U.js → powersync-cZe4kzhL.js} +26 -27
  161. package/dist/prisma/index.d.ts +1 -1
  162. package/dist/prisma/index.js +6 -12
  163. package/dist/{problem-B43ztKIm.js → problem-CnWraVhC.js} +8 -7
  164. package/dist/{problem-details-_AMOYz-w.js → problem-details-DECUnXAn.js} +2 -2
  165. package/dist/{problem-details-DX075l9V.d.ts → problem-details-rIIo8B2C.d.ts} +1 -1
  166. package/dist/{protected-BdnIEFkY.d.ts → protected-B3_P7xuw.d.ts} +9 -6
  167. package/dist/{protected-utU-SLuy.js → protected-BN7BUdY1.js} +20 -8
  168. package/dist/{provider-CSQd7m92.js → provider-Bi-0HNL3.js} +23 -10
  169. package/dist/{provider-DZY281jO.d.ts → provider-kwHC9CZD.d.ts} +1 -1
  170. package/dist/{provider-store-Cfbvo4DE.js → provider-store-Ctt-81Ni.js} +6 -3
  171. package/dist/react/index.d.ts +7 -7
  172. package/dist/react/index.js +5 -5
  173. package/dist/react/provider-client.d.ts +1 -1
  174. package/dist/react/provider-client.js +1 -1
  175. package/dist/react-native/index.d.ts +20 -11
  176. package/dist/react-native/index.js +33 -17
  177. package/dist/{refs-KYb4ntaz.js → refs-f3imMjNW.js} +1 -1
  178. package/dist/relation-walk-BXnlLtg2.js +186 -0
  179. package/dist/relations-CvmSpG67.js +163 -0
  180. package/dist/{replay-CYyiLiwO.d.ts → replay-COpmZUfx.d.ts} +1 -1
  181. package/dist/request-context-BVM7aWNs.js +71 -0
  182. package/dist/request-context-C2_1lchh.d.ts +5 -0
  183. package/dist/resource-relations-D1Un3pcz.js +243 -0
  184. package/dist/retire-BFcxL6un.js +240 -0
  185. package/dist/{rls-B4ur8nKQ.js → rls-55DQTuf5.js} +14 -2
  186. package/dist/{rls-DQtdgTHB.js → rls-BEktUaqg.js} +884 -484
  187. package/dist/{policy-xyWg7QdR.js → role-builder-B4GbKM-i.js} +235 -541
  188. package/dist/{rpc-DL9Sqvb1.js → rpc-nYC3cR_u.js} +15 -5
  189. package/dist/{run-DKDbM4Du.js → run-DMcNW_8T.js} +3 -3
  190. package/dist/{runtime-CB8gQFvS.js → runtime-D_tMXnsq.js} +1 -1
  191. package/dist/{saas-DhpJjnBA.js → saas-DtaA4JuW.js} +9 -8
  192. package/dist/{openapi-schema--ARjyfQr.js → schema-Bol6gqXA.js} +3 -5
  193. package/dist/{schema-D3MnDMxa.js → schema-DjQBcAP9.js} +4 -2
  194. package/dist/scim/index.d.ts +1 -1
  195. package/dist/scim/index.js +1 -1
  196. package/dist/{scim-BFGBBAqR.js → scim-vFR1O5oG.js} +6 -12
  197. package/dist/{scopes-CVdPrWN-.js → scopes-tvpa34ep.js} +10 -2
  198. package/dist/server/index.d.ts +18 -8
  199. package/dist/server/index.js +8 -8
  200. package/dist/{server-DlZ28Oz5.js → server-ZYEHtNHS.js} +4 -4
  201. package/dist/{create-B1d519XK.d.ts → server-types-DdqBwZN_.d.ts} +69 -33
  202. package/dist/shared-1uhI-e-b.js +294 -0
  203. package/dist/{shared-DRu8VFVM.js → shared-JhMeOsDF.js} +1 -1
  204. package/dist/{sink-Bd9PSyfq.js → sink-BTtmfPnE.js} +1 -1
  205. package/dist/{sink-B1fZzIMf.d.ts → sink-CPN4zLfs.d.ts} +1 -1
  206. package/dist/{skills-Biq5uup3.js → skills-BZdRQkxs.js} +4 -3
  207. package/dist/{skills-Bx-U0irG.js → skills-Dle4ZoLF.js} +2 -2
  208. package/dist/{snapshot-Enxd0n-s.js → snapshot-Dc9CHPME.js} +116 -13
  209. package/dist/{snapshot-cache-D6jLelln.js → snapshot-cache-Cod40D-X.js} +1 -1
  210. package/dist/{snapshot-cache-B-LxUahj.d.ts → snapshot-cache-J5T7t_vD.d.ts} +1 -1
  211. package/dist/solid/index.d.ts +22 -22
  212. package/dist/solid/index.js +40 -10
  213. package/dist/{sources-4p0-4xQm.js → sources-B1-b-R0t.js} +25 -26
  214. package/dist/{sources-BdOYLw9j.d.ts → sources-Dljy06zL.d.ts} +6 -2
  215. package/dist/{sql-xdg5f4Fi.js → sql-t8teWOfo.js} +19 -3
  216. package/dist/{src-BDwEZWrZ.js → src-Bb7no-hS.js} +194 -123
  217. package/dist/ssf/index.d.ts +3 -3
  218. package/dist/ssf/index.js +58 -61
  219. package/dist/store-9KO4BlkB.d.ts +147 -0
  220. package/dist/{store-DMAWwAJV.js → store-ILkLUj_o.js} +4 -4
  221. package/dist/{store-options-ByhZq1jV.js → store-options-CbUHDoSe.js} +16 -7
  222. package/dist/{stores-BT2pSCub.js → stores-BHXdSbw9.js} +7 -3
  223. package/dist/stores-Cxz_80g-.d.ts +31 -0
  224. package/dist/{stream-DDpvynSB.js → stream-BMui98KK.js} +2 -1
  225. package/dist/{stream-D1RXubw2.d.ts → stream-Dwsg6WwE.d.ts} +2 -2
  226. package/dist/{subject-settings-BwBmCdTR.js → subject-settings-CkEwrw3W.js} +23 -5
  227. package/dist/supabase/index.d.ts +4 -4
  228. package/dist/supabase/index.js +3 -3
  229. package/dist/supabase/middleware.d.ts +11 -5
  230. package/dist/supabase/middleware.js +10 -7
  231. package/dist/{supabase-C0qESOa-.js → supabase-C1TWlnYt.js} +36 -52
  232. package/dist/{supabase-Boqb9a_Y.js → supabase-Dbqr141s.js} +2 -2
  233. package/dist/supabase-hook-BULg7Ut_.js +2 -0
  234. package/dist/{supabase-hook-CSLQ4zJ3.js → supabase-hook-Cva3ikXz.js} +731 -782
  235. package/dist/{supautils-Cn4R4cJ4.js → supautils-B6HYL9eL.js} +2 -2
  236. package/dist/svelte/Protected.svelte +9 -2
  237. package/dist/svelte/index.d.ts +6 -6
  238. package/dist/svelte/index.js +25 -11
  239. package/dist/svelte/runtime.d.ts +10 -3
  240. package/dist/svelte/runtime.js +4 -3
  241. package/dist/svelte/source.d.ts +6 -6
  242. package/dist/svelte/source.js +4 -4
  243. package/dist/{validity-uOp8UpYn.js → tenancy-DshjqY0n.js} +3 -39
  244. package/dist/terminal/index.d.ts +5 -5
  245. package/dist/terminal/index.js +18 -34
  246. package/dist/testing/index.d.ts +89 -77
  247. package/dist/testing/index.js +1276 -1262
  248. package/dist/testing/saas/index.d.ts +4 -4
  249. package/dist/testing/saas/index.js +2 -2
  250. package/dist/testing/saas/permissions.d.ts +1 -1
  251. package/dist/testing/saas/permissions.js +1 -1
  252. package/dist/thenable-QSmvt-vZ.js +65 -0
  253. package/dist/{token-CIWxJOCh.js → token-Bx9qy30p.js} +1 -1
  254. package/dist/tool-refusal-CQ7OEia9.js +41 -0
  255. package/dist/trpc/index.d.ts +5 -5
  256. package/dist/trpc/index.js +7 -8
  257. package/dist/{types-DbjRN55U.d.ts → types-7rJVLWe5.d.ts} +82 -4
  258. package/dist/{types-aqOHTHcp.d.ts → types-Br9IXUBG.d.ts} +1 -1
  259. package/dist/types-ByUo56un.d.ts +88 -0
  260. package/dist/{types-Cq_H8N_X.d.ts → types-C0dee0Qf.d.ts} +2 -2
  261. package/dist/{types-DxiCGmmd.d.ts → types-CIlTojhq.d.ts} +2 -2
  262. package/dist/{types-QCuYJh4q.d.ts → types-CUcFZfpU.d.ts} +1 -1
  263. package/dist/{types-C97IskBw.d.ts → types-CqrjB9o6.d.ts} +1 -1
  264. package/dist/{types-BnIEz1sU.d.ts → types-DHrmBJLH.d.ts} +24 -6
  265. package/dist/{types-Dnemwd77.d.ts → types-DpWfQdSh.d.ts} +5 -1
  266. package/dist/{types-Bvc4oWT6.d.ts → types-DvupZE0w.d.ts} +1 -1
  267. package/dist/unplugin/index.d.ts +1 -1
  268. package/dist/unplugin/index.js +1 -1
  269. package/dist/{usage-GTixvDDU.js → usage-4G6t643F.js} +2 -2
  270. package/dist/{usage-ItS7nLcl.js → usage-CG9nOYZw.js} +7 -7
  271. package/dist/usage-iFLJ0-rr.js +2 -0
  272. package/dist/{validation-error-Ba264OaJ.d.ts → validation-error-BSSw0l_8.d.ts} +1 -1
  273. package/dist/{validation-error-CnjZ4t92.js → validation-error-ZfUHbKvf.js} +1 -1
  274. package/dist/validity-dVrUEPJt.js +62 -0
  275. package/dist/{verifier-BxBo6I44.js → verifier-DMr_Zmb_.js} +51 -15
  276. package/dist/{rls-verify-CVQTHTh5.js → verify-BztUB3GX.js} +668 -239
  277. package/dist/{version-BvacVTZR.js → version-BEogC-rB.js} +1 -1
  278. package/dist/{views-Soe7bGSC.js → views-CJsrBS1f.js} +23 -1
  279. package/dist/{vocabulary-DA8a8zif.d.ts → vocabulary-hhEFLFoL.d.ts} +15 -6
  280. package/dist/vue/index.d.ts +24 -19
  281. package/dist/vue/index.js +24 -8
  282. package/dist/watch-C8TpsAl4.js +2 -0
  283. package/dist/{watch-DVBJ9cBq.js → watch-zeucB7eF.js} +6 -6
  284. package/dist/webmcp/index.d.ts +2 -2
  285. package/dist/webmcp/index.js +13 -37
  286. package/dist/wrap-Cr93qqdP.d.ts +14 -0
  287. package/dist/wrap-DWsU_5Bd.js +26 -0
  288. package/package.json +8 -8
  289. package/schemas/catalog-v1.json +6 -0
  290. package/skills/permdock-credentials/SKILL.md +1 -1
  291. package/skills/permdock-credentials/references/tokens-keys-links.md +7 -2
  292. package/skills/permdock-data/references/queries-and-rls.md +4 -0
  293. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +1 -0
  294. package/skills/permdock-wire/SKILL.md +2 -2
  295. package/skills/permdock-wire/references/adapters.md +9 -1
  296. package/skills/permdock-wire/references/policy-options.md +10 -1
  297. package/dist/catalog-CRW5Mx_B.js +0 -2
  298. package/dist/collect-DSWOk19R.js +0 -2
  299. package/dist/create-CMwIl-w2.js +0 -253
  300. package/dist/delegation-D8pUEuce.js +0 -103
  301. package/dist/doctor-collect-CHk6XWOA.js +0 -665
  302. package/dist/doctor-igIiM_Hl.js +0 -1194
  303. package/dist/evaluation-items-CfCCejQd.js +0 -40
  304. package/dist/fields-BMl1RxoX.js +0 -26
  305. package/dist/grantee-Cv5Sogfv.js +0 -602
  306. package/dist/hosted-DJQw46hn.js +0 -266
  307. package/dist/instance-options-Dhhcnm3y.js +0 -22
  308. package/dist/load-DwJUafYN.js +0 -2
  309. package/dist/map-AcxK9o_D.js +0 -147
  310. package/dist/permissions-DVoF6dMt.js +0 -662
  311. package/dist/powersync-e_AZrKbg.js +0 -2
  312. package/dist/protected-xAr24FEC.d.ts +0 -40
  313. package/dist/relations-cjOL01hZ.js +0 -505
  314. package/dist/rls-graph-CHwx0V8q.js +0 -435
  315. package/dist/rls-shared-Cewd_-zI.js +0 -495
  316. package/dist/store-jOBYpiXC.d.ts +0 -36
  317. package/dist/stores-C0IMQrGI.d.ts +0 -52
  318. package/dist/supabase-config-BpPXt3x1.js +0 -472
  319. package/dist/supabase-hook-6sYLXg_u.js +0 -2
  320. package/dist/thenable-okc2xDsj.js +0 -10
  321. package/dist/types-CKNSyIf_.d.ts +0 -52
  322. package/dist/usage-DorAJiU_.js +0 -2
  323. package/dist/watch-BwxLTYMZ.js +0 -2
@@ -1,4 +1,4 @@
1
- import { t as packageRoot } from "./package-root-zGkxO3oN.js";
1
+ import { t as packageRoot } from "./package-root-DtNnpmUd.js";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  //#region src/cli/version.ts
@@ -1,3 +1,4 @@
1
+ import { t as describe } from "./describe-Cgkp7eP0.js";
1
2
  //#region src/client/views.ts
2
3
  function permissionSet(store, permissions, data) {
3
4
  const granted = [];
@@ -64,6 +65,12 @@ function protectedView(local, root, permission, data, scoped) {
64
65
  slot: "pending"
65
66
  };
66
67
  const decision = state.decision;
68
+ if (decision.outcome === "approval-required") return {
69
+ allowed: false,
70
+ status: state.status,
71
+ decision,
72
+ slot: "approval"
73
+ };
67
74
  if (!state.allowed || decision.outcome !== "granted") return {
68
75
  ...state,
69
76
  slot: "fallback"
@@ -91,5 +98,20 @@ function approvalHandle(store, decision) {
91
98
  request: (note) => store.requestApproval(decision, note)
92
99
  };
93
100
  }
101
+ function slotContent(slot, own, defaults) {
102
+ switch (slot) {
103
+ case "pending": return own.pending ?? defaults?.pending;
104
+ case "fallback": return own.fallback ?? defaults?.fallback;
105
+ case "approval": return own.approval ?? own.fallback ?? defaults?.approval ?? defaults?.fallback;
106
+ default: return slot;
107
+ }
108
+ }
109
+ /** `describe` with the provider's `messages`; a call's own `messages` win. */
110
+ function describeWith(messages) {
111
+ return (decision, options) => describe(decision, messages === void 0 || options?.messages !== void 0 ? options : {
112
+ ...options,
113
+ messages
114
+ });
115
+ }
94
116
  //#endregion
95
- export { protectedView as a, subjectView as c, permissionSet as i, tenantView as l, filterResult as n, rolesView as o, livePermDock as r, scopedTenant as s, approvalHandle as t };
117
+ export { permissionSet as a, scopedTenant as c, tenantView as d, livePermDock as i, slotContent as l, describeWith as n, protectedView as o, filterResult as r, rolesView as s, approvalHandle as t, subjectView as u };
@@ -1,7 +1,16 @@
1
- import { n as ActionMeta } from "./permissions-DttnqqxC.js";
1
+ import { A as WithX, O as AppDataSchema, n as ActionMeta } from "./permission-types-Dg39z9Kv.js";
2
2
  //#region src/core/vocabulary.d.ts
3
3
  declare const ROLE_KIND: "role";
4
4
  declare const PLAN_KIND: "plan";
5
+ /** `defineRoles` and `definePlans` options. */
6
+ type VocabularyOptions<X = never> = {
7
+ /**
8
+ * A Standard Schema for every leaf's `meta.x`, validated synchronously at
9
+ * definition time. On a role tree it also checks the `meta.x` of custom
10
+ * roles a `RoleSource` returns; an invalid one is dropped, not the role.
11
+ */
12
+ readonly x?: AppDataSchema<X>;
13
+ };
5
14
  /**
6
15
  * A role's metadata. `audience` names the surface its holders use (`'staff'`,
7
16
  * `'portal'`, `'platform'`); `permdock.audiences()` lists the distinct
@@ -43,14 +52,14 @@ type Vocabulary = {
43
52
  readonly roles?: RoleTree;
44
53
  readonly plans?: PlanTree;
45
54
  };
46
- type InferRoleTree<Input> = { readonly [K in keyof Input & string]: Role<K>; };
47
- type InferPlanTree<Input> = { readonly [K in keyof Input & string]: Plan<K>; };
55
+ type InferRoleTree<Input, X = never> = { readonly [K in keyof Input & string]: WithX<Role<K>, X>; };
56
+ type InferPlanTree<Input, X = never> = { readonly [K in keyof Input & string]: WithX<Plan<K>, X>; };
48
57
  declare function isRole(value: unknown): value is Role;
49
58
  declare function isPlan(value: unknown): value is Plan;
50
- declare function defineRoles<const Input extends Record<string, RoleInit>>(input: Input): InferRoleTree<Input>;
51
- declare function definePlans<const Input extends Record<string, PlanInit>>(input: Input): InferPlanTree<Input>;
59
+ declare function defineRoles<const Input extends Record<string, RoleInit>, X = never>(input: Input, options?: VocabularyOptions<X>): InferRoleTree<Input, X>;
60
+ declare function definePlans<const Input extends Record<string, PlanInit>, X = never>(input: Input, options?: VocabularyOptions<X>): InferPlanTree<Input, X>;
52
61
  declare function listRoles(tree: RoleTree | undefined): readonly Role[];
53
62
  declare function listPlans(tree: PlanTree | undefined): readonly Plan[];
54
63
  declare function findRole(tree: RoleTree | undefined, key: string): Role | undefined;
55
64
  //#endregion
56
- export { RoleTree as a, defineRoles as c, isRole as d, listPlans as f, RoleMeta as i, findRole as l, PlanTree as n, Vocabulary as o, listRoles as p, Role as r, definePlans as s, Plan as t, isPlan as u };
65
+ export { RoleTree as a, definePlans as c, isPlan as d, isRole as f, RoleMeta as i, defineRoles as l, listRoles as m, PlanTree as n, Vocabulary as o, listPlans as p, Role as r, VocabularyOptions as s, Plan as t, findRole as u };
@@ -1,36 +1,39 @@
1
- import { Ft as TokenVerifier, Mr as Membership, Tt as Snapshot, Yn as Decision } from "../policy-IB6yxpC3.js";
2
- import { f as Permission } from "../permissions-DttnqqxC.js";
3
- import { r as Role } from "../vocabulary-DA8a8zif.js";
4
- import { n as requiredPlans } from "../problem-details-DX075l9V.js";
5
- import { i as describe } from "../describe-DMYiCjJV.js";
1
+ import { Dr as Membership, an as Snapshot, ir as Decision, rr as ApprovalRequiredDecision, ut as TokenVerifier } from "../policy-types-sp9P1iIV.js";
2
+ import { d as Permission } from "../permission-types-Dg39z9Kv.js";
3
+ import { r as Role } from "../vocabulary-hhEFLFoL.js";
4
+ import { n as requiredPlans } from "../problem-details-rIIo8B2C.js";
5
+ import { i as describe, r as DescribeOptions, t as DecisionDescription } from "../describe-C3ldA9os.js";
6
6
  import { t as PermissionBoundaryState } from "../boundary-BmHxVH1J.js";
7
7
  import { t as approvalHeaders } from "../headers-Cf-zWvsO.js";
8
- import { a as FilterResult, c as SubjectView, i as ClientStatus, l as TenantView, n as ApprovalState, o as PermissionSet, r as ClientPermDock, s as PermissionState, t as ApprovalHandle, u as UseRolesOptions } from "../types-CKNSyIf_.js";
9
- import { ComputedRef, DefineComponent, MaybeRefOrGetter, Plugin } from "vue";
8
+ import { a as ClientPermDock, c as PermissionSet, d as SubjectView, f as TenantView, i as ApprovalState, l as PermissionState, o as ClientStatus, p as UseRolesOptions, r as ApprovalHandle, s as FilterResult, u as ProviderOptionsBase } from "../store-9KO4BlkB.js";
9
+ import { ComputedRef, DefineComponent, MaybeRefOrGetter, Plugin, VNode } from "vue";
10
10
  //#region src/vue/types.d.ts
11
- type PermDockPluginOptions = {
11
+ type PermDockPluginOptions = ProviderOptionsBase & {
12
12
  /**
13
13
  * A ref or getter re-hydrates the store when it changes; a promise keeps
14
14
  * the store `pending` until it settles (await the same promise in an async
15
15
  * `setup` under `<Suspense>`).
16
16
  */
17
17
  readonly snapshot: MaybeRefOrGetter<Snapshot | string> | PromiseLike<Snapshot | string>;
18
- /**
19
- * The AuthZEN evaluations endpoint for checks the snapshot cannot answer.
20
- * `false` never calls one: such a check is denied with reason `server-only`.
21
- */
22
- readonly endpoint?: string | false;
23
- /** Where `refresh()` fetches a fresh snapshot. Defaults to `endpoint`. */
24
- readonly snapshotUrl?: string;
25
- readonly approvals?: string;
26
18
  /** A ref or getter switches the active tenant (`refresh({ tenant })`) when it changes. */
27
19
  readonly tenant?: MaybeRefOrGetter<string | undefined>;
28
- readonly fetch?: typeof fetch;
29
20
  /** Read on every request: a ref or getter carries a rotated token without rebuilding the store. */
30
21
  readonly headers?: MaybeRefOrGetter<Readonly<Record<string, string>> | undefined>;
31
- readonly maxAge?: number;
32
22
  /** Read on every verification; set it at install to verify signed snapshots. */
33
23
  readonly verifier?: MaybeRefOrGetter<TokenVerifier | undefined>;
24
+ /** What every `<Protected>` renders for a slot it leaves out. */
25
+ readonly defaults?: PermDockDefaults;
26
+ };
27
+ type SlotOutput = VNode | VNode[] | string | null;
28
+ /** Render functions for the `<Protected>` slots a component leaves out; they get the slot props. */
29
+ type PermDockDefaults = {
30
+ readonly pending?: () => SlotOutput;
31
+ readonly fallback?: (props: {
32
+ readonly decision: Decision;
33
+ }) => SlotOutput;
34
+ readonly approval?: (props: {
35
+ readonly decision: ApprovalRequiredDecision;
36
+ }) => SlotOutput;
34
37
  };
35
38
  //#endregion
36
39
  //#region src/vue/composables.d.ts
@@ -53,6 +56,8 @@ export declare function useAssignablePermissions(options?: MaybeRefOrGetter<{
53
56
  }>): ComputedRef<readonly Permission[]>;
54
57
  export declare function useSubject(): ComputedRef<SubjectView>;
55
58
  export declare function useApproval(decision: MaybeRefOrGetter<Decision>): ComputedRef<ApprovalHandle>;
59
+ /** `describe` with the plugin's `messages`; a call's own `messages` win. */
60
+ export declare function useDescribe(): (decision: Decision, options?: DescribeOptions) => DecisionDescription;
56
61
  //#endregion
57
62
  //#region src/vue/boundary.d.ts
58
63
  /**
@@ -76,4 +81,4 @@ type ProtectedProps = {
76
81
  };
77
82
  export declare const Protected: DefineComponent<ProtectedProps>;
78
83
  //#endregion
79
- export { type ApprovalHandle, type ApprovalState, type ClientPermDock, type ClientStatus, type FilterResult, type PermDockPluginOptions, type PermissionBoundaryState, type PermissionSet, type PermissionState, type ProtectedProps, type SubjectView, type TenantView, type UseRolesOptions, approvalHeaders, describe, requiredPlans };
84
+ export { type ApprovalHandle, type ApprovalState, type ClientPermDock, type ClientStatus, type FilterResult, type PermDockDefaults, type PermDockPluginOptions, type PermissionBoundaryState, type PermissionSet, type PermissionState, type ProtectedProps, type SubjectView, type TenantView, type UseRolesOptions, approvalHeaders, describe, requiredPlans };
package/dist/vue/index.js CHANGED
@@ -1,13 +1,14 @@
1
- import { r as requiredPlans } from "../problem-details-_AMOYz-w.js";
2
- import { t as describe } from "../describe-B_gVZEVi.js";
1
+ import { r as requiredPlans } from "../problem-details-DECUnXAn.js";
2
+ import { t as describe } from "../describe-Cgkp7eP0.js";
3
3
  import { t as approvalHeaders } from "../headers-BZSDieNT.js";
4
- import { i as isPromiseLike } from "../store-options-ByhZq1jV.js";
5
- import { a as protectedView, c as subjectView, i as permissionSet, l as tenantView, n as filterResult, o as rolesView, r as livePermDock, s as scopedTenant, t as approvalHandle } from "../views-Soe7bGSC.js";
4
+ import { i as isPromiseLike } from "../store-options-CbUHDoSe.js";
5
+ import { a as permissionSet, c as scopedTenant, d as tenantView, i as livePermDock, l as slotContent, n as describeWith, o as protectedView, r as filterResult, s as rolesView, t as approvalHandle, u as subjectView } from "../views-CJsrBS1f.js";
6
6
  import { n as boundaryFallback, t as boundaryDigest } from "../boundary-BM8a_P6E.js";
7
- import { n as switchTenant, t as providerStore } from "../provider-store-Cfbvo4DE.js";
7
+ import { n as switchTenant, t as providerStore } from "../provider-store-Ctt-81Ni.js";
8
8
  import { computed, defineComponent, effectScope, getCurrentScope, inject, isRef, onErrorCaptured, onScopeDispose, provide, shallowRef, toValue, watch } from "vue";
9
9
  //#region src/vue/context.ts
10
10
  const permDockKey = Symbol("permdock");
11
+ const permDockUiKey = Symbol("permdock-ui");
11
12
  //#endregion
12
13
  //#region src/vue/composables.ts
13
14
  function useStore() {
@@ -87,6 +88,10 @@ function useApproval(decision) {
87
88
  return approvalHandle(store, toValue(decision));
88
89
  });
89
90
  }
91
+ /** `describe` with the plugin's `messages`; a call's own `messages` win. */
92
+ function useDescribe() {
93
+ return describeWith(inject(permDockUiKey, {}).messages);
94
+ }
90
95
  //#endregion
91
96
  //#region src/vue/boundary.ts
92
97
  const boundaryKey = Symbol("permdock-boundary");
@@ -154,6 +159,10 @@ const permdockPlugin = { install(app, options) {
154
159
  store.dispose();
155
160
  });
156
161
  app.provide(permDockKey, store);
162
+ app.provide(permDockUiKey, {
163
+ defaults: options.defaults,
164
+ messages: options.messages
165
+ });
157
166
  } };
158
167
  //#endregion
159
168
  //#region src/vue/protected.ts
@@ -176,6 +185,7 @@ const Protected = defineComponent({
176
185
  setup(props, { slots }) {
177
186
  const local = usePermission(() => props.permission, () => props.data);
178
187
  const root = usePermDock();
188
+ const { defaults } = inject(permDockUiKey, {});
179
189
  const scoped = computed(() => scopedTenant(root, props.tenant));
180
190
  return () => {
181
191
  const view = protectedView({
@@ -183,9 +193,15 @@ const Protected = defineComponent({
183
193
  status: local.status.value,
184
194
  decision: local.decision.value
185
195
  }, root, props.permission, props.data, scoped.value);
196
+ const own = {
197
+ pending: slots["pending"],
198
+ fallback: slots["fallback"],
199
+ approval: slots["approval"]
200
+ };
186
201
  switch (view.slot) {
187
- case "pending": return slots["pending"]?.() ?? null;
188
- case "fallback": return slots["fallback"]?.({ decision: view.decision }) ?? null;
202
+ case "pending": return slotContent("pending", own, defaults)?.() ?? null;
203
+ case "fallback": return slotContent("fallback", own, defaults)?.({ decision: view.decision }) ?? null;
204
+ case "approval": return slotContent("approval", own, defaults)?.({ decision: view.decision }) ?? null;
189
205
  case "default": return slots["default"]?.({ decision: view.decision }) ?? null;
190
206
  default: return view;
191
207
  }
@@ -193,4 +209,4 @@ const Protected = defineComponent({
193
209
  }
194
210
  });
195
211
  //#endregion
196
- export { PermissionBoundary, Protected, approvalHeaders, describe, permdockPlugin, requiredPlans, useApproval, useAssignablePermissions, useAssignableRoles, useFilter, useMemberships, usePermDock, usePermission, usePermissionBoundary, usePermissions, useRoles, useSubject, useTenant };
212
+ export { PermissionBoundary, Protected, approvalHeaders, describe, permdockPlugin, requiredPlans, useApproval, useAssignablePermissions, useAssignableRoles, useDescribe, useFilter, useMemberships, usePermDock, usePermission, usePermissionBoundary, usePermissions, useRoles, useSubject, useTenant };
@@ -0,0 +1,2 @@
1
+ import { n as createCollectScheduler } from "./watch-zeucB7eF.js";
2
+ export { createCollectScheduler };
@@ -1,7 +1,7 @@
1
1
  import { i as describeError } from "./errors-CWfoNg9N.js";
2
- import { t as defaultSrcPath } from "./files-DWUN9PzI.js";
3
- import { r as runCollect } from "./collect-DSTE3ml9.js";
4
- import { n as isConfigFile, r as loadConfig } from "./config-BJiM-xAm.js";
2
+ import { t as defaultSrcPath } from "./files-D_JIzUrP.js";
3
+ import { r as runCollect } from "./collect-2SrB7lfk.js";
4
+ import { n as isConfigFile, r as loadConfig } from "./config-BIjREpyE.js";
5
5
  import { watch } from "node:fs";
6
6
  import { basename, dirname, relative, resolve, sep } from "node:path";
7
7
  //#region src/cli/watch.ts
@@ -19,7 +19,7 @@ function within(dirs, file) {
19
19
  return path !== "" && !path.startsWith("..") && !path.startsWith(sep);
20
20
  });
21
21
  }
22
- async function collectOnce(cwd, options, check, fresh, configFile) {
22
+ async function collectOnce(cwd, options, check, fresh, configFile, now = () => /* @__PURE__ */ new Date()) {
23
23
  const config = await loadConfig(cwd, configFile, { fresh });
24
24
  const collect = {
25
25
  ...config.collect,
@@ -30,7 +30,7 @@ async function collectOnce(cwd, options, check, fresh, configFile) {
30
30
  config,
31
31
  collect,
32
32
  check,
33
- now: /* @__PURE__ */ new Date(),
33
+ now: now(),
34
34
  fresh
35
35
  });
36
36
  const inputs = [
@@ -67,7 +67,7 @@ function createCollectScheduler(cwd, options, settings) {
67
67
  async function run(check) {
68
68
  const fresh = loaded;
69
69
  loaded = true;
70
- const result = await collectOnce(cwd, options, check, fresh, settings?.configFile);
70
+ const result = await collectOnce(cwd, options, check, fresh, settings?.configFile, settings?.now);
71
71
  ignored = new Set(result.written);
72
72
  inputs = result.inputs;
73
73
  sources = result.sources;
@@ -1,5 +1,5 @@
1
- import { Tt as Snapshot, Yn as Decision } from "../policy-IB6yxpC3.js";
2
- import { f as Permission, m as PermissionTree } from "../permissions-DttnqqxC.js";
1
+ import { an as Snapshot, ir as Decision } from "../policy-types-sp9P1iIV.js";
2
+ import { d as Permission, p as PermissionTree } from "../permission-types-Dg39z9Kv.js";
3
3
  import { StandardSchemaV1 } from "@standard-schema/spec";
4
4
  //#region src/webmcp/types.d.ts
5
5
  type WebMcpClientStatus = "ready" | "pending" | "stale" | "server-only";
@@ -1,15 +1,11 @@
1
- import { t as compact } from "../compact-y6vfu2_f.js";
2
- import { _ as listPermissions, h as isRegistryTree, s as getRegistry, t as annotationsFor, x as resourceOfNode } from "../permissions-DVoF6dMt.js";
3
- import { n as PermDockValidationError } from "../validation-error-CnjZ4t92.js";
4
- import { a as wireDenials } from "../problem-details-_AMOYz-w.js";
5
- import { t as describe } from "../describe-B_gVZEVi.js";
6
- import { n as isThenable, t as ignoreRejection } from "../thenable-okc2xDsj.js";
1
+ import { r as isRecord, t as compact } from "../compact-CAf557ZB.js";
2
+ import { n as isThenable, t as ignoreRejection } from "../thenable-QSmvt-vZ.js";
3
+ import { n as PermDockValidationError } from "../validation-error-ZfUHbKvf.js";
4
+ import { c as listPermissions, f as resourceOfNode, i as getRegistry, m as annotationsFor, s as isRegistryTree } from "../permission-registry-BsblpB-z.js";
7
5
  import { n as resourceRef } from "../resource-ref-CaS9yVPi.js";
6
+ import { n as deniedToolRefusal, r as toolErrorResult, t as approvalToolRefusal } from "../tool-refusal-CQ7OEia9.js";
8
7
  //#region src/webmcp/register.ts
9
8
  const MISSING_CONTEXT = "permdock/webmcp: document.modelContext is absent; registerTools is a no-op.";
10
- function isRecord(value) {
11
- return value !== null && typeof value === "object" && !Array.isArray(value);
12
- }
13
9
  const CURRENT = Symbol.for("permdock.current");
14
10
  function current(permdock) {
15
11
  const latest = permdock[CURRENT];
@@ -100,43 +96,23 @@ function bindTenant(input, tenantKey, tenant) {
100
96
  }
101
97
  };
102
98
  }
103
- function alternativesOf(decision) {
104
- return decision.alternatives.map((leaf) => leaf.key);
105
- }
106
99
  function deniedResult(decision, permission, data) {
107
- const described = describe(decision);
108
- const alternatives = alternativesOf(decision);
109
- const suffix = alternatives.length === 0 ? "" : ` You may: ${alternatives.join(", ")}.`;
110
- return {
111
- isError: true,
112
- content: [{
113
- type: "text",
114
- text: `Denied: ${permission.key}.${suffix}`
115
- }],
116
- structuredContent: compact({
117
- outcome: "denied",
118
- permission: permission.key,
119
- resource: resourceRef(permission, permission.kind === "collection" ? void 0 : data),
120
- denials: wireDenials(decision.denials),
121
- alternatives,
122
- detail: described.detail
123
- })
124
- };
100
+ return toolErrorResult(deniedToolRefusal(decision, permission, refOf(permission, data)));
125
101
  }
126
102
  function approvalResult(decision, permission, data) {
103
+ const refusal = approvalToolRefusal(decision, permission, refOf(permission, data));
127
104
  return {
128
105
  content: [{
129
106
  type: "text",
130
- text: describe(decision).detail
107
+ text: refusal.text
131
108
  }],
132
- structuredContent: {
133
- outcome: "approval-required",
134
- permission: permission.key,
135
- resource: resourceRef(permission, permission.kind === "collection" ? void 0 : data),
136
- token: decision.token
137
- }
109
+ structuredContent: refusal.structured
138
110
  };
139
111
  }
112
+ /** A collection permission names the resource type only, never an id from the input. */
113
+ function refOf(permission, data) {
114
+ return resourceRef(permission, permission.kind === "collection" ? void 0 : data);
115
+ }
140
116
  function validationResult(error) {
141
117
  return {
142
118
  isError: true,
@@ -0,0 +1,14 @@
1
+ import { j as PolicyVocabulary, jt as PermDock } from "./policy-types-sp9P1iIV.js";
2
+ //#region src/core/wrap.d.ts
3
+ /** A wrapper an adapter applies to each instance it builds, as `withOtel` does. */
4
+ type PermDockWrap = <V extends PolicyVocabulary>(permdock: PermDock<V>) => PermDock<V>;
5
+ /** The members `wrapPermDock` replaces; it re-wraps the derived instances itself. */
6
+ type PermDockOverrides<V extends PolicyVocabulary = PolicyVocabulary> = Partial<Omit<PermDock<V>, "tenant" | "team" | "derive">>;
7
+ /**
8
+ * A frozen copy of `permdock` with the members `overrides` returns replaced.
9
+ * `overrides` runs again for every instance `tenant()`, `team()` and
10
+ * `derive()` return, so a wrapper never falls off a derived instance.
11
+ */
12
+ declare function wrapPermDock<V extends PolicyVocabulary = PolicyVocabulary>(permdock: PermDock<V>, overrides: (permdock: PermDock<V>) => PermDockOverrides<V>): PermDock<V>;
13
+ //#endregion
14
+ export { PermDockWrap as n, wrapPermDock as r, PermDockOverrides as t };
@@ -0,0 +1,26 @@
1
+ //#region src/core/wrap.ts
2
+ /**
3
+ * A frozen copy of `permdock` with the members `overrides` returns replaced.
4
+ * `overrides` runs again for every instance `tenant()`, `team()` and
5
+ * `derive()` return, so a wrapper never falls off a derived instance.
6
+ */
7
+ function wrapPermDock(permdock, overrides) {
8
+ const wrap = (next) => wrapPermDock(next, overrides);
9
+ return Object.freeze({
10
+ ...permdock,
11
+ ...overrides(permdock),
12
+ tenant: (id) => wrap(permdock.tenant(id)),
13
+ team: (id) => wrap(permdock.team(id)),
14
+ derive: (options) => {
15
+ const derived = permdock.derive(options);
16
+ return derived instanceof Promise ? derived.then(wrap) : wrap(derived);
17
+ }
18
+ });
19
+ }
20
+ /** `otel`, then `wrap`. */
21
+ function composeWraps(otel, wrap) {
22
+ if (otel === void 0 || wrap === void 0) return otel ?? wrap;
23
+ return (permdock) => wrap(otel(permdock));
24
+ }
25
+ //#endregion
26
+ export { wrapPermDock as n, composeWraps as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "permdock",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Typed permissions for TypeScript apps, APIs, databases, and AI agents, with the permdock CLI and test runners.",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -263,7 +263,7 @@
263
263
  "smol-toml": "1.9.0"
264
264
  },
265
265
  "devDependencies": {
266
- "@anthropic-ai/claude-agent-sdk": "0.3.288",
266
+ "@anthropic-ai/claude-agent-sdk": "0.3.289",
267
267
  "@arethetypeswrong/cli": "0.18.5",
268
268
  "@babel/core": "8.0.6",
269
269
  "@modelcontextprotocol/client": "2.3.0",
@@ -272,9 +272,9 @@
272
272
  "@nestjs/core": "12.1.2",
273
273
  "@nestjs/platform-express": "12.1.2",
274
274
  "@openai/agents": "0.18.0",
275
- "@orpc/contract": "2.0.0-beta.41",
276
- "@orpc/openapi": "2.0.0-beta.41",
277
- "@orpc/server": "2.0.0-beta.41",
275
+ "@orpc/contract": "2.0.0-beta.42",
276
+ "@orpc/openapi": "2.0.0-beta.42",
277
+ "@orpc/server": "2.0.0-beta.42",
278
278
  "@permdock/ox-config": "0.0.0",
279
279
  "@permdock/typescript-config": "0.0.0",
280
280
  "@supabase/middleware": "1.0.0",
@@ -290,14 +290,14 @@
290
290
  "ai": "7.0.127",
291
291
  "ajv": "8.20.0",
292
292
  "babel-plugin-react-compiler": "1.0.0",
293
- "better-supabase": "0.7.0",
293
+ "better-supabase": "0.8.0",
294
294
  "drizzle-orm": "1.0.0-rc.5-5935859",
295
295
  "elysia": "1.4.30",
296
296
  "eve": "0.71.3",
297
297
  "express": "5.2.1",
298
298
  "fastify": "5.12.5",
299
299
  "happy-dom": "20.14.5",
300
- "hono": "4.13.12",
300
+ "hono": "4.13.13",
301
301
  "jose": "6.2.12",
302
302
  "kysely": "0.29.6",
303
303
  "next": "16.3.8",
@@ -334,7 +334,7 @@
334
334
  "@supabase/middleware": ">=1",
335
335
  "@trpc/server": ">=11",
336
336
  "ai": ">=5",
337
- "better-supabase": ">=0.6.0 <0.8.0",
337
+ "better-supabase": ">=0.6.0 <0.9.0",
338
338
  "drizzle-orm": ">=0.40 || >=1.0.0-rc.0",
339
339
  "elysia": ">=1",
340
340
  "eve": ">=0.40",
@@ -53,6 +53,9 @@
53
53
  "items": {
54
54
  "type": "string"
55
55
  }
56
+ },
57
+ "meta": {
58
+ "type": "object"
56
59
  }
57
60
  }
58
61
  }
@@ -485,6 +488,9 @@
485
488
  },
486
489
  "portable": {
487
490
  "const": false
491
+ },
492
+ "meta": {
493
+ "type": "object"
488
494
  }
489
495
  }
490
496
  }
@@ -30,7 +30,7 @@ Authentication is upstream: core never verifies a token. A `subjectFrom*` resolv
30
30
 
31
31
  ## Workflow
32
32
 
33
- 1. **Verify access tokens.** Resolve the subject with `subjectFromJwt(token, { discovery, audience })` from `permdock/jwt`, or `subjectFromIntrospection` when the app already called introspection. -> [references/tokens-keys-links.md](references/tokens-keys-links.md)
33
+ 1. **Verify access tokens.** Create one `createJwtSubjectResolver({ discovery, audience })` per issuer from `permdock/jwt` for the life of the process, because it caches Discovery and the JWKS; `subjectFromJwt(token, options)` caches nothing and suits a one-off check. Or use `subjectFromIntrospection` when the app already called introspection. -> [references/tokens-keys-links.md](references/tokens-keys-links.md)
34
34
  ✓ An ID token, a token for another audience and an expired token each resolve to the anonymous subject.
35
35
  2. **Issue API keys, when the product has them.** Guard the creation endpoint with its own permission, call `decideCredential(permdock, request, { settings })`, store the hash with the returned `Credential`, and show the key once. -> [references/tokens-keys-links.md](references/tokens-keys-links.md#api-keys-and-service-accounts)
36
36
  ✓ A service key wider than its creator is denied with `exceeds-creator`.
@@ -5,14 +5,19 @@ Owning pages: [JWT adapter](https://permdock.com/docs/adapters/jwt), [authentica
5
5
  ## Access tokens — `permdock/jwt`
6
6
 
7
7
  ```ts
8
- import { subjectFromJwt } from "permdock/jwt";
8
+ import { createJwtSubjectResolver } from "permdock/jwt";
9
9
 
10
- const subject = await subjectFromJwt(token, {
10
+ // One resolver per issuer for the life of the process: it caches Discovery and the JWKS.
11
+ const resolve = createJwtSubjectResolver({
11
12
  discovery: "https://issuer.example.com",
12
13
  audience: "https://api.example.com",
13
14
  });
15
+
16
+ const subject = await resolve(token, request);
14
17
  ```
15
18
 
19
+ `subjectFromJwt(token, options)` takes the same options but builds a new verifier per call, so each call fetches Discovery and the JWKS again. Use it for a one-off check such as a CLI or a test.
20
+
16
21
  - Prefer `discovery: '<issuer>'` over a hand-copied `jwks` URL. Set `audience` to the resource identifier. Write algorithms as `Ed25519`, `ES256` or `PS256`; never `EdDSA`, `none` or `RSA1_5`.
17
22
  - Keep the default `accept: 'access-token'`, so an ID token never authorises an API call.
18
23
  - `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`.
@@ -57,6 +57,10 @@ When the database already holds the rules, skip `generate`. Map each helper in `
57
57
 
58
58
  When hand-written policies call the app's own helpers (`org_ids_with_permission`, `has_org_permission`), map each under `rls.migrate.helpers` with its `form` (`ids`, `row`, `scoped`, `global`, `membership`) and the legacy keys under `rls.migrate.keys` or `prefixes`. Run `permdock rls migrate`, read the skipped calls, and apply with `--write`. Generate with `--helpers-only` while the policies stay hand-written. A `row-conditions` skip means that table's policy should be generated, not migrated.
59
59
 
60
+ When the old helpers read a permissions table that triggers keep in step (`user_permissions`), list it under `rls.migrate.tables`. `permdock rls migrate` then reports its refresh triggers and every policy, view or function that still reads it, and `permdock doctor` reports PD066 while the migrations still create it. Rewrite each reader, then run `permdock rls migrate --retire-out <migrations dir>/`, which exits `1` and writes nothing while a reader remains. Never hand-write the drop with `cascade` ([retire a materialised table](https://permdock.com/docs/cli/rls#retire-a-materialised-table)).
61
+
62
+ Triggers the app owns on generated tables (an audit trigger, a notification) go in `rls.triggers` or `rls.audit`, so they live in the generated files; never in a migration that patches the generated tables afterwards ([triggers and audit](https://permdock.com/docs/cli/rls#triggers-and-audit)).
63
+
60
64
  ## Attributes RLS cannot see
61
65
 
62
66
  A grant condition on `context.*` cannot be enforced by the database (PD027). Compare with a server-set `principal.claims.*` claim instead, never one from `user_metadata`. On Supabase, `supabase.hook.attrs` lists only server-owned columns or `app_metadata.<key>` entries clients cannot update (PD028). A check that must refuse a sign-in (single sign-on enforcement, a locked account) goes in `supabase.hook.before` as a schema-qualified `(event jsonb) returns jsonb` function the generated hook calls first; never a second hook or a hand edit of the generated one. The hook, declarative schemas (`--split`) and `fromTable` / `fromJunction` membership sources are on the [Supabase adapter](https://permdock.com/docs/adapters/supabase) and [Supabase hook](https://permdock.com/docs/adapters/supabase-hook) pages.
@@ -87,3 +87,4 @@ type CustomRole = {
87
87
  - A platform custom role (`scope: 'global'`, no `tenant`, `team` or `id`) is held through `principal.roles` and capped by the allows of declared global roles marked `assignable`. `RoleSource.globalRoles({ held })` returns them; `customRoleSource(reader, { read: 'held', policy })` skips that read while every held global role is declared.
88
88
  - A stored grant under a key renamed with `definePermissions(..., { renamed })` still resolves; `validateCustomRole` lists it in `renamed` as `{ from, to }`, and `permdock doctor` PD055 prints the `update` that rewrites it.
89
89
  - For generated RLS, add `--custom-roles` (or `rls.customRoles: true`) to `permdock rls generate`. Platform roles are rows with `scope = 'global'` and a null `tenant_id`, or the top-level `role_grants` claim in `jwt` mode. With levels, `custom_role_permissions` gains a `level` column and the claim writes `key@level`.
90
+ - To adopt custom roles the app already stores in its own tables, set `rls.customRoles.from` and `rls.customRoleWrites.roles`, then run `permdock rls generate --backfill-out <migrations dir>/`. The migration saves each role through the trusted replace function, drops entries outside the ceiling with a warning, and skips roles that already have rows; never write the copy by hand ([backfill](https://permdock.com/docs/cli/rls#backfill-from-existing-tables)).
@@ -110,7 +110,7 @@ Install each with `npx skills add ScaleDockHQ/PermDock --skill <name>` when the
110
110
 
111
111
  ## Reference index
112
112
 
113
- - [references/adapters.md](references/adapters.md): factory shapes for Next.js, HTTP frameworks, RPC frameworks, UI frameworks, AuthZEN, OpenAPI, OpenTelemetry, SCIM, Cloud, Better Auth, Clerk, Supabase, the remote PDP and collect-only frameworks.
114
- - [references/policy-options.md](references/policy-options.md): limits, disclosure, plans, validity windows, step-up, and CLI starting points (OpenAPI import, Arazzo, Cloud push).
113
+ - [references/adapters.md](references/adapters.md): factory shapes for Next.js, HTTP frameworks, RPC frameworks, UI frameworks, AuthZEN, OpenAPI, OpenTelemetry, SCIM, Cloud, Better Auth, Clerk, Supabase, the remote PDP, collect-only frameworks, and the `onDenied`, `context` and `wrap` adapter hooks.
114
+ - [references/policy-options.md](references/policy-options.md): limits, disclosure, plans, validity windows, step-up, app data and app obligations, and CLI starting points (OpenAPI import, Arazzo, Cloud push).
115
115
  - The `permdock` skill: the mental model, `explain` for an unexpected denial, and the docs MCP.
116
116
  - Docs: [policies](https://permdock.com/docs/concepts/policies), [conditions](https://permdock.com/docs/concepts/conditions), [decisions](https://permdock.com/docs/concepts/decisions), [adapters](https://permdock.com/docs/adapters).
@@ -313,6 +313,14 @@ instrument(permdock, {
313
313
 
314
314
  HTTP adapters accept the same options as `otel`. `@opentelemetry/api` is optional; without it the adapter writes only through `logger`.
315
315
 
316
+ ## Adapter hooks
317
+
318
+ Every HTTP adapter, `permdock/mcp` and `permdock/ai-sdk` take three hooks ([extend PermDock](https://permdock.com/docs/guides/extending)):
319
+
320
+ - `onDenied`: on HTTP, `({ decision, problem, request })` returns Problem Details with extra members, a `Response`, or `undefined`; a status below 300 or a throw keeps the default. On MCP and the AI SDK it returns replacement text only. On Next.js the factory `onDenied` also runs for `requireAccess`.
321
+ - `context`: returns plain JSON merged into `subject.context`. Return only server-derived values, never a header, body field or tool argument; it is visible in the snapshot.
322
+ - `wrap`: wraps each instance after `otel`; `permdock/next` takes it too. Build it with `wrapPermDock(permdock, (inner) => ({ … }))` so `tenant()`, `team()` and `derive()` stay wrapped.
323
+
316
324
  ## SCIM — `permdock/scim`
317
325
 
318
326
  No factory. Mount `scimHandler` and pass `directoryMembershipSource(store)` as `memberships`:
@@ -402,7 +410,7 @@ const subject = subjectFromSupabase(claims, {
402
410
 
403
411
  Write the claims with `permdock supabase hook generate`; `permdock supabase inspect --json` prints the manifest (helper names, tenant claim, budget, claims written) which `authorizationProvider` from `permdock/better-supabase` turns into better-supabase's `authorization` config. No `@supabase/supabase-js` peer. Pair with `permdock rls generate`, or keep SQL as authority and run `permdock rls verify --db` against `sqlFunction` twins ([database-first](https://permdock.com/docs/adapters/rls)); the generic RLS workflow is in the `permdock-data` skill.
404
412
 
405
- With better-supabase, set `authorization: authorizationProvider({ manifest, catalog })` in `better-supabase.config.ts` (with `rls.customRoles` its `canAssign` and `canAssignFor` call `permdock_can_assign_any` and its `_for` form, so custom roles are assignable through better-supabase; regenerate the manifest after turning custom roles on), build bucket and topic `access` policies with `bucketPolicy` and `topicPolicy`, and map its session with `subjectFromBetterSupabase(session)` (all from `permdock/better-supabase`): the active tenant's `features` become `principal.plans`. Pass `plans: { keys }` when better-supabase's `entitlements.claim.keys` shortens feature keys, and `apiKeys: { permissions, manifest }` so an `apiKey` session maps to the key's credential subject instead of the anonymous one. For `createMcp` tools, put the permission in `meta` and spread `toolPolicy({ permdock })` into the options: tools without one are hidden and refused, and approval-required calls are refused because `createMcp` collects no approvals. Wrap a `CredentialProvider` with `credentialGuard(provider, { permdock, use, revoke? })` so PermDock decides each token use. `authorizationProvider({ ..., approver })` lets holders of that permission approve AI tool calls, never their own. better-supabase's `createAgentRuntime({ toolApproval })` takes `toolApproval` from `permdock/ai-sdk` as it is. Validate its claims with `betterSupabase.claims(supabaseClaims().extend(appSchema))` (`supabaseClaims` from `permdock/supabase`, any Standard Schema as `appSchema`) instead of a hand-written copy of the claim shape. A `supabase.hook.claims` function that needs the user's organizations calls `<schema>.member_organization_ids_for(user_id)` (generated by `rls generate`, executable by `supabase_auth_admin` only) instead of querying the membership tables itself. A token Supabase's OAuth server issued to a third-party app (`client_id`) becomes an `oauth-client` actor limited to its `scope`; `deny(permission, { to: actor('oauth-client') })` keeps such apps out, in the app and, through `rls generate`, in Postgres. A better-supabase support session (`act.kind: 'support'`) is actor kind `support` with `sessionId` and `readOnly`, and `actingAs` (`act.kind: 'impersonation'`) is kind `impersonation`; neither has a delegation, so they reach nothing until a policy delegation names `actor('support')` or `actor('impersonation')`, and `readOnly: true` (also when `read_only` is absent) narrows that to read-only permissions. Generated RLS reads memberships, not `act`, so a support token sent to the Data API writes as the user: add a restrictive `for update` (and `insert` / `delete`) policy per writable table that requires `act ->> 'read_only' = 'false'` when `act` is a support or session level ([support access](https://permdock.com/docs/guides/support-access)). With `rls.anonymousSignIns: 'deny'`, pass `anonymousSignIns: 'deny'` to the subject mapper too (doctor PD057). Check a deployed database against the generated policies with `permdock rls verify --introspect --db $DATABASE_URL`.
413
+ With better-supabase, set `authorization: authorizationProvider({ manifest, catalog })` in `better-supabase.config.ts` (with `rls.customRoles` its `canAssign` and `canAssignFor` call `permdock_can_assign_any` and its `_for` form, so custom roles are assignable through better-supabase; regenerate the manifest after turning custom roles on), on 0.8 pass `authorizer({ policy })` to the server (`createNext`, `createHono`, `createMcp`) so every `permission` a resource, action, route guard or tool declares is decided by PermDock from the verified claims (`operations` maps tables for `permissions: true`; a missing or anonymous claim denies), build bucket and topic `access` policies with `bucketPolicy` and `topicPolicy`, and map its session with `subjectFromBetterSupabase(session)` (all from `permdock/better-supabase`): the active tenant's `features` become `principal.plans`. Pass `plans: { keys }` when better-supabase's `entitlements.claim.keys` shortens feature keys, and `apiKeys: { permissions, manifest }` so an `apiKey` session maps to the key's credential subject instead of the anonymous one. For `createMcp` tools, put the permission in `meta` and spread `toolPolicy({ permdock })` into the options: tools without one are hidden and refused, and approval-required calls are refused because `createMcp` collects no approvals. Wrap a `CredentialProvider` with `credentialGuard(provider, { permdock, use, revoke? })` so PermDock decides each token use. `authorizationProvider({ ..., approver })` lets holders of that permission approve AI tool calls, never their own. better-supabase's `createAgentRuntime({ toolApproval })` takes `toolApproval` from `permdock/ai-sdk` as it is. Validate its claims with `betterSupabase.claims(supabaseClaims().extend(appSchema))` (`supabaseClaims` from `permdock/supabase`, any Standard Schema as `appSchema`) instead of a hand-written copy of the claim shape. A `supabase.hook.claims` function that needs the user's organizations calls `<schema>.member_organization_ids_for(user_id)` (generated by `rls generate`, executable by `supabase_auth_admin` only) instead of querying the membership tables itself. A token Supabase's OAuth server issued to a third-party app (`client_id`) becomes an `oauth-client` actor limited to its `scope`; `deny(permission, { to: actor('oauth-client') })` keeps such apps out, in the app and, through `rls generate`, in Postgres. A better-supabase support session (`act.kind: 'support'`) is actor kind `support` with `sessionId` and `readOnly`, and `actingAs` (`act.kind: 'impersonation'`) is kind `impersonation`; neither has a delegation, so they reach nothing until a policy delegation names `actor('support')` or `actor('impersonation')`, and `readOnly: true` (also when `read_only` is absent) narrows that to read-only permissions. Generated RLS reads memberships, not `act`, so a support token sent to the Data API writes as the user: add a restrictive `for update` (and `insert` / `delete`) policy per writable table that requires `act ->> 'read_only' = 'false'` when `act` is a support or session level ([support access](https://permdock.com/docs/guides/support-access)). With `rls.anonymousSignIns: 'deny'`, pass `anonymousSignIns: 'deny'` to the subject mapper too (doctor PD057). Check a deployed database against the generated policies with `permdock rls verify --introspect --db $DATABASE_URL`.
406
414
 
407
415
  `claims` is whatever Supabase verified: `data.claims` from `supabase.auth.getClaims()` on an `@supabase/ssr` server client, or `jwtClaims` from `@supabase/server` (`ctx.jwtClaims` in `withSupabase` or a `pipeline`, and `c.var.jwtClaims` after a framework bridge such as `toHono([withClaims(), withPermDock()])`). `@supabase/server/adapters/*` and `c.var.supabaseContext` are deprecated and removed on 1 December 2026; do not write new code against them ([Hono, H3, Elysia and NestJS](https://permdock.com/docs/adapters/supabase#hono-h3-elysia-and-nestjs)). Pass `null` for anonymous callers; never `getSession().access_token` (unverified). An API-key auth mode (`secret`, `publishable`) has `jwtClaims: null` and is the anonymous subject, not a user.
408
416
 
@@ -33,10 +33,19 @@ Hardware-key step-up is `to: assurance({ amr: ['hwk'], maxAge: 300 })` and rende
33
33
  Adopting PermDock in an app with its own keys, SQL helpers and tokens is a step-by-step guide ([existing apps](https://permdock.com/docs/getting-started/existing-apps)):
34
34
 
35
35
  - Keep the app's keys. Map verbs such as `view` to SQL with `rls.actions`, and give colliding resources a distinct `name` on `resource()`.
36
- - Put application-owned metadata in `meta.x`; PermDock carries it and never reads it.
36
+ - Put application-owned metadata in `meta.x`; PermDock carries it and never reads it (see App data below).
37
37
  - Rename a key later with `definePermissions(tree, { renamed: { "old.key": "new.key" } })`. Remove the alias only when `permdock doctor` PD055 and PD056 are quiet; `permdock diff` reports the removal as the breaking `alias-removed`.
38
38
  - Generate helpers beside legacy SQL with `permdock rls generate --helpers-only --shims`, then rewrite policies with `permdock rls migrate --write`.
39
39
 
40
+ ## App data and app obligations
41
+
42
+ Owning page: [extend PermDock](https://permdock.com/docs/guides/extending).
43
+
44
+ - Type `x` with one Standard Schema per kind: `definePermissions(tree, { x: { permission, resource } })`, `defineRoles(tree, { x })`, `definePlans(tree, { x })`, `definePolicy(…, { x: { grant, membership } })`. Each schema validates synchronously. Invalid `x` in code throws; invalid `Membership.x` or custom-role `meta.x` from a source is dropped and the row stays.
45
+ - Describe a grant with `allow(p, { name, meta: { description, x } })`. It reaches `decision.matched`, decision events, snapshot grants and catalog grants, and stays out of the policy fingerprint.
46
+ - Steer code on a grant with `allow(p, { obligations: ['watermark', { name, detail }] })`, never on a deny. Read `{ kind: 'app', name, detail? }` from `decision.obligations` on a granted decision.
47
+ - Snapshots carry grant `meta`, membership `x` and every leaf's `meta` to the client: never put a secret in them.
48
+
40
49
  ## CLI starting points
41
50
 
42
51
  - When the app already has an OpenAPI document and no definitions yet, start from `permdock openapi import --doc <doc> --out src/permissions.generated.ts --schema zod` and review each action's `meta.inferredFrom`.
@@ -1,2 +0,0 @@
1
- import { t as runCatalog } from "./catalog-DWF5cYqB.js";
2
- export { runCatalog };
@@ -1,2 +0,0 @@
1
- import { r as runCollect } from "./collect-DSTE3ml9.js";
2
- export { runCollect };