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,15 +1,14 @@
1
- import { n as isReadonlyArray, r as sole, t as compact } from "./compact-y6vfu2_f.js";
1
+ import { a as sole, n as isReadonlyArray, t as compact } from "./compact-CAf557ZB.js";
2
2
  import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
3
- import { D as ownKeys, T as isForbiddenKey, _ as listPermissions, f as isFieldRelation, g as isSelfParented, h as isRegistryTree, i as findPermission, p as isPermission, s as getRegistry, t as annotationsFor, w as assertSafeKey } from "./permissions-DVoF6dMt.js";
4
- import { c as isConditionRef, l as isSqlFunctionField, n as isSubjectRef, o as isCondition, s as isConditionDate } from "./refs-KYb4ntaz.js";
5
- import { c as isUserApprover, i as flattenApprovers, l as user, o as isAnyOfInput, r as approverLeaves, s as isPermissionApprover } from "./approvers-DT4AVyIg.js";
6
- import { n as defineScopes, o as resolveScope } from "./scopes-CVdPrWN-.js";
3
+ import { a as assertSafeKey, c as ownKeys, o as isForbiddenKey } from "./thenable-QSmvt-vZ.js";
4
+ import { c as isConditionRef, l as isSqlFunctionField, n as isSubjectRef, o as isCondition, s as isConditionDate } from "./refs-f3imMjNW.js";
5
+ import { c as isUserApprover, i as flattenApprovers, l as user, o as isAnyOfInput, r as approverLeaves, s as isPermissionApprover } from "./approvers-CqPOLD-o.js";
6
+ import { n as assertMetaValue, r as parseAppData, t as assertAppData } from "./app-data-CV8pqqMi.js";
7
7
  import { t as parseDuration } from "./duration-xK2jGFVc.js";
8
- import { E as listRoles, a as authenticated, g as relationStart, h as relationHops, l as inheritCondition, r as asGrantee, s as flattenGrantee, u as isGraphRelation, v as roleNameOf, w as isRole, y as roleScopeOf } from "./grantee-Cv5Sogfv.js";
9
- import { t as canonicalJson } from "./canonical-json-DemiK4Vp.js";
10
- import { i as sanitizeFields } from "./fields-BMl1RxoX.js";
11
- import { n as sha256, t as bytesToBase64Url } from "./sha256-BO0swRXL.js";
12
- import { f as relatesTo, h as scopeField, n as normalizeValidity, s as memberOfFields } from "./validity-uOp8UpYn.js";
8
+ import { c as listPermissions, o as isPermission } from "./permission-registry-BsblpB-z.js";
9
+ import { d as isSelfParented } from "./resource-relations-D1Un3pcz.js";
10
+ import { a as authenticated, d as roleScopeOf, g as isRole, o as flattenGrantee, r as asGrantee, u as roleNameOf } from "./grantee-CXY-0C87.js";
11
+ import { n as normalizeValidity, o as sanitizeFields } from "./validity-dVrUEPJt.js";
13
12
  //#region src/conditions/opaque.ts
14
13
  function opaque(input) {
15
14
  return freezeDeep({
@@ -213,6 +212,153 @@ function normalizeWhere(input) {
213
212
  });
214
213
  }
215
214
  //#endregion
215
+ //#region src/core/approval-normalize.ts
216
+ /** Every approver a requirement names: `by`, each stage and its escalation, and `escalation.to`, inside `anyOf` groups too. */
217
+ function approversOf(requirement) {
218
+ return [
219
+ ...approverLeaves(requirement.by),
220
+ ...(requirement.stages ?? []).flatMap((stage) => approverLeaves(stage.by).concat(approverLeaves(stage.escalation?.to))),
221
+ ...approverLeaves(requirement.escalation?.to)
222
+ ];
223
+ }
224
+ function asApprover(input) {
225
+ if (isPermissionApprover(input)) {
226
+ if (typeof input.permission !== "string" || input.permission === "") throw new Error("PermDock: a permission approver needs a permission key");
227
+ return Object.freeze({
228
+ kind: "permission",
229
+ permission: input.permission
230
+ });
231
+ }
232
+ if (isAnyOfInput(input)) {
233
+ if (!Array.isArray(input.of) || input.of.length === 0) throw new Error("PermDock: anyOf() needs at least one approver");
234
+ const of = input.of.map((item) => {
235
+ const normalized = asApprover(item);
236
+ const items = flattenApprovers(normalized);
237
+ if (items.length === 0) throw new Error("PermDock: an anyOf() item names no approver");
238
+ const [first] = items;
239
+ return isReadonlyArray(normalized) || first === void 0 ? items : first;
240
+ });
241
+ return Object.freeze({
242
+ kind: "any-of",
243
+ of: Object.freeze(of)
244
+ });
245
+ }
246
+ if (isReadonlyArray(input)) {
247
+ const items = [];
248
+ for (const item of input) items.push(...flattenApprovers(asApprover(item)));
249
+ return items;
250
+ }
251
+ if (isUserApprover(input)) return user(input.id);
252
+ return asGrantee(input);
253
+ }
254
+ function normalizeApproval(approval, permission) {
255
+ if (approval === void 0) return;
256
+ if (approval === "human") return "human";
257
+ if (approval.staleOn !== void 0 && approval.staleOn !== "resource-change") throw new Error(`PermDock: approval staleOn must be 'resource-change', got '${String(approval.staleOn)}'`);
258
+ const label = permission ?? "a grant";
259
+ assertQuorum(approval.quorum, "approval.quorum", label);
260
+ if (approval.ttl !== void 0 && parseDuration(approval.ttl) === void 0) throw new Error(`PermDock: approval.ttl on '${label}' must be a duration such as '30m', got '${approval.ttl}'`);
261
+ const escalation = normalizeEscalation(approval.escalation, label);
262
+ const mode = approval.mode ?? "any";
263
+ if (mode !== "any") return compact({
264
+ mode,
265
+ stages: normalizeStages(approval, mode, label),
266
+ distinct: approval.distinct,
267
+ staleOn: approval.staleOn,
268
+ ttl: approval.ttl,
269
+ escalation
270
+ });
271
+ if (approval.stages !== void 0) throw new Error(`PermDock: approval.stages on '${label}' needs mode: 'all' or 'sequential'`);
272
+ const by = approval.by === void 0 ? void 0 : asApprover(approval.by);
273
+ if (by === void 0 && approval.distinct === void 0 && approval.staleOn === void 0 && approval.quorum === void 0 && approval.ttl === void 0 && escalation === void 0) return "human";
274
+ return compact({
275
+ by: by ?? authenticated(),
276
+ distinct: approval.distinct,
277
+ staleOn: approval.staleOn,
278
+ quorum: approval.quorum,
279
+ ttl: approval.ttl,
280
+ escalation
281
+ });
282
+ }
283
+ function assertQuorum(quorum, name, label) {
284
+ if (quorum !== void 0 && (!Number.isInteger(quorum) || quorum < 1)) throw new Error(`PermDock: ${name} on '${label}' must be an integer of at least 1, got ${String(quorum)}`);
285
+ }
286
+ function normalizeStages(approval, mode, label) {
287
+ if (mode !== "all" && mode !== "sequential") throw new Error(`PermDock: approval.mode on '${label}' must be 'any', 'all' or 'sequential', got '${mode}'`);
288
+ if (approval.by !== void 0 || approval.quorum !== void 0) throw new Error(`PermDock: approval on '${label}' sets mode '${mode}': put by and quorum on each stage`);
289
+ const stages = approval.stages ?? [];
290
+ if (stages.length === 0) throw new Error(`PermDock: approval mode '${mode}' on '${label}' needs at least one stage`);
291
+ return stages.map((stage, index) => {
292
+ assertQuorum(stage.quorum, `approval.stages[${index}].quorum`, label);
293
+ const by = asApprover(stage.by);
294
+ if (flattenApprovers(by).length === 0) throw new Error(`PermDock: approval.stages[${index}].by on '${label}' names no approver`);
295
+ return compact({
296
+ by,
297
+ quorum: stage.quorum,
298
+ escalation: normalizeEscalation(stage.escalation, label)
299
+ });
300
+ });
301
+ }
302
+ function normalizeEscalation(escalation, label) {
303
+ if (escalation === void 0) return;
304
+ if (parseDuration(escalation.after) === void 0) throw new Error(`PermDock: approval.escalation.after on '${label}' must be a duration such as '4h', got '${escalation.after}'`);
305
+ return {
306
+ after: escalation.after,
307
+ to: asApprover(escalation.to)
308
+ };
309
+ }
310
+ /**
311
+ * A role with `activation` is eligible-only: it needs a positive `maxDuration`
312
+ * (Doctor PD033 warns without one). `justification` defaults to `'optional'`.
313
+ */
314
+ function activationApproval(option, roleName) {
315
+ const label = `activation of '${roleName}'`;
316
+ const approval = normalizeApproval(option, label);
317
+ if (approval !== void 0 && approval !== "human" && approversOf(approval).some((item) => item.kind === "relation")) throw new Error(`PermDock: approval on ${label} names a relation; an activation has no row to read it on`);
318
+ return approval;
319
+ }
320
+ /**
321
+ * A stale-on-change approval needs a row to version: an instance permission
322
+ * whose resource declares `version`.
323
+ */
324
+ function assertApprovalVersions(grants, resources) {
325
+ for (const grant of grants) {
326
+ const approval = grant.approval;
327
+ if (approval === void 0 || approval === "human" || approval.staleOn === void 0) continue;
328
+ if (grant.permission.kind !== "instance") throw new Error(`PermDock: approval staleOn on '${grant.permission.key}' needs an instance action; a collection action has no row to version`);
329
+ if (resources.get(grant.permission.resource)?.version === void 0) throw new Error(`PermDock: approval staleOn on '${grant.permission.key}' needs resource(..., { version: '<field>' }) on '${grant.permission.resource}'`);
330
+ }
331
+ }
332
+ /**
333
+ * A relation approver is checked by id, from the requested row: the
334
+ * relation lives on the permission's own resource (optionally up its parent
335
+ * chain), or at the end of a list of links from it.
336
+ */
337
+ function assertApprovalRelations(grants, resources) {
338
+ for (const grant of grants) {
339
+ const approval = grant.approval;
340
+ if (approval === void 0 || approval === "human") continue;
341
+ for (const item of approversOf(approval)) {
342
+ if (item.kind !== "relation") continue;
343
+ const label = `${grant.permission.key}: approver relation '${item.relation}'`;
344
+ if (grant.permission.kind !== "instance") throw new Error(`PermDock: ${label} needs an instance action; a collection action has no row to read it on`);
345
+ if (approverRelationResource(grant.permission.resource, item.through, resources) !== item.resource) throw new Error(`PermDock: ${label} must live on '${grant.permission.resource}' or at the end of its through links`);
346
+ if (resources.get(item.resource)?.relations[item.relation] === void 0) throw new Error(`PermDock: ${label} is not declared on '${item.resource}'`);
347
+ }
348
+ }
349
+ }
350
+ /** The resource a relation approver's `through` reaches from `start`, or `undefined`. */
351
+ function approverRelationResource(start, through, resources) {
352
+ if (through === void 0) return start;
353
+ if (through === "parent") return isSelfParented(resources.get(start)) ? start : void 0;
354
+ let current = start;
355
+ for (const name of through) {
356
+ const node = current === void 0 ? void 0 : resources.get(current);
357
+ current = node !== void 0 && Object.hasOwn(node.links, name) ? node.links[name]?.resource : void 0;
358
+ }
359
+ return current;
360
+ }
361
+ //#endregion
216
362
  //#region src/core/limits.ts
217
363
  const UNIT_SECONDS = {
218
364
  s: 1,
@@ -427,119 +573,7 @@ function applyQuota(input) {
427
573
  }
428
574
  }
429
575
  //#endregion
430
- //#region src/core/policy.ts
431
- /** Every approver a requirement names: `by`, each stage and its escalation, and `escalation.to`, inside `anyOf` groups too. */
432
- function approversOf(requirement) {
433
- return [
434
- ...approverLeaves(requirement.by),
435
- ...(requirement.stages ?? []).flatMap((stage) => approverLeaves(stage.by).concat(approverLeaves(stage.escalation?.to))),
436
- ...approverLeaves(requirement.escalation?.to)
437
- ];
438
- }
439
- function asApprover(input) {
440
- if (isPermissionApprover(input)) {
441
- if (typeof input.permission !== "string" || input.permission === "") throw new Error("PermDock: a permission approver needs a permission key");
442
- return Object.freeze({
443
- kind: "permission",
444
- permission: input.permission
445
- });
446
- }
447
- if (isAnyOfInput(input)) {
448
- if (!Array.isArray(input.of) || input.of.length === 0) throw new Error("PermDock: anyOf() needs at least one approver");
449
- const of = input.of.map((item) => {
450
- const normalized = asApprover(item);
451
- const items = flattenApprovers(normalized);
452
- if (items.length === 0) throw new Error("PermDock: an anyOf() item names no approver");
453
- const [first] = items;
454
- return isReadonlyArray(normalized) || first === void 0 ? items : first;
455
- });
456
- return Object.freeze({
457
- kind: "any-of",
458
- of: Object.freeze(of)
459
- });
460
- }
461
- if (isReadonlyArray(input)) {
462
- const items = [];
463
- for (const item of input) items.push(...flattenApprovers(asApprover(item)));
464
- return items;
465
- }
466
- if (isUserApprover(input)) return user(input.id);
467
- return asGrantee(input);
468
- }
469
- function indexPolicy(roles, grants, vocabulary) {
470
- const declaredRoles = new Set(roles.map((item) => item.name));
471
- for (const leaf of listRoles(vocabulary.roles)) declaredRoles.add(leaf.key);
472
- const supports = roles.flatMap((binding) => binding.support === void 0 ? [] : [binding.support]);
473
- const listed = grants.length > 0 ? grants : roles.flatMap((binding) => binding.grants);
474
- const byKey = /* @__PURE__ */ new Map();
475
- for (const grant of listed) {
476
- const bucket = byKey.get(grant.permission.key);
477
- if (bucket === void 0) byKey.set(grant.permission.key, [grant]);
478
- else bucket.push(grant);
479
- }
480
- for (const bucket of byKey.values()) Object.freeze(bucket);
481
- return freezeDeep({
482
- declaredRoles,
483
- supports,
484
- grantsByKey: byKey
485
- });
486
- }
487
- function normalizeApproval(approval, permission) {
488
- if (approval === void 0) return;
489
- if (approval === "human") return "human";
490
- if (approval.staleOn !== void 0 && approval.staleOn !== "resource-change") throw new Error(`PermDock: approval staleOn must be 'resource-change', got '${String(approval.staleOn)}'`);
491
- const label = permission ?? "a grant";
492
- assertQuorum(approval.quorum, "approval.quorum", label);
493
- if (approval.ttl !== void 0 && parseDuration(approval.ttl) === void 0) throw new Error(`PermDock: approval.ttl on '${label}' must be a duration such as '30m', got '${approval.ttl}'`);
494
- const escalation = normalizeEscalation(approval.escalation, label);
495
- const mode = approval.mode ?? "any";
496
- if (mode !== "any") return compact({
497
- mode,
498
- stages: normalizeStages(approval, mode, label),
499
- distinct: approval.distinct,
500
- staleOn: approval.staleOn,
501
- ttl: approval.ttl,
502
- escalation
503
- });
504
- if (approval.stages !== void 0) throw new Error(`PermDock: approval.stages on '${label}' needs mode: 'all' or 'sequential'`);
505
- const by = approval.by === void 0 ? void 0 : asApprover(approval.by);
506
- if (by === void 0 && approval.distinct === void 0 && approval.staleOn === void 0 && approval.quorum === void 0 && approval.ttl === void 0 && escalation === void 0) return "human";
507
- return compact({
508
- by: by ?? authenticated(),
509
- distinct: approval.distinct,
510
- staleOn: approval.staleOn,
511
- quorum: approval.quorum,
512
- ttl: approval.ttl,
513
- escalation
514
- });
515
- }
516
- function assertQuorum(quorum, name, label) {
517
- if (quorum !== void 0 && (!Number.isInteger(quorum) || quorum < 1)) throw new Error(`PermDock: ${name} on '${label}' must be an integer of at least 1, got ${String(quorum)}`);
518
- }
519
- function normalizeStages(approval, mode, label) {
520
- if (mode !== "all" && mode !== "sequential") throw new Error(`PermDock: approval.mode on '${label}' must be 'any', 'all' or 'sequential', got '${mode}'`);
521
- if (approval.by !== void 0 || approval.quorum !== void 0) throw new Error(`PermDock: approval on '${label}' sets mode '${mode}': put by and quorum on each stage`);
522
- const stages = approval.stages ?? [];
523
- if (stages.length === 0) throw new Error(`PermDock: approval mode '${mode}' on '${label}' needs at least one stage`);
524
- return stages.map((stage, index) => {
525
- assertQuorum(stage.quorum, `approval.stages[${index}].quorum`, label);
526
- const by = asApprover(stage.by);
527
- if (flattenApprovers(by).length === 0) throw new Error(`PermDock: approval.stages[${index}].by on '${label}' names no approver`);
528
- return compact({
529
- by,
530
- quorum: stage.quorum,
531
- escalation: normalizeEscalation(stage.escalation, label)
532
- });
533
- });
534
- }
535
- function normalizeEscalation(escalation, label) {
536
- if (escalation === void 0) return;
537
- if (parseDuration(escalation.after) === void 0) throw new Error(`PermDock: approval.escalation.after on '${label}' must be a duration such as '4h', got '${escalation.after}'`);
538
- return {
539
- after: escalation.after,
540
- to: asApprover(escalation.to)
541
- };
542
- }
576
+ //#region src/core/grant-builders.ts
543
577
  function isClosure(value) {
544
578
  return typeof value === "function";
545
579
  }
@@ -548,78 +582,6 @@ function flattenPermissions(input) {
548
582
  if (isReadonlyArray(input)) return input.flatMap((item) => flattenPermissions(item));
549
583
  return [...listPermissions(input)];
550
584
  }
551
- function delegationTarget(to, index) {
552
- if (typeof to === "string") return { kind: to };
553
- if ("actor" in to) return { kind: to.actor };
554
- const target = compact({
555
- kind: to.kind,
556
- id: to.id,
557
- client: to.client
558
- });
559
- if (typeof target.kind !== "string" || target.kind === "") throw new Error(`PermDock: delegations[${index}].to needs an actor kind, such as actor('eve')`);
560
- if (target.id !== void 0 && (typeof target.id !== "string" || target.id === "")) throw new Error(`PermDock: delegations[${index}].to.id must be a non-empty string`);
561
- if (target.client !== void 0 && (typeof target.client !== "string" || target.client === "")) throw new Error(`PermDock: delegations[${index}].to.client must be a non-empty string`);
562
- if (target.id !== void 0 && target.client !== void 0) throw new Error(`PermDock: delegations[${index}].to names both an id and a client; name one`);
563
- return target;
564
- }
565
- function normalizeDelegation(input, index, tree) {
566
- const label = `delegations[${index}]`;
567
- const from = asGrantee(input.from);
568
- const items = flattenGrantee(from);
569
- if (items.length === 0) throw new Error(`PermDock: ${label}.from names nobody`);
570
- if (items.some((item) => item.kind === "relation" || item.kind === "inherit")) throw new Error(`PermDock: ${label}.from names a relation or inherit(); a delegation is matched without a row, so name a role or another subject-only grantee`);
571
- if (items.some((item) => item.kind === "actor")) throw new Error(`PermDock: ${label}.from names an actor; the principal hands over, the actor is \`to\``);
572
- const leaves = /* @__PURE__ */ new Map();
573
- for (const leaf of input.permissions.flatMap((item) => flattenPermissions(item))) {
574
- if (findPermission(tree, leaf.key) === void 0) throw new Error(`PermDock: ${label} names unknown permission '${leaf.key}'`);
575
- leaves.set(leaf.key, leaf);
576
- }
577
- const keys = [...leaves.keys()].toSorted();
578
- if (keys.length === 0) throw new Error(`PermDock: ${label}.permissions is empty`);
579
- return compact({
580
- from,
581
- to: delegationTarget(input.to, index),
582
- permissions: keys,
583
- readOnly: [...leaves.values()].filter((leaf) => annotationsFor(leaf).readOnlyHint).map((leaf) => leaf.key).toSorted(),
584
- validity: normalizeValidity(input, label)
585
- });
586
- }
587
- /** RFC 6749 section 3.3 `scope-token`: printable ASCII without space, `"` or `\`. */
588
- function isScopeToken(value) {
589
- return /^[!#-[\]-~]+$/u.test(value);
590
- }
591
- function normalizeOAuthScopes(input, tree) {
592
- if (input === void 0) return [];
593
- const own = new Set(listPermissions(tree).map((leaf) => leaf.scope));
594
- return Object.entries(input).map(([scope, items]) => {
595
- if (!isScopeToken(scope)) throw new Error(`PermDock: oauthScopes key '${scope}' is not an OAuth scope token`);
596
- if (own.has(scope)) throw new Error(`PermDock: oauthScopes key '${scope}' is a permission's own scope`);
597
- const leaves = /* @__PURE__ */ new Map();
598
- for (const leaf of (Array.isArray(items) ? items : []).flatMap((item) => flattenPermissions(item))) {
599
- if (findPermission(tree, leaf.key) === void 0) throw new Error(`PermDock: oauthScopes '${scope}' names unknown permission '${leaf.key}'`);
600
- leaves.set(leaf.key, leaf);
601
- }
602
- if (leaves.size === 0) throw new Error(`PermDock: oauthScopes '${scope}' covers no permission`);
603
- const sorted = [...leaves.values()].toSorted((a, b) => a.key.localeCompare(b.key));
604
- return {
605
- scope,
606
- permissions: sorted.map((leaf) => leaf.key),
607
- scopes: sorted.map((leaf) => leaf.scope)
608
- };
609
- });
610
- }
611
- function resolveRoleScope(on) {
612
- if (on === void 0) return "global";
613
- if (typeof on === "string") {
614
- if (on === "global" || on === "resource") throw new Error(`PermDock: role on: '${on}' is not a scope name`);
615
- return on;
616
- }
617
- const permissions = flattenPermissions(on);
618
- const names = new Set(permissions.map((permission) => permission.resource));
619
- const [resource] = names;
620
- if (names.size !== 1 || resource === void 0) throw new Error("PermDock: role on: resource must name exactly one resource");
621
- return { resource };
622
- }
623
585
  const GROUP = /^[a-z][a-z0-9_-]*$/u;
624
586
  function grantGroup(group, key) {
625
587
  if (group === void 0) return;
@@ -661,11 +623,64 @@ function makeGrant(permission, effect, condition) {
661
623
  fields: sanitizeFields(condition?.fields),
662
624
  name: condition?.name,
663
625
  group: grantGroup(condition?.group, permission.key),
626
+ meta: grantMeta(condition?.meta, permission.key, void 0),
627
+ obligations: appObligations(condition?.obligations, permission.key, effect),
664
628
  purpose,
665
629
  validity: normalizeValidity(condition ?? {}, permission.key),
666
630
  requires
667
631
  });
668
632
  }
633
+ /** Checks a grant's `meta`: plain JSON, string `description`, `x` through the schema when given. */
634
+ function grantMeta(meta, key, schema) {
635
+ if (meta === void 0) return;
636
+ assertAppData(meta, `meta of a grant on ${key}`);
637
+ const { description, x } = meta;
638
+ if (description !== void 0 && typeof description !== "string") throw new TypeError(`PermDock: meta.description of a grant on ${key} must be a string`);
639
+ return freezeDeep(compact({
640
+ description,
641
+ x: x === void 0 ? void 0 : parseAppData(schema, x, `meta.x of a grant on ${key}`)
642
+ }));
643
+ }
644
+ function appObligations(input, key, effect) {
645
+ if (input === void 0) return;
646
+ if (effect !== "allow") throw new Error(`PermDock: obligations are allowed on an allow only; '${key}' is a deny`);
647
+ const list = input;
648
+ if (!Array.isArray(list)) throw new TypeError(`PermDock: obligations on '${key}' must be a list`);
649
+ const items = list;
650
+ const seen = /* @__PURE__ */ new Set();
651
+ const out = [];
652
+ for (const item of items) {
653
+ const entry = typeof item === "object" && item !== null ? item : void 0;
654
+ const name = typeof item === "string" ? item : entry === void 0 ? void 0 : Reflect.get(entry, "name");
655
+ if (typeof name !== "string" || !GROUP.test(name)) throw new Error(`PermDock: obligation '${String(name)}' on '${key}' must be lower case letters, digits, _ or -, starting with a letter`);
656
+ if (seen.has(name)) throw new Error(`PermDock: obligation '${name}' is listed twice on '${key}'`);
657
+ seen.add(name);
658
+ const detail = entry === void 0 ? void 0 : Reflect.get(entry, "detail");
659
+ if (detail === void 0) {
660
+ out.push({
661
+ kind: "app",
662
+ name
663
+ });
664
+ continue;
665
+ }
666
+ assertMetaValue(detail, `detail of obligation '${name}' on '${key}'`);
667
+ out.push({
668
+ kind: "app",
669
+ name,
670
+ detail
671
+ });
672
+ }
673
+ return out.length === 0 ? void 0 : freezeDeep(out);
674
+ }
675
+ /** Re-checks every grant's `meta.x` with the policy's grant schema, keeping the schema output. */
676
+ function withGrantSchema(grant, schema) {
677
+ const meta = grant.meta;
678
+ if (schema === void 0 || meta?.x === void 0) return grant;
679
+ return freezeDeep({
680
+ ...grant,
681
+ meta: grantMeta(meta, grant.permission.key, schema) ?? meta
682
+ });
683
+ }
669
684
  function requiredKey(input, permission, effect) {
670
685
  if (input === void 0) return;
671
686
  if (effect !== "allow") throw new Error(`PermDock: requires is allowed on an allow only; '${permission.key}' is a deny`);
@@ -688,6 +703,30 @@ function flattenGrants(grants) {
688
703
  else out.push(grant);
689
704
  return out;
690
705
  }
706
+ function completeGrant(grant) {
707
+ const to = flattenGrantee(grant.to);
708
+ const first = to[0];
709
+ if (to.length === 1 && first?.kind === "role" && first.role === "") throw new Error("PermDock: grant is missing to");
710
+ return freezeDeep({
711
+ ...grant,
712
+ role: roleNameOf(grant.to),
713
+ scope: roleScopeOf(grant.to)
714
+ });
715
+ }
716
+ //#endregion
717
+ //#region src/core/role-builder.ts
718
+ function resolveRoleScope(on) {
719
+ if (on === void 0) return "global";
720
+ if (typeof on === "string") {
721
+ if (on === "global" || on === "resource") throw new Error(`PermDock: role on: '${on}' is not a scope name`);
722
+ return on;
723
+ }
724
+ const permissions = flattenPermissions(on);
725
+ const names = new Set(permissions.map((permission) => permission.resource));
726
+ const [resource] = names;
727
+ if (names.size !== 1 || resource === void 0) throw new Error("PermDock: role on: resource must name exactly one resource");
728
+ return { resource };
729
+ }
691
730
  function role(name, grants, options) {
692
731
  if (options !== void 0 && Object.hasOwn(options, "restricted")) throw new Error(`PermDock: role option 'restricted' is reserved`);
693
732
  const leaf = isRole(name) ? name : void 0;
@@ -723,16 +762,6 @@ function role(name, grants, options) {
723
762
  activation
724
763
  }));
725
764
  }
726
- /**
727
- * A role with `activation` is eligible-only: it needs a positive `maxDuration`
728
- * (Doctor PD033 warns without one). `justification` defaults to `'optional'`.
729
- */
730
- function activationApproval(option, roleName) {
731
- const label = `activation of '${roleName}'`;
732
- const approval = normalizeApproval(option, label);
733
- if (approval !== void 0 && approval !== "human" && approversOf(approval).some((item) => item.kind === "relation")) throw new Error(`PermDock: approval on ${label} names a relation; an activation has no row to read it on`);
734
- return approval;
735
- }
736
765
  function normalizeActivation(roleName, option) {
737
766
  if (option === void 0) return;
738
767
  const justification = option.justification ?? "optional";
@@ -783,340 +812,5 @@ function roleRules(roleName, scope, options) {
783
812
  for: nameList(roleName, "for", options?.for)
784
813
  });
785
814
  }
786
- function canonicalPolicy(grants, delegations, levels) {
787
- const payload = canonicalGrants(grants);
788
- const withDelegations = delegations.length === 0 ? payload : `${payload}\n${JSON.stringify(delegations)}`;
789
- return levels === void 0 ? withDelegations : `${withDelegations}\nlevels:${canonicalJson(levels)}`;
790
- }
791
- function normalizeLevels(resources) {
792
- const out = {};
793
- for (const node of resources.values()) {
794
- const entries = Object.entries({ ...node.levels });
795
- if (entries.length === 0) continue;
796
- const levels = {};
797
- for (const [name, input] of entries) try {
798
- levels[name] = Object.keys(input).length === 0 ? {
799
- op: "and",
800
- conditions: []
801
- } : normalizeWhere(input);
802
- } catch (error) {
803
- throw new Error(`PermDock: level '${name}' on '${node.name}' is not a valid condition`, { cause: error });
804
- }
805
- out[node.name] = levels;
806
- }
807
- return Object.keys(out).length === 0 ? void 0 : freezeDeep(out);
808
- }
809
- /** Declared levels of `resource` with their conditions, in declaration order. */
810
- function policyLevels(policy, resource) {
811
- const levels = policy.levels;
812
- return levels !== void 0 && Object.hasOwn(levels, resource) ? Object.entries({ ...levels[resource] }) : [];
813
- }
814
- /** The condition of `level` on `resource`, if the policy declares it. */
815
- function levelCondition(policy, resource, level) {
816
- return policyLevels(policy, resource).find(([name]) => name === level)?.[1];
817
- }
818
- /** Declared level names of `resource`, in declaration order. */
819
- function levelNames(policy, resource) {
820
- return policyLevels(policy, resource).map(([name]) => name);
821
- }
822
- function canonicalGrants(grants) {
823
- const payload = grants.map((grant) => ({
824
- permission: grant.permission.key,
825
- effect: grant.effect,
826
- to: grant.to,
827
- role: grant.role,
828
- where: grant.where,
829
- check: grant.check,
830
- approval: grant.approval,
831
- portable: grant.portable,
832
- fields: grant.fields,
833
- scope: grant.scope,
834
- name: grant.name,
835
- purpose: grant.purpose,
836
- breakGlass: grant.breakGlass,
837
- viaOnly: grant.viaOnly,
838
- validity: grant.validity,
839
- requires: grant.requires
840
- }));
841
- return JSON.stringify(payload);
842
- }
843
- function assertParentGraph(resources) {
844
- for (const node of resources.values()) {
845
- if (node.parent === void 0) continue;
846
- if (!resources.has(node.parent.resource)) throw new Error(`PermDock: resource '${node.name}' parents unknown resource '${node.parent.resource}'`);
847
- }
848
- }
849
- /**
850
- * Graph relation grantees must reach their resource: `through: 'parent'` from
851
- * the row to its parent resource or along its own self-parent, and never over
852
- * a `memberOf` relation, which is tenancy, not the object graph.
853
- */
854
- function assertRelationGrants(grants, resources) {
855
- for (const grant of grants) for (const item of flattenGrantee(grant.to)) {
856
- if (item.kind !== "relation" || !isGraphRelation(item, resources)) continue;
857
- const label = `grant ${grant.permission.key} relation '${item.relation}'`;
858
- const target = resources.get(item.resource);
859
- const spec = target?.relations[item.relation];
860
- if (target === void 0 || spec === void 0) throw new Error(`PermDock: ${label}: ${item.resource} does not declare it`);
861
- if (isFieldRelation(spec) && spec.memberOf !== void 0) throw new Error(`PermDock: ${label} is a memberOf relation; through walks the object graph, not scopes`);
862
- const row = resources.get(grant.permission.resource);
863
- if (Array.isArray(item.through)) {
864
- if (relationHops(item, row, resources) === void 0) throw new Error(`PermDock: ${label}: the links [${item.through.join(", ")}] from ${grant.permission.resource} do not end on ${target.name}${(item.depth ?? 0) > 0 ? ` (or ${target.name} does not parent itself for depth)` : ""}`);
865
- continue;
866
- }
867
- if (item.through === "parent" && target.name === row?.name && !isSelfParented(target)) throw new Error(`PermDock: ${label}: through: 'parent' needs ${target.name} to parent itself`);
868
- if (relationStart(item, row, target) === void 0) throw new Error(item.through === void 0 ? `PermDock: ${label} is on ${target.name}, not ${grant.permission.resource}; add through: 'parent'` : `PermDock: ${label}: ${grant.permission.resource} has no parent on ${target.name}`);
869
- }
870
- }
871
- function assertInheritGrants(grants, resources, tree) {
872
- const keys = new Set(listPermissions(tree).map((leaf) => leaf.key));
873
- const edges = /* @__PURE__ */ new Map();
874
- for (const grant of grants) for (const item of flattenGrantee(grant.to)) {
875
- if (item.kind !== "inherit") continue;
876
- const label = `grant ${grant.permission.key} inherit '${item.permission}'`;
877
- if (grant.effect !== "allow") throw new Error(`PermDock: ${label}: inherit() is allowed on an allow only`);
878
- if (grant.permission.kind !== "instance") throw new Error(`PermDock: ${label}: inherit() needs an instance action; a collection action has no row to follow`);
879
- if (!keys.has(item.permission)) throw new Error(`PermDock: ${label}: the policy does not declare it`);
880
- if (inheritCondition(item, resources.get(grant.permission.resource), resources) === void 0) throw new Error(item.through === "parent" ? `PermDock: ${label}: ${grant.permission.resource} has no parent on ${item.resource}` : `PermDock: ${label}: the links [${item.through.join(", ")}] from ${grant.permission.resource} do not end on ${item.resource}`);
881
- const next = edges.get(grant.permission.key) ?? /* @__PURE__ */ new Set();
882
- next.add(item.permission);
883
- edges.set(grant.permission.key, next);
884
- }
885
- const done = /* @__PURE__ */ new Set();
886
- const visit = (key, path) => {
887
- if (path.includes(key)) throw new Error(`PermDock: inherit() grants form a cycle: ${[...path.slice(path.indexOf(key)), key].join(" -> ")}`);
888
- if (done.has(key)) return;
889
- for (const target of edges.get(key) ?? []) visit(target, [...path, key]);
890
- done.add(key);
891
- };
892
- for (const key of edges.keys()) visit(key, []);
893
- }
894
- function scopeOfGrant(scope, declared) {
895
- if (typeof scope !== "string" || scope === "global") return scope;
896
- const resolved = resolveScope(declared, scope);
897
- if (resolved === void 0) throw new Error(`PermDock: definePolicy({ scopes }) must declare '${scope}' for on: '${scope}' roles`);
898
- return resolved;
899
- }
900
- function rescopeGrantee(to, declared) {
901
- const items = flattenGrantee(to);
902
- if (!items.some((item) => item.kind === "role")) return to;
903
- const mapped = items.map((item) => item.kind === "role" ? freezeDeep({
904
- ...item,
905
- scope: scopeOfGrant(item.scope, declared)
906
- }) : item);
907
- if (Array.isArray(to)) return freezeDeep(mapped);
908
- const [single] = mapped;
909
- return single ?? to;
910
- }
911
- /** Resolves `tenant` / `team` aliases to declared names; an undeclared scope throws. */
912
- function rescopeGrant(grant, declared) {
913
- const scope = scopeOfGrant(grant.scope, declared);
914
- const to = rescopeGrantee(grant.to, declared);
915
- if (scope === grant.scope && to === grant.to) return grant;
916
- return freezeDeep({
917
- ...grant,
918
- scope,
919
- to
920
- });
921
- }
922
- function rescopeBinding(binding, declared) {
923
- const grants = binding.grants.map((grant) => rescopeGrant(grant, declared));
924
- const on = typeof binding.on === "string" ? scopeOfGrant(binding.on, declared) : binding.on;
925
- return freezeDeep(compact({
926
- ...binding,
927
- grants,
928
- on
929
- }));
930
- }
931
- /**
932
- * No implicit cascade: a grant on scope S reaches a row only through the row's
933
- * own S key, so every resource an instance grant on S touches declares a
934
- * `memberOf: S` relation on that key. Without it `where()` and RLS could not
935
- * narrow the rows.
936
- */
937
- function assertScopeKeys(grants, scopes, resources) {
938
- for (const grant of grants) {
939
- if (typeof grant.scope !== "string" || grant.scope === "global" || grant.permission.kind !== "instance") continue;
940
- const key = scopes.find((scope) => scope.name === grant.scope)?.key;
941
- const node = resources.get(grant.permission.resource);
942
- if (key === void 0 || node === void 0) continue;
943
- const fields = memberOfFields(node, grant.scope, scopes);
944
- if (fields.length > 1 && !fields.includes(key)) throw new Error(`PermDock: resource '${node.name}' declares several memberOf relations to '${grant.scope}' (${fields.join(", ")}); name the one holding the instance with the scope's key '${key}'`);
945
- const field = scopeField(node, grant.scope, scopes);
946
- if (field !== void 0 && relatesTo(node, field, grant.scope, scopes)) continue;
947
- throw new Error(`PermDock: resource '${node.name}' needs relations: { <name>: { field: '${key}', memberOf: '${grant.scope}' } } for ${grant.permission.key} on '${grant.scope}' roles`);
948
- }
949
- }
950
- /** A `requires` names a permission the policy declares. */
951
- function assertRequires(grants, tree) {
952
- const keys = new Set(listPermissions(tree).map((leaf) => leaf.key));
953
- for (const grant of grants) for (const key of grant.requires ?? []) if (!keys.has(key)) throw new Error(`PermDock: '${grant.permission.key}' requires '${key}', which the policy does not declare`);
954
- }
955
- /**
956
- * A stale-on-change approval needs a row to version: an instance permission
957
- * whose resource declares `version`.
958
- */
959
- function assertApprovalVersions(grants, resources) {
960
- for (const grant of grants) {
961
- const approval = grant.approval;
962
- if (approval === void 0 || approval === "human" || approval.staleOn === void 0) continue;
963
- if (grant.permission.kind !== "instance") throw new Error(`PermDock: approval staleOn on '${grant.permission.key}' needs an instance action; a collection action has no row to version`);
964
- if (resources.get(grant.permission.resource)?.version === void 0) throw new Error(`PermDock: approval staleOn on '${grant.permission.key}' needs resource(..., { version: '<field>' }) on '${grant.permission.resource}'`);
965
- }
966
- }
967
- /**
968
- * A relation approver is checked by id, from the requested row: the
969
- * relation lives on the permission's own resource (optionally up its parent
970
- * chain), or at the end of a list of links from it.
971
- */
972
- function assertApprovalRelations(grants, resources) {
973
- for (const grant of grants) {
974
- const approval = grant.approval;
975
- if (approval === void 0 || approval === "human") continue;
976
- for (const item of approversOf(approval)) {
977
- if (item.kind !== "relation") continue;
978
- const label = `${grant.permission.key}: approver relation '${item.relation}'`;
979
- if (grant.permission.kind !== "instance") throw new Error(`PermDock: ${label} needs an instance action; a collection action has no row to read it on`);
980
- if (approverRelationResource(grant.permission.resource, item.through, resources) !== item.resource) throw new Error(`PermDock: ${label} must live on '${grant.permission.resource}' or at the end of its through links`);
981
- if (resources.get(item.resource)?.relations[item.relation] === void 0) throw new Error(`PermDock: ${label} is not declared on '${item.resource}'`);
982
- }
983
- }
984
- }
985
- /** The resource a relation approver's `through` reaches from `start`, or `undefined`. */
986
- function approverRelationResource(start, through, resources) {
987
- if (through === void 0) return start;
988
- if (through === "parent") return isSelfParented(resources.get(start)) ? start : void 0;
989
- let current = start;
990
- for (const name of through) {
991
- const node = current === void 0 ? void 0 : resources.get(current);
992
- current = node !== void 0 && Object.hasOwn(node.links, name) ? node.links[name]?.resource : void 0;
993
- }
994
- return current;
995
- }
996
- function isVocabularyInput(value) {
997
- return value !== null && typeof value === "object" && "permissions" in value && isRegistryTree(value.permissions);
998
- }
999
- function completeGrant(grant) {
1000
- const to = flattenGrantee(grant.to);
1001
- const first = to[0];
1002
- if (to.length === 1 && first?.kind === "role" && first.role === "") throw new Error("PermDock: grant is missing to");
1003
- return freezeDeep({
1004
- ...grant,
1005
- role: roleNameOf(grant.to),
1006
- scope: roleScopeOf(grant.to)
1007
- });
1008
- }
1009
- function mergeBindings(items) {
1010
- const merged = /* @__PURE__ */ new Map();
1011
- for (const item of items) {
1012
- const existing = merged.get(item.name);
1013
- if (existing === void 0) {
1014
- merged.set(item.name, item);
1015
- continue;
1016
- }
1017
- merged.set(item.name, freezeDeep(compact({
1018
- name: item.name,
1019
- grants: [...existing.grants, ...item.grants],
1020
- on: existing.on,
1021
- assignable: existing.assignable,
1022
- exclusiveWith: existing.exclusiveWith ?? item.exclusiveWith,
1023
- min: existing.min ?? item.min,
1024
- max: existing.max ?? item.max,
1025
- transferOnly: existing.transferOnly ?? item.transferOnly,
1026
- assigns: existing.assigns ?? item.assigns,
1027
- for: existing.for ?? item.for,
1028
- meta: existing.meta ?? item.meta,
1029
- activation: existing.activation ?? item.activation,
1030
- support: existing.support ?? item.support
1031
- })));
1032
- }
1033
- return {
1034
- roles: [...merged.values()],
1035
- rolesByName: merged
1036
- };
1037
- }
1038
- function definePolicy(permissions, options) {
1039
- const vocabulary = isVocabularyInput(permissions) ? permissions : { permissions };
1040
- const tree = vocabulary.permissions;
1041
- const mapper = options.principal ?? options.subject;
1042
- if (mapper === void 0) throw new Error("PermDock: definePolicy requires principal or subject");
1043
- const resources = getRegistry(tree);
1044
- assertParentGraph(resources);
1045
- const scopes = defineScopes(options.scopes);
1046
- const { roles, rolesByName } = mergeBindings((options.roles ?? []).map((binding) => rescopeBinding(binding, scopes)));
1047
- const declared = new Set(roles.map((item) => item.name));
1048
- for (const leaf of listRoles(vocabulary.roles)) declared.add(leaf.key);
1049
- for (const binding of roles) for (const name of binding.assigns ?? []) if (!declared.has(name)) throw new Error(`PermDock: role '${binding.name}' names undeclared role '${name}'`);
1050
- const fromBindings = roles.flatMap((item) => item.grants);
1051
- const fromGrants = flattenGrants(options.grants ?? []).map(completeGrant).map((grant) => rescopeGrant(grant, scopes));
1052
- const grants = [...fromBindings, ...fromGrants];
1053
- assertScopeKeys(grants, scopes, resources);
1054
- assertApprovalVersions(grants, resources);
1055
- assertApprovalRelations(grants, resources);
1056
- assertRelationGrants(grants, resources);
1057
- assertRequires(grants, tree);
1058
- assertInheritGrants(grants, resources, tree);
1059
- const delegations = (options.delegations ?? []).map((item, index) => normalizeDelegation(item, index, tree));
1060
- const levels = normalizeLevels(resources);
1061
- const oauthScopes = normalizeOAuthScopes(options.oauthScopes, tree);
1062
- const fingerprint = bytesToBase64Url(sha256(oauthScopes.length === 0 ? canonicalPolicy(grants, delegations, levels) : `${canonicalPolicy(grants, delegations, levels)}\noauthScopes:${canonicalJson(oauthScopes)}`));
1063
- const hostable = [...new Set((options.hostable ?? []).flatMap((item) => flattenPermissions(item).map((leaf) => leaf.key)))].toSorted();
1064
- const fresh = [...new Set((options.fresh ?? []).flatMap((item) => flattenPermissions(item).map((leaf) => leaf.key)))].toSorted();
1065
- return freezeDeep({
1066
- permissions: tree,
1067
- roles,
1068
- rolesByName,
1069
- grants,
1070
- vocabulary,
1071
- scopes,
1072
- principal: mapper,
1073
- subject: mapper,
1074
- context: options.context,
1075
- validate: options.validate ?? "boundary",
1076
- onDenied: options.onDenied,
1077
- fingerprint,
1078
- resources,
1079
- providers: options.providers,
1080
- hostable,
1081
- fresh,
1082
- delegations: delegations.length === 0 ? void 0 : delegations,
1083
- levels,
1084
- oauthScopes: oauthScopes.length === 0 ? void 0 : oauthScopes,
1085
- index: indexPolicy(roles, grants, vocabulary)
1086
- });
1087
- }
1088
- function exclusivePairs(policy) {
1089
- const pairs = /* @__PURE__ */ new Map();
1090
- for (const binding of policy.roles) if (binding.exclusiveWith !== void 0) pairs.set(binding.name, binding.exclusiveWith);
1091
- return pairs;
1092
- }
1093
- function grantList(policy) {
1094
- if (policy.grants !== void 0 && policy.grants.length > 0) return policy.grants;
1095
- return policy.roles.flatMap((binding) => binding.grants);
1096
- }
1097
- function declaredRoleNames(policy) {
1098
- return policy.index.declaredRoles;
1099
- }
1100
- function separationConflicts(policy, memberships) {
1101
- const exclusive = exclusivePairs(policy);
1102
- const seen = /* @__PURE__ */ new Set();
1103
- const conflicts = [];
1104
- for (const membership of memberships) {
1105
- const held = new Set(membership.roles);
1106
- for (const name of held) for (const other of exclusive.get(name) ?? []) {
1107
- if (!held.has(other)) continue;
1108
- const pair = [name, other].toSorted();
1109
- const key = `${membership.principal ?? ""}:${membership.tenant ?? ""}:${pair.join("+")}`;
1110
- if (seen.has(key)) continue;
1111
- seen.add(key);
1112
- conflicts.push(compact({
1113
- principal: membership.principal ?? "",
1114
- tenant: membership.tenant,
1115
- roles: pair
1116
- }));
1117
- }
1118
- }
1119
- return conflicts;
1120
- }
1121
815
  //#endregion
1122
- export { opaque as S, memoryLimitStore as _, definePolicy as a, assertSqlFunctionArg as b, indexPolicy as c, normalizeApproval as d, normalizeAssurance as f, applyQuota as g, separationConflicts as h, declaredRoleNames as i, levelCondition as l, role as m, assertApprovalRelations as n, deny as o, policyLevels as p, completeGrant as r, grantList as s, allow as t, levelNames as u, normalizeWhere as v, assertSqlFunctionName as x, assertPortableTwin as y };
816
+ export { assertSqlFunctionName as _, deny as a, withGrantSchema as c, assertApprovalRelations as d, assertApprovalVersions as f, assertSqlFunctionArg as g, assertPortableTwin as h, completeGrant as i, applyQuota as l, normalizeWhere as m, role as n, flattenGrants as o, normalizeApproval as p, allow as r, flattenPermissions as s, normalizeAssurance as t, memoryLimitStore as u, opaque as v };