permdock 0.6.0 → 0.8.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 (507) hide show
  1. package/README.md +2 -3
  2. package/dist/{2020-C9VN-x8c.js → 2020-CJbO8Bvz.js} +1 -3
  3. package/dist/a2a/index.d.ts +7 -7
  4. package/dist/a2a/index.js +9 -9
  5. package/dist/action-result-CL-QCITA.d.ts +19 -0
  6. package/dist/{adapter-context-CRhqyzCk.js → adapter-context-CIQpQxbE.js} +8 -2
  7. package/dist/{adoption-scan-DCYe60Pi.js → adoption-scan-BLs67P1l.js} +5 -5
  8. package/dist/agent/index.d.ts +3 -3
  9. package/dist/agent/index.js +1 -1
  10. package/dist/ai-sdk/index.d.ts +31 -10
  11. package/dist/ai-sdk/index.js +22 -12
  12. package/dist/{app-data-MuyzVqX8.js → app-data-UNNm07jV.js} +10 -7
  13. package/dist/{approval-header-CJACtHkv.js → approval-header-8QV6MU4H.js} +6 -3
  14. package/dist/{approval-prompt-Dg5LeAcT.js → approval-prompt-B8hQY69x.js} +5 -6
  15. package/dist/{approval-prompt-DvSSPQJX.d.ts → approval-prompt-PYagyQUj.d.ts} +13 -11
  16. package/dist/approvals/index.d.ts +5 -5
  17. package/dist/approvals/index.js +7 -7
  18. package/dist/{approvals-p1PGoVjb.js → approvals-DnIBTuXE.js} +128 -78
  19. package/dist/{approvers-CqPOLD-o.js → approvers-B4r0N_Uz.js} +8 -2
  20. package/dist/{arazzo-41WuzHou.js → arazzo-3RhGfkAK.js} +2 -2
  21. package/dist/{arazzo-CaUVBn7D.js → arazzo-B5-ulWif.js} +6 -6
  22. package/dist/{args-IIolxxKA.js → args-0FrVs5EH.js} +125 -8
  23. package/dist/astro/index.d.ts +30 -12
  24. package/dist/astro/index.js +2 -2
  25. package/dist/{audience-DabClFLQ.js → audience-BAkBDMqn.js} +8 -8
  26. package/dist/{auth-DRLEizbL.js → auth--yPyZNgr.js} +21 -10
  27. package/dist/authzen/index.d.ts +171 -25
  28. package/dist/authzen/index.js +321 -149
  29. package/dist/{automation-BNM3TtDo.d.ts → automation-DqEoWHBc.d.ts} +42 -32
  30. package/dist/{automation-DVjOckjV.js → automation-x3KEUusw.js} +22 -21
  31. package/dist/base-url-BQbddZO5.js +9 -0
  32. package/dist/better-auth/index.d.ts +2 -2
  33. package/dist/better-auth/index.js +13 -7
  34. package/dist/better-supabase/index.d.ts +392 -220
  35. package/dist/better-supabase/index.js +293 -152
  36. package/dist/{bind-DOyrv6zi.d.ts → bind-Cp2hBHzP.d.ts} +27 -12
  37. package/dist/{bind-CAvgUuKs.js → bind-D_sZSVA3.js} +22 -10
  38. package/dist/{body-CH5of8Ne.js → body-CJQwYVa8.js} +3 -3
  39. package/dist/{body-text-QcXok_SI.js → body-text-DQhcmqdY.js} +8 -4
  40. package/dist/{boundary-BM8a_P6E.js → boundary-BV3O1eud.js} +8 -2
  41. package/dist/{boundary-BmHxVH1J.d.ts → boundary-C9ck-3uK.d.ts} +13 -4
  42. package/dist/{budget-NbEtbJC_.js → budget-BELja5A9.js} +6 -3
  43. package/dist/{budget-JqcRqyhK.d.ts → budget-hYsPz_yE.d.ts} +6 -3
  44. package/dist/{build-instance-Bu_eDqYw.js → build-instance-CNWaYJyr.js} +3 -3
  45. package/dist/{canonical-json-BC8_nMTw.js → canonical-json-DwilZ1iB.js} +6 -3
  46. package/dist/{capability-N1K9IpqS.js → capability-BqX94r07.js} +31 -25
  47. package/dist/{capability-Drg-1YhL.d.ts → capability-ChuiONQU.d.ts} +41 -29
  48. package/dist/{casbin-Dyu2gnUD.js → casbin-H0rKxBx2.js} +16 -8
  49. package/dist/{casbin-Cr7RLtA3.js → casbin-cbSbhT_k.js} +2 -2
  50. package/dist/{casl-64gpT-8x.js → casl-C4OINZHI.js} +2 -2
  51. package/dist/{casl-DjEDhTCP.js → casl-CHHoCldP.js} +19 -10
  52. package/dist/catalog/index.d.ts +104 -23
  53. package/dist/catalog/index.js +117 -8
  54. package/dist/{catalog-HD2gf5mY.js → catalog-BFpz2EmT.js} +57 -26
  55. package/dist/{catalog-DZVbrF-z.js → catalog-DCspHDc8.js} +3 -3
  56. package/dist/{catalog-doc-Cdn7-0pQ.js → catalog-doc-DjMKzJp9.js} +53 -16
  57. package/dist/{catalog-fingerprint-CCP0-yQS.js → catalog-fingerprint-e6aCWosn.js} +19 -15
  58. package/dist/catalog-mRQQQhNK.js +1 -0
  59. package/dist/catalog-operations-Dadrl7Z-.js +60 -0
  60. package/dist/{create-CQWIpUG-.js → challenge-DImNcR7B.js} +157 -39
  61. package/dist/chat/index.d.ts +1 -1
  62. package/dist/chat/index.js +13 -10
  63. package/dist/chat-sdk/index.d.ts +44 -26
  64. package/dist/chat-sdk/index.js +17 -17
  65. package/dist/checks-CGkP3Z7A.js +40 -0
  66. package/dist/{claims-map-7oQ3ue4X.js → claims-map-CKkoAAYF.js} +5 -2
  67. package/dist/{claims-map-Ca-QX8C6.d.ts → claims-map-D1Pb5oRq.d.ts} +8 -5
  68. package/dist/claude-agent/index.d.ts +6 -6
  69. package/dist/claude-agent/index.js +6 -3
  70. package/dist/clerk/index.d.ts +11 -7
  71. package/dist/clerk/index.js +6 -6
  72. package/dist/cli/bin.js +4 -4
  73. package/dist/cli/index.d.ts +82 -7
  74. package/dist/cli/index.js +6 -6
  75. package/dist/{clients-C7zLFuWT.d.ts → clients-C_NOET3z.d.ts} +5 -5
  76. package/dist/{clients-DjU5ABMy.js → clients-DYr3U86j.js} +3 -3
  77. package/dist/cloud/index.d.ts +186 -38
  78. package/dist/cloud/index.js +293 -31
  79. package/dist/{cloud-ytQ3uviA.js → cloud-BFlGMaak.js} +5 -6
  80. package/dist/{codemod-5mpSpnUY.js → codemod-DLQ9Zpo4.js} +3 -4
  81. package/dist/{codemod-ua2hHy7w.js → codemod-DWSN2erG.js} +523 -201
  82. package/dist/collect-B5BL3klN.js +1 -0
  83. package/dist/{collect-mLTY4nwb.js → collect-B7ZFAJU3.js} +36 -64
  84. package/dist/{collect-Ci6akVwH.js → collect-Bzv3le0A.js} +6 -6
  85. package/dist/{compare-pfyVnBjE.js → compare-DTfyUunF.js} +2 -2
  86. package/dist/compile/index.d.ts +2 -2
  87. package/dist/compile/index.js +1 -1
  88. package/dist/{compile-1bsAezL0.d.ts → compile-BFzysW3o.d.ts} +36 -12
  89. package/dist/{compile-CMqMx_IN.js → compile-EzEMB-7v.js} +77 -33
  90. package/dist/{completion-BTFrHZhX.js → completion-saoYiRFO.js} +17 -8
  91. package/dist/config-BwPBfN0t.js +108 -0
  92. package/dist/{config-Bj2Ixq3d.js → config-DBeXXmBF.js} +2 -2
  93. package/dist/{config-report-DSpsLpCE.js → config-report-BipSWA6V.js} +9 -6
  94. package/dist/config-shape-ykV0Vm2n.js +134 -0
  95. package/dist/{connection-DjhIJSs2.js → connection-B72dg5Q2.js} +23 -22
  96. package/dist/connector-schema-CYLQNMYq.js +434 -0
  97. package/dist/{context-B_u3_bDJ.js → context-BnIzxTNE.js} +4 -3
  98. package/dist/convex/index.d.ts +13 -7
  99. package/dist/convex/index.js +9 -6
  100. package/dist/core-H-mbhpZc.js +341 -0
  101. package/dist/core-hWIARPDz.d.ts +206 -0
  102. package/dist/{create-CBMmFie-.d.ts → create-BSNrVuxh.d.ts} +87 -34
  103. package/dist/{create-B30OMUOJ.d.ts → create-BVq1lNQE.d.ts} +49 -28
  104. package/dist/{create-D_NmPOdH.d.ts → create-CM1FciYG.d.ts} +37 -29
  105. package/dist/{create-CGm28gyI.js → create-Cq4Uox0f.js} +13 -9
  106. package/dist/{create-DCF2SvoT.js → create-_noSrY1T.js} +15 -21
  107. package/dist/{credential-BcoiejpY.js → credential-CyyyvCsL.js} +42 -39
  108. package/dist/{credentials-DPyHmYz5.js → credentials-CdDxp7jN.js} +6 -6
  109. package/dist/{deciding-columns-Sq12mEA6.js → deciding-columns-NB4wcyBf.js} +13 -2
  110. package/dist/{delegation-j6-rc37o.js → delegation-CDB6_keF.js} +31 -22
  111. package/dist/delivery/index.d.ts +5 -5
  112. package/dist/delivery/index.js +6 -5
  113. package/dist/{delivery-DCAgNyCn.js → delivery-BupfvJIV.js} +81 -20
  114. package/dist/{delivery-event-xX4obB8F.js → delivery-event-JioK5YbS.js} +6 -6
  115. package/dist/denied-text-CHNlVInN.d.ts +22 -0
  116. package/dist/{describe-BybMRY7A.js → describe-Bb4hGK5d.js} +6 -5
  117. package/dist/{describe-B5qgDvEW.d.ts → describe-ByS9LgHK.d.ts} +5 -5
  118. package/dist/{device-BARQ8eYG.js → device-BwbJNmb2.js} +11 -8
  119. package/dist/{diff-CmuSD3vc.js → diff-CN8IYhC_.js} +2 -2
  120. package/dist/{diff-3jbx6Rm4.js → diff-iZWV65nC.js} +23 -14
  121. package/dist/{digest-B3kc_PgQ.d.ts → digest-8Yx2CchM.d.ts} +3 -3
  122. package/dist/{doctor-BdZw53-k.js → doctor-CHD1M9R5.js} +485 -141
  123. package/dist/{doctor-3ZqNHX_G.js → doctor-D3wo-yuz.js} +4 -4
  124. package/dist/drizzle/index.d.ts +33 -19
  125. package/dist/drizzle/index.js +17 -9
  126. package/dist/elysia/index.d.ts +17 -11
  127. package/dist/elysia/index.js +5 -5
  128. package/dist/{errors-BKy0EfhN.js → errors-B6R_lg2a.js} +13 -4
  129. package/dist/{errors-BWXBMaKK.d.ts → errors-CHwoRRpB.d.ts} +4 -1
  130. package/dist/{errors-CWTY6uih.js → errors-Vpu6rKHl.js} +14 -10
  131. package/dist/{errors-DH5QEGXh.d.ts → errors-zi_4T-rx.d.ts} +22 -6
  132. package/dist/{evaluate-CNClBvcj.js → evaluate-Dd8Ta0Ie.js} +185 -80
  133. package/dist/{evaluations-beAooV0n.js → evaluations-IBceAeKT.js} +41 -20
  134. package/dist/{evaluations-C_1vdSZc.d.ts → evaluations-z8dQFDaN.d.ts} +12 -6
  135. package/dist/eve/index.d.ts +9 -6
  136. package/dist/eve/index.js +4 -4
  137. package/dist/{event-time-CsegxXxB.js → event-time-BGy48400.js} +8 -4
  138. package/dist/{expiry-D4_YKRKD.js → expiry-6XByK0dm.js} +8 -5
  139. package/dist/express/index.d.ts +9 -6
  140. package/dist/express/index.js +9 -6
  141. package/dist/fastify/index.d.ts +16 -10
  142. package/dist/fastify/index.js +8 -5
  143. package/dist/{fetch-adapter-Dw0MTS3D.d.ts → fetch-adapter-C1DCvpqV.d.ts} +9 -6
  144. package/dist/{fetch-adapter-DD_gfmrC.js → fetch-adapter-JL43jD3E.js} +14 -11
  145. package/dist/fields-D0vUI6dq.js +498 -0
  146. package/dist/{files-C5ZI27eV.js → files-B3AA05f1.js} +21 -5
  147. package/dist/{files-D_JIzUrP.js → files-BSjrtIHw.js} +11 -4
  148. package/dist/{fixtures-B7XrLeY7.js → fixtures-A1_sp_tR.js} +15 -6
  149. package/dist/{flags-C3DktBDY.js → flags-DXjoTVbS.js} +2 -2
  150. package/dist/{freeze-CrU8nQeX.js → freeze-jjan0lCv.js} +4 -1
  151. package/dist/{from-snapshot-CTCMsFZk.js → from-snapshot-DCakWRsr.js} +26 -16
  152. package/dist/gen-B5kvbAoZ.js +58 -0
  153. package/dist/gen-DWCYcMQM.js +827 -0
  154. package/dist/generate-CRVV5V7l.js +165 -0
  155. package/dist/generate-CezbCaTI.js +275 -0
  156. package/dist/{grantee-hxrUsbpM.js → grantee-Dke-9rd1.js} +4 -4
  157. package/dist/{grantee-conditions-CcXf8hMM.js → grantee-conditions-BrYPe-w0.js} +12 -12
  158. package/dist/{grantee-match-DbENBHLB.js → grantee-match-7RZZvoT_.js} +12 -6
  159. package/dist/{graph-sql-B-dsAT6j.d.ts → graph-sql-BwFC4Qjs.d.ts} +3 -3
  160. package/dist/h3/index.d.ts +10 -7
  161. package/dist/h3/index.js +3 -3
  162. package/dist/headers-B9jQxjtW.d.ts +10 -0
  163. package/dist/{helpers-CBYVMjwh.js → helpers-DJicaG6f.js} +40 -28
  164. package/dist/hono/index.d.ts +16 -10
  165. package/dist/hono/index.js +5 -5
  166. package/dist/{hosted-BPk51-kX.d.ts → hosted-Cmtxogd0.d.ts} +44 -20
  167. package/dist/{hosted-B46-5LYE.js → hosted-D0IzESu_.js} +68 -25
  168. package/dist/{http-ujKm0JXE.js → http-DH94eh6f.js} +4 -4
  169. package/dist/{http-BBoKefeS.js → http-DKLXrFGk.js} +13 -7
  170. package/dist/{http-DXJ37RDA.js → http-DOL33cO0.js} +11 -8
  171. package/dist/{import-wyqXUyjm.js → import-CST57XLp.js} +64 -51
  172. package/dist/{import-CNV7I2Dw.js → import-_YqhhwvX.js} +6 -6
  173. package/dist/{index-B8YjkEZ4.d.ts → index-B8s204GL.d.ts} +64 -52
  174. package/dist/{index-Ch8LpNDp.d.ts → index-BT5-1VsX.d.ts} +64 -25
  175. package/dist/{index-DuWxc5dt.d.ts → index-BW_0MZOS.d.ts} +388 -149
  176. package/dist/index-BhxEUY9J.d.ts +233 -0
  177. package/dist/index-Bv5iXPqU.d.ts +210 -0
  178. package/dist/{index-C-6Letxg.d.ts → index-_9UiQIkt.d.ts} +164 -77
  179. package/dist/index.d.ts +22 -21
  180. package/dist/index.js +35 -33
  181. package/dist/{init-GG6Jh8HD.js → init-Dz_PsHdv.js} +5 -5
  182. package/dist/{init-DeMYsnYJ.js → init-cE3A8aXq.js} +10 -10
  183. package/dist/{instance-options-BsVpyGIk.d.ts → instance-options-B0KXqTrJ.d.ts} +4 -4
  184. package/dist/{instance-snapshot-BOEhcqIF.js → instance-snapshot--JWiTrvO.js} +81 -56
  185. package/dist/{instant-BluqDvyS.js → instant-DK3Iz83e.js} +2 -2
  186. package/dist/{internals-Dk8A8fX3.js → internals-B3IgHrvo.js} +6 -3
  187. package/dist/{json-schema-B-vAwlde.js → json-schema-BPGa-RjQ.js} +9 -3
  188. package/dist/{json-schema-CN_iLFH2.d.ts → json-schema-BfXgnRNT.d.ts} +4 -4
  189. package/dist/jwt/index.d.ts +125 -17
  190. package/dist/jwt/index.js +157 -16
  191. package/dist/{kernel-D0NVb1cK.js → kernel-C-fYydV2.js} +151 -16
  192. package/dist/kysely/index.d.ts +49 -33
  193. package/dist/kysely/index.js +9 -7
  194. package/dist/{live-options-BaAFCIiu.js → live-options-BBIT68le.js} +2 -2
  195. package/dist/{load-DFS_ry0W.js → load-DjSU5KXO.js} +6 -6
  196. package/dist/load-Dm0pSYH3.js +1 -0
  197. package/dist/{login-Dfe5RlYk.js → login-D-8tMqzo.js} +4 -4
  198. package/dist/{login-imhuwvn3.js → login-DplQ0s84.js} +18 -15
  199. package/dist/{manifest-dvL2XEe1.js → manifest-Cgiq5oqc.js} +67 -37
  200. package/dist/{manifest-mx5ghSFM.d.ts → manifest-CzzWtnAb.d.ts} +144 -28
  201. package/dist/{manifest-schema-C0kK_8V0.js → manifest-schema-2r37XRhD.js} +80 -9
  202. package/dist/{manifest-C8IzW3Do.js → manifest-wg8WkkpD.js} +11 -7
  203. package/dist/{map-claims-D3oRmTk0.js → map-claims-BNWCJtmP.js} +27 -18
  204. package/dist/{map-error-Dr70oA_3.js → map-error-pasIGqMT.js} +7 -7
  205. package/dist/{markers-C6joDI3o.js → markers-BeHZ4x9Q.js} +20 -5
  206. package/dist/mcp/index.d.ts +154 -47
  207. package/dist/mcp/index.js +200 -41
  208. package/dist/{migrate-CIq4-E9F.js → migrate-B7oP_sQU.js} +102 -31
  209. package/dist/module-values-BJTBdo6y.js +107 -0
  210. package/dist/nest/index.d.ts +23 -13
  211. package/dist/nest/index.js +18 -11
  212. package/dist/next/client.d.ts +5 -2
  213. package/dist/next/client.js +1 -1
  214. package/dist/next/index.d.ts +72 -26
  215. package/dist/next/index.js +110 -6
  216. package/dist/next/plugin.d.ts +1 -1
  217. package/dist/next/plugin.js +4 -3
  218. package/dist/node/index.d.ts +5 -5
  219. package/dist/node/index.js +3 -3
  220. package/dist/{ocsf-BFp-PZZA.js → ocsf-TcjRBgIs.js} +15 -5
  221. package/dist/openai/index.d.ts +13 -7
  222. package/dist/openai/index.js +3 -3
  223. package/dist/openapi/index.d.ts +61 -30
  224. package/dist/openapi/index.js +2 -2
  225. package/dist/{openapi-B7HZ0f-r.js → openapi-BOsx0xn9.js} +34 -24
  226. package/dist/{openapi-C4dDTVEd.js → openapi-CBZUhA3l.js} +4 -5
  227. package/dist/{openapi-DD1SV-5-.js → openapi-VeHHU2l9.js} +23 -14
  228. package/dist/{operation-findings-DgATDpvh.js → operation-findings-CXtFzlKJ.js} +3 -3
  229. package/dist/{operations-X0VM7F3m.d.ts → operations-Ci_rT6Uo.d.ts} +10 -7
  230. package/dist/orpc/index.d.ts +68 -14
  231. package/dist/orpc/index.js +62 -13
  232. package/dist/otel/index.d.ts +7 -4
  233. package/dist/otel/index.js +8 -5
  234. package/dist/output-files-BHOIlrfD.js +1 -0
  235. package/dist/{output-files-DhRBBE4n.js → output-files-BIQ_9pIs.js} +29 -17
  236. package/dist/{output-1im__-08.js → output-tkju6U7R.js} +15 -7
  237. package/dist/ownership-B4L59T9u.js +1054 -0
  238. package/dist/parse-1_ZheTW5.js +151 -0
  239. package/dist/parse-local-manifest-BQhTlLQS.d.ts +10 -0
  240. package/dist/parse-local-manifest-DEiCF4ah.js +69 -0
  241. package/dist/{parse-request-D_tUXG6M.js → parse-request-CwCZpyjV.js} +7 -8
  242. package/dist/{paths-DXSHAMIa.js → paths-CUvURzHp.js} +4 -1
  243. package/dist/pdp/index.d.ts +9 -6
  244. package/dist/pdp/index.js +23 -12
  245. package/dist/{peer-CRvC7Hg1.js → peer-C9LvBCcb.js} +1 -1
  246. package/dist/peer-Q0fuZ6hx.js +982 -0
  247. package/dist/{permdock-SV8ZINYT.d.ts → permdock-B6Sf4T_S.d.ts} +270 -117
  248. package/dist/{permdock-BrAscV28.js → permdock-L-_I_3zP.js} +226 -74
  249. package/dist/{permission-registry-Br4jSNVi.js → permission-registry-B8tYxPIt.js} +24 -11
  250. package/dist/{vocabulary-CN8H_9UF.d.ts → permission-types-CAY-GU7e.d.ts} +130 -104
  251. package/dist/{permissions-u_KHg-sN.d.ts → permissions-Bx6UI8n1.d.ts} +6 -2
  252. package/dist/{permissions-B-wCP5ZC.js → permissions-CVXmRILq.js} +3 -3
  253. package/dist/{permissions-BPxlwVhN.js → permissions-mDcTWoBs.js} +8 -5
  254. package/dist/pg-DQTqRrou.js +60 -0
  255. package/dist/{pins-8ILTftC9.js → pins-nqarl3oE.js} +4 -1
  256. package/dist/pkce-CnmmYqUZ.js +21 -0
  257. package/dist/{policy-77FSAq_V.d.ts → policy-Ba4bDhaj.d.ts} +5 -5
  258. package/dist/{policy-DbM5YYtV.js → policy-CLQ8__GF.js} +49 -20
  259. package/dist/{policy-from-catalog-C2gMa2Dj.js → policy-from-catalog-CJgOm6aq.js} +28 -25
  260. package/dist/{policy-module-CTlwMvLI.js → policy-module-xym9fnSq.js} +12 -6
  261. package/dist/{policy-types-n0uRTsW8.d.ts → policy-types-CCiDRZBH.d.ts} +802 -334
  262. package/dist/postgres-store-DcyrPS-r.js +1028 -0
  263. package/dist/{postgrest-DAjUkF9w.js → postgrest-D4nuPXIQ.js} +88 -36
  264. package/dist/{postgrest-CEgRbefE.d.ts → postgrest-DicQyqm-.d.ts} +60 -30
  265. package/dist/powersync-DHNQX06W.js +1117 -0
  266. package/dist/{powersync-DISt6SUe.js → powersync-DXqGuq9A.js} +3 -3
  267. package/dist/powersync-Djf-zCpB.js +1 -0
  268. package/dist/preset/index.d.ts +38 -28
  269. package/dist/preset/index.js +1 -1
  270. package/dist/{preset-DZdU0tne.js → preset-BjLzeFpp.js} +58 -34
  271. package/dist/{principal-source-pHneukrx.js → principal-source-C6N60GtM.js} +10 -10
  272. package/dist/prisma/index.d.ts +69 -41
  273. package/dist/prisma/index.js +21 -17
  274. package/dist/{problem-CTviyH5L.js → problem-BVLHFK33.js} +41 -21
  275. package/dist/{problem-details-cn5X30gZ.js → problem-details-CLDgX1KV.js} +13 -4
  276. package/dist/{problem-types-CJ2325SZ.js → problem-types-DSsRfONQ.js} +4 -1
  277. package/dist/prompt-BYc6drYW.js +938 -0
  278. package/dist/protected-action-BE7N_Luo.d.ts +58 -0
  279. package/dist/protected-action-DUYqb-Ma.js +80 -0
  280. package/dist/{protected-BlF0F6wL.js → protected-action-QEA8arRB.js} +48 -14
  281. package/dist/{provider-B1al-AZz.js → provider-C55OGXJ7.js} +5 -4
  282. package/dist/{provider-DILL9oPK.d.ts → provider-DXfq5c2d.d.ts} +1 -1
  283. package/dist/{provider-store-DM6DNcta.js → provider-store-CaTv00tr.js} +13 -9
  284. package/dist/pull-B65ndFNZ.js +1 -0
  285. package/dist/{pull-jEwbf80J.js → pull-CwpGaQSi.js} +12 -11
  286. package/dist/{push-BD4f15co.js → push-DgssgzkK.js} +62 -16
  287. package/dist/{pushed-policy-DCW91KQU.d.ts → pushed-policy-D1Eoi6NM.d.ts} +12 -6
  288. package/dist/{pushed-policy-CqtxkV4G.js → pushed-policy-ITwYKvvH.js} +10 -7
  289. package/dist/react/index.d.ts +9 -8
  290. package/dist/react/index.js +7 -6
  291. package/dist/react/provider-client.d.ts +1 -1
  292. package/dist/react/provider-client.js +1 -1
  293. package/dist/react-native/index.d.ts +104 -51
  294. package/dist/react-native/index.js +394 -67
  295. package/dist/{refs-K6eWUJ0H.js → refs-C8BKxc_e.js} +17 -3
  296. package/dist/{relation-walk-3OyDBF0S.js → relation-walk-DK_gkgL7.js} +12 -9
  297. package/dist/{relations-BnCWnJGI.js → relations-BxvRvDHK.js} +3 -3
  298. package/dist/{replay-Du1tJjG7.js → replay-BU09ad4L.js} +1 -1
  299. package/dist/{replay-Bkm-Ne4l.d.ts → replay-DNftIb_R.d.ts} +1 -1
  300. package/dist/{request-context-C81Pip9n.js → request-context-C25ilqiJ.js} +8 -8
  301. package/dist/{request-schema-CMreVuFM.js → request-schema-DhX7UbfQ.js} +4 -1
  302. package/dist/resend/index.d.ts +34 -28
  303. package/dist/resend/index.js +29 -29
  304. package/dist/resolve-names-CF7xXLSG.js +201 -0
  305. package/dist/{resource-relations-D_jw0BFx.js → resource-relations-8-pCScBO.js} +18 -9
  306. package/dist/{retire-CALjIQ7e.js → retire-B2xffQgY.js} +15 -6
  307. package/dist/{revocations-R07lFBnX.d.ts → revocations-BaUXHM1N.d.ts} +6 -3
  308. package/dist/{rls-DTvYd-lI.js → rls-CNEH2_BG.js} +743 -624
  309. package/dist/{rls-BAqP4q66.js → rls-Ca8Jz9b5.js} +41 -10
  310. package/dist/{role-builder-uWQZ4v84.js → role-builder-BK2-T6oD.js} +41 -20
  311. package/dist/rolldown-runtime-C3I60J0A.js +4 -0
  312. package/dist/{row-conditions-h2HythXQ.js → row-conditions-BAGHOmVq.js} +4 -3
  313. package/dist/{rpc-VSl5ylaQ.js → rpc-fNqAIqQk.js} +8 -5
  314. package/dist/{run-CUKuz0A8.js → run-Bz26OTfO.js} +26 -23
  315. package/dist/run-D-JE8QWb.js +1 -0
  316. package/dist/{run-ticket-DocwaTKn.d.ts → run-ticket-DbWI9f99.d.ts} +33 -13
  317. package/dist/{run-ticket-sxFI6LAk.js → run-ticket-Dv7aF7Dk.js} +29 -8
  318. package/dist/{runtime-D3VTAiCA.js → runtime-BGnrOkVH.js} +5 -2
  319. package/dist/{saas-BCXRuXca.js → saas-iWnUdwCt.js} +42 -29
  320. package/dist/{scan-qvOe0hS3.js → scan-DCj1KQfn.js} +1 -1
  321. package/dist/{schema-B4v0Qrac.js → schema-BOJjqlWL.js} +3 -2
  322. package/dist/{schema-yLuBWWsh.js → schema-Dst9I9Gs.js} +9 -5
  323. package/dist/scim/index.d.ts +3 -2
  324. package/dist/scim/index.js +3 -1
  325. package/dist/scim-D8YupzX1.js +44 -0
  326. package/dist/{scim-ClHtpyV3.js → scim-jJBJ7g1Z.js} +35 -551
  327. package/dist/{scopes-CUPSjo9q.js → scopes-0Up_UA2t.js} +42 -24
  328. package/dist/server/index.d.ts +12 -12
  329. package/dist/server/index.js +13 -13
  330. package/dist/{server-C3WXAHZj.js → server-3cVlTLde.js} +31 -31
  331. package/dist/{server-types-CKQiCnON.d.ts → server-types-CIlpSA2G.d.ts} +81 -46
  332. package/dist/{sha256-D9ihqmvd.js → sha256-C-4WXKIu.js} +4 -3
  333. package/dist/{shared-BAK8t4Uo.js → shared-Afctg7B0.js} +100 -61
  334. package/dist/{shared-DvvFzYXe.js → shared-l0oGGetg.js} +9 -6
  335. package/dist/{signals-D3NcTKUS.js → signals-B1vHR3fN.js} +2 -2
  336. package/dist/{sink-BEZSlMS_.js → sink-D9_vh372.js} +32 -21
  337. package/dist/{sink-4-eQIRWf.d.ts → sink-Dvi7YZG_.d.ts} +44 -20
  338. package/dist/{skills-B6lVdD_W.js → skills-Bjj7BNEQ.js} +16 -12
  339. package/dist/{skills-CTYwkl44.js → skills-OuoMR49L.js} +3 -3
  340. package/dist/{snapshot-B7DkYg6g.js → snapshot-CXlzi69u.js} +21 -18
  341. package/dist/{snapshot-cache-PXI-vGpY.d.ts → snapshot-cache-BAXZ0KOp.d.ts} +21 -12
  342. package/dist/{snapshot-cache-DZHQ0KF6.js → snapshot-cache-Bx_4xC_6.js} +14 -11
  343. package/dist/solid/index.d.ts +55 -15
  344. package/dist/solid/index.js +46 -12
  345. package/dist/solid-start/index.d.ts +30 -12
  346. package/dist/solid-start/index.js +3 -3
  347. package/dist/sources-B1Os_YUu.d.ts +312 -0
  348. package/dist/{sources-vs5dGOsS.js → sources-CMAM-2A3.js} +156 -51
  349. package/dist/sources-qoIJQrJv.js +11 -0
  350. package/dist/{sql-B5T1IL83.js → sql-0WjxIp9g.js} +32 -7
  351. package/dist/sql-B80DFdpG.d.ts +10 -0
  352. package/dist/{src-Cu2m75uo.js → src-DZ0l9UAg.js} +305 -123
  353. package/dist/ssf/index.d.ts +4 -4
  354. package/dist/ssf/index.js +665 -224
  355. package/dist/{standard-webhooks-rbD7LS6h.d.ts → standard-webhooks-C-qX4mJW.d.ts} +7 -7
  356. package/dist/{standard-webhooks-DgFFD-Ga.js → standard-webhooks-D67a3nzk.js} +5 -5
  357. package/dist/{store-BDutJkDL.js → store-RNFvaJJv.js} +43 -29
  358. package/dist/{store-options-u0ycEe8s.js → store-options-Dil3lraY.js} +105 -15
  359. package/dist/stores-C0Kta5Ft.d.ts +59 -0
  360. package/dist/{stores-CGhM8BN_.js → stores-DxZWDXCs.js} +42 -5
  361. package/dist/{stream-CvdUS9V1.js → stream-CDvF0sJm.js} +5 -5
  362. package/dist/{stream-CeCMJmBB.d.ts → stream-ltuLdtTG.d.ts} +4 -3
  363. package/dist/{style-DiKWnAvn.js → style-DblOtSga.js} +1 -1
  364. package/dist/{style-Uao76wO7.js → style-Ds11Hmk4.js} +3 -1
  365. package/dist/{subject-settings-CkEwrw3W.js → subject-settings-8sH5HlII.js} +8 -4
  366. package/dist/{row-check-Dt35czLy.d.ts → subject-settings-vNW8qmUH.d.ts} +30 -18
  367. package/dist/supabase/index.d.ts +48 -37
  368. package/dist/supabase/index.js +6 -6
  369. package/dist/supabase/middleware.d.ts +19 -13
  370. package/dist/supabase/middleware.js +7 -7
  371. package/dist/{supabase-x5JtR2tc.js → supabase-BL1qJzzY.js} +82 -36
  372. package/dist/{supabase-By_frk3U.js → supabase-D39cuGPt.js} +3 -3
  373. package/dist/{supabase-hook-BMoEhZir.js → supabase-hook-B-yXnzUl.js} +1206 -286
  374. package/dist/supabase-hook-H-MtE9Wd.js +1 -0
  375. package/dist/supautils-BU-pAEpf.js +808 -0
  376. package/dist/{support-session-C6xJQYut.js → support-session-BsmPCbz8.js} +22 -22
  377. package/dist/svelte/PermissionBoundary.svelte +2 -6
  378. package/dist/svelte/Protected.svelte +2 -8
  379. package/dist/svelte/index.d.ts +9 -8
  380. package/dist/svelte/index.js +10 -9
  381. package/dist/svelte/runtime.d.ts +4 -4
  382. package/dist/svelte/runtime.js +4 -4
  383. package/dist/svelte/source.d.ts +9 -8
  384. package/dist/svelte/source.js +6 -5
  385. package/dist/sveltekit/index.d.ts +30 -12
  386. package/dist/sveltekit/index.js +2 -2
  387. package/dist/{ownership-DqaJNJPn.js → tables-DeMNEy6V.js} +1025 -1085
  388. package/dist/tanstack-start/index.d.ts +22 -10
  389. package/dist/tanstack-start/index.js +2 -2
  390. package/dist/{target-Bw37TFNA.js → target-qdEAnnhU.js} +6 -6
  391. package/dist/{tenancy-DN2QAx9z.js → tenancy-5d1zVBvK.js} +36 -21
  392. package/dist/terminal/index.d.ts +23 -14
  393. package/dist/terminal/index.js +17 -20
  394. package/dist/testing/core.d.ts +2 -0
  395. package/dist/testing/core.js +1 -0
  396. package/dist/testing/fixtures/index.d.ts +15 -0
  397. package/dist/testing/fixtures/index.js +831 -0
  398. package/dist/testing/index.d.ts +235 -285
  399. package/dist/testing/index.js +502 -927
  400. package/dist/testing/saas/index.d.ts +43 -27
  401. package/dist/testing/saas/index.js +2 -2
  402. package/dist/testing/saas/permissions.d.ts +1 -1
  403. package/dist/testing/saas/permissions.js +1 -1
  404. package/dist/text-diff-BtfSmdUo.js +444 -0
  405. package/dist/{thenable-yD7SabqG.js → thenable-BNSM1U2R.js} +12 -3
  406. package/dist/{time-DkWjdL98.js → time-nR1JesoH.js} +32 -8
  407. package/dist/{token-BLZcjQgt.js → token-DC9EQiet.js} +15 -13
  408. package/dist/{tool-refusal-CMLN5xhn.js → tool-refusal-Qpjs_W6M.js} +5 -2
  409. package/dist/trpc/index.d.ts +11 -8
  410. package/dist/trpc/index.js +15 -9
  411. package/dist/type-helpers-BIPIDa6a.d.ts +50 -0
  412. package/dist/{types-8RnwUAvE.d.ts → types-AMJ5qoU_.d.ts} +49 -30
  413. package/dist/{types-C_IiEs64.d.ts → types-B2mlGuhW.d.ts} +14 -11
  414. package/dist/{types-_WhUP7ud.d.ts → types-B4uqKDnp.d.ts} +25 -12
  415. package/dist/{types-CX7AvRqP.d.ts → types-BJk0BKRX.d.ts} +24 -14
  416. package/dist/types-B_d_g7T3.d.ts +262 -0
  417. package/dist/{types-BdtSDbBO.d.ts → types-B_tiYvk8.d.ts} +59 -32
  418. package/dist/{types-DqzsnlSA.js → types-CcUXciSj.js} +17 -5
  419. package/dist/{types-Dfv0aTER.d.ts → types-DC1Loeh3.d.ts} +449 -168
  420. package/dist/{types-lUlG3TVd.d.ts → types-DHKPcqzr.d.ts} +2 -2
  421. package/dist/{types-C791HFu9.d.ts → types-DjuMBNF9.d.ts} +68 -32
  422. package/dist/{types-C863OQiR.d.ts → types-HzqOtvsJ.d.ts} +23 -12
  423. package/dist/{types-Druu9wLM.d.ts → types-ZzRGoViD.d.ts} +77 -24
  424. package/dist/{types-BzzaHxt3.d.ts → types-ah9NlU6j.d.ts} +137 -48
  425. package/dist/{types-CVZSNocA.d.ts → types-djVzLlIV.d.ts} +31 -14
  426. package/dist/{types-BtHtcKMr.d.ts → types-yUuPR5Hy.d.ts} +47 -24
  427. package/dist/unplugin/index.d.ts +1 -1
  428. package/dist/unplugin/index.js +2 -2
  429. package/dist/usage-CYeXek0p.js +1 -0
  430. package/dist/{usage-SveTRTyr.js → usage-CxEzS4ey.js} +50 -26
  431. package/dist/{usage-CRVl9V3t.js → usage-ab0PdusX.js} +2 -2
  432. package/dist/{validation-error-ZfUHbKvf.js → validation-error-CYg2kJEw.js} +4 -1
  433. package/dist/{validation-error-DHUrAkku.d.ts → validation-error-YGg2mXyH.d.ts} +5 -2
  434. package/dist/{validity-CZ7-y0Cj.js → validity-Buc7w8E9.js} +13 -10
  435. package/dist/{verifier-DHuh-okk.js → verifier-DUV6pLqZ.js} +10 -4
  436. package/dist/{verify-BaAKx7t6.js → verify-DZeqoWu5.js} +417 -489
  437. package/dist/version-DMQ0dnN5.js +48 -0
  438. package/dist/version-DizhmD72.js +1 -0
  439. package/dist/{views-DTIIO-oQ.js → views-CD8wuL4Z.js} +19 -6
  440. package/dist/vocabulary-DEJ5j4mR.d.ts +70 -0
  441. package/dist/vue/index.d.ts +71 -21
  442. package/dist/vue/index.js +50 -13
  443. package/dist/{waiter-B986w1oK.d.ts → waiter-Bu9zAlE0.d.ts} +13 -10
  444. package/dist/{waiter-BGUtGYoU.js → waiter-aBLM63_f.js} +1 -1
  445. package/dist/{watch-vea54PRw.js → watch-Cx_WciLE.js} +8 -8
  446. package/dist/watch-DB42U1ib.js +1 -0
  447. package/dist/webmcp/index.d.ts +11 -11
  448. package/dist/webmcp/index.js +8 -5
  449. package/dist/{where-scope-C9vfEphl.js → where-scope-DlCdCM_8.js} +56 -30
  450. package/dist/{who-can-DWBAcaCQ.js → who-can-rI7dCR9Q.js} +23 -20
  451. package/dist/workflow/index.d.ts +3 -3
  452. package/dist/workflow/index.js +13 -13
  453. package/dist/workflow-sdk/index.d.ts +19 -13
  454. package/dist/workflow-sdk/index.js +6 -6
  455. package/dist/{wrap-gX61EtpB.js → wrap-B2wziJI_.js} +11 -5
  456. package/dist/{wrap-C5jC6sKI.d.ts → wrap-DlJE3gS_.d.ts} +8 -5
  457. package/package.json +25 -14
  458. package/schemas/catalog-v1.json +3 -0
  459. package/schemas/cli-result-v1.json +1 -0
  460. package/schemas/cloud-api-v1.json +152 -7
  461. package/schemas/connector-v1.json +8 -0
  462. package/schemas/supabase-claims-v1.json +5 -0
  463. package/schemas/supabase-manifest-v1.json +308 -75
  464. package/skills/permdock/SKILL.md +1 -0
  465. package/skills/permdock-agents/references/runtimes.md +3 -1
  466. package/skills/permdock-approvals/references/stores-and-resume.md +2 -1
  467. package/skills/permdock-credentials/references/tokens-keys-links.md +8 -6
  468. package/skills/permdock-data/references/queries-and-rls.md +6 -2
  469. package/skills/permdock-tenancy/SKILL.md +1 -1
  470. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +2 -1
  471. package/skills/permdock-wire/references/adapters.md +28 -22
  472. package/skills/permdock-wire/references/policy-options.md +1 -0
  473. package/dist/catalog-BoWglDPI.js +0 -1
  474. package/dist/collect-D7eQDffE.js +0 -1
  475. package/dist/config-bs_kZeYq.js +0 -162
  476. package/dist/denied-text-CiFQNuMV.d.ts +0 -19
  477. package/dist/fields-OYG_JR78.js +0 -203
  478. package/dist/generate-CNU1pIOo.js +0 -171
  479. package/dist/headers-BIjfMaoC.js +0 -8
  480. package/dist/headers-CIbDTUTK.d.ts +0 -7
  481. package/dist/index-Cp_ilKi1.d.ts +0 -91
  482. package/dist/index-CueFnxQc.d.ts +0 -110
  483. package/dist/load-BxEtwlBS.js +0 -1
  484. package/dist/output-files-B3IZJksC.js +0 -1
  485. package/dist/package-root-Dk_ETdkp.js +0 -31
  486. package/dist/parse-Cxq0WxrA.js +0 -53
  487. package/dist/parse-local-manifest-5ODwqu8b.d.ts +0 -10
  488. package/dist/parse-local-manifest-CVSs6J9I.js +0 -34
  489. package/dist/peer-C8swJ2GH.js +0 -50
  490. package/dist/policies-DP2nqRoF.js +0 -295
  491. package/dist/powersync-BkWWCS1K.js +0 -538
  492. package/dist/powersync-MMJ2mI2q.js +0 -1
  493. package/dist/problem-details-B45V5d2b.d.ts +0 -7
  494. package/dist/prompt-DfZLJLIn.js +0 -32
  495. package/dist/protected-RFGpakN9.d.ts +0 -38
  496. package/dist/pull-CvpINcMK.js +0 -1
  497. package/dist/run-DDwUaJDU.js +0 -1
  498. package/dist/sources-Xc4zkszI.d.ts +0 -190
  499. package/dist/stores-BUGNbJTt.d.ts +0 -30
  500. package/dist/supabase-hook-CCw5m35C.js +0 -1
  501. package/dist/supautils-B6HYL9eL.js +0 -91
  502. package/dist/text-diff-BQcUapOb.js +0 -15
  503. package/dist/types-B3_ooZgZ.d.ts +0 -172
  504. package/dist/usage-CZpSQP6L.js +0 -1
  505. package/dist/version-CEbQ5UeM.js +0 -18
  506. package/dist/version-DXkYUISx.js +0 -1
  507. package/dist/watch--ovlPOc0.js +0 -1
@@ -0,0 +1,1054 @@
1
+ import { a as sole, n as isReadonlyArray, r as isRecord } from "./compact-CAf557ZB.js";
2
+ import { n as isForbiddenKey } from "./paths-CUvURzHp.js";
3
+ import { u as isSqlFunctionField } from "./refs-C8BKxc_e.js";
4
+ import { u as isoAt } from "./time-nR1JesoH.js";
5
+ import { f as scopeList, l as rootScope, s as resolveScope, u as scopeChain } from "./scopes-0Up_UA2t.js";
6
+ import { t as isoInstant } from "./instant-DK3Iz83e.js";
7
+ import { m as findRole, v as listRoles } from "./grantee-Dke-9rd1.js";
8
+ import { r as relationCondition, t as inheritCondition } from "./grantee-conditions-BrYPe-w0.js";
9
+ import { i as configError } from "./errors-Vpu6rKHl.js";
10
+ import { i as qualifySqlTable } from "./sql-0WjxIp9g.js";
11
+ import { a as scopeMembershipTable, i as scopeColumn, s as relatedSql } from "./compile-EzEMB-7v.js";
12
+ import { l as roleColumn } from "./sources-CMAM-2A3.js";
13
+ import { A as quoteQualified, D as qualified, E as helperSchema, L as sqlType, M as textArrayLiteral, O as quoteIdent, R as tenantTypeOf, S as CLAIM, T as declaredArray, _ as subjectClaimJsonSql, b as tenantClaimSql, d as keyTenantSql, f as kindFilterSql, h as roleKindSql, j as quoteTable, k as quoteLiteral, m as memberVia, p as liveSessionSql, s as signedIn, t as CUSTOM_ROLES, u as globalKindFilterSql, v as subjectClaimSql, y as subjectIdSql } from "./shared-Afctg7B0.js";
14
+ import { $ as graphSqlText, A as claimKeptLines, B as hasCustomRoleChecksFor, F as globalRoleRows, I as membershipRows, L as roleRows, M as memberColumn, N as sourceFilters, P as sourcesKeep, U as storedTenant, X as CLOSURE, Z as graphHelper, _t as activeMembershipSql, c as holderSources, ct as memberIdsHelper, d as sourceRowsSql, f as sourceTransferTriggerSql, g as OWNERSHIP, gt as activeInstancesSql, h as ASSIGNMENTS, ht as scopeTable, it as linkHelper, j as disabledColumn, l as pairsSql, m as transferTriggerSql, mt as scopeSources, nt as inheritedRowsHelper, p as holdersTriggerSql, pt as restrictedHelper, st as memberForTable, u as sourceHoldersTriggerSql, ut as memberRoleOf, yt as activeUserSql } from "./tables-DeMNEy6V.js";
15
+ //#region src/cli/sql/conditions.ts
16
+ const MAX_CLAIM_DEPTH = 8;
17
+ /**
18
+ * The claim path of a `principal.claim.*` / `principal.claims.*` ref, one
19
+ * segment per JSON key; `undefined` for any other ref.
20
+ */
21
+ function claimPath(ref) {
22
+ const prefix = ["principal.claim.", "principal.claims."].find((item) => ref.startsWith(item));
23
+ if (prefix === void 0) return;
24
+ const segments = ref.slice(prefix.length).split(".");
25
+ if (segments.length > MAX_CLAIM_DEPTH) throw configError(`PermDock CLI: claim path '${ref}' is deeper than ${MAX_CLAIM_DEPTH}`);
26
+ for (const segment of segments) if (!CLAIM.test(segment) || isForbiddenKey(segment)) throw configError(`PermDock CLI: unsafe claim name '${segment}'`);
27
+ return segments;
28
+ }
29
+ function jsonPath(base, keys, last) {
30
+ let sql = base;
31
+ for (const [index, key] of keys.entries()) sql += ` ${index === keys.length - 1 ? last : "->"} ${quoteLiteral(key)}`;
32
+ return sql;
33
+ }
34
+ /**
35
+ * The JSON document a claim path starts from and the keys to walk in it. The
36
+ * `guc` dialect keeps each top-level claim in its own setting as JSON text.
37
+ */
38
+ function claimRoot(ctx, path) {
39
+ const [head, ...rest] = path;
40
+ if (head === void 0) throw configError("PermDock CLI: empty claim path");
41
+ switch (ctx.dialect) {
42
+ case "supabase": return {
43
+ root: "(select auth.jwt())",
44
+ keys: path
45
+ };
46
+ case "neon": return {
47
+ root: "(select auth.session())",
48
+ keys: path
49
+ };
50
+ case "guc": return {
51
+ root: subjectClaimJsonSql(ctx, head),
52
+ keys: rest
53
+ };
54
+ default: return ctx.dialect;
55
+ }
56
+ }
57
+ /** The claim at `path` as `jsonb`. */
58
+ function claimJsonSql(ctx, path) {
59
+ const { root, keys } = claimRoot(ctx, path);
60
+ return keys.length === 0 ? root : `(${jsonPath(root, keys, "->")})`;
61
+ }
62
+ /**
63
+ * The claim at `path` as text: `->>` on the last key, or the plain setting for
64
+ * a one-segment `guc` claim.
65
+ */
66
+ function claimTextSql(ctx, path) {
67
+ const [head] = path;
68
+ if (path.length === 1 && head !== void 0) return subjectClaimSql(ctx, head);
69
+ const { root, keys } = claimRoot(ctx, path);
70
+ return `(${jsonPath(root, keys, "->>")})`;
71
+ }
72
+ /** The JSON kind a claim must have to compare with a column of `type`. */
73
+ function jsonKindOf(type) {
74
+ if (type === "numeric") return "number";
75
+ return type === "boolean" ? "boolean" : "string";
76
+ }
77
+ /**
78
+ * A claim compared with a column of `type`. Numbers and booleans must be JSON
79
+ * of that kind (anything else is `null`, so the comparison is false, as in
80
+ * memory); other types cast the text form. A one-segment `guc` claim is text
81
+ * and is cast as is.
82
+ */
83
+ function typedClaimSql(ctx, path, type) {
84
+ const text = claimTextSql(ctx, path);
85
+ if (type === void 0 || type === "text") return text;
86
+ const cast = `${text}::${sqlType(type)}`;
87
+ const kind = jsonKindOf(type);
88
+ if (kind === "string" || ctx.dialect === "guc" && path.length === 1) return `(${cast})`;
89
+ return `(case when jsonb_typeof(${claimJsonSql(ctx, path)}) = '${kind}' then ${cast} end)`;
90
+ }
91
+ /**
92
+ * The elements of an array claim as a Postgres array of the column's type,
93
+ * built once per statement (an uncorrelated `array(select ...)` is an
94
+ * InitPlan). A missing or non-array claim is the empty array; elements of
95
+ * another JSON kind are left out.
96
+ */
97
+ function claimArraySql(ctx, path, type) {
98
+ const json = claimJsonSql(ctx, path);
99
+ return `array(select ${type === void 0 || type === "text" ? `(e #>> '{}')` : `(e #>> '{}')::${sqlType(type)}`} from jsonb_array_elements(case when jsonb_typeof(${json}) = 'array' then ${json} else '[]'::jsonb end) e where jsonb_typeof(e) = '${jsonKindOf(type)}')`;
100
+ }
101
+ function sqlValue(value, ctx, field) {
102
+ if (value !== null && typeof value === "object" && "ref" in value) return compileRef(value.ref, ctx, field);
103
+ if (value !== null && typeof value === "object" && "date" in value) {
104
+ const instant = isoInstant(value.date);
105
+ return instant === void 0 ? "null" : quoteLiteral(isoAt(instant));
106
+ }
107
+ if (isReadonlyArray(value)) return `array[${value.map((item) => sqlValue(item, ctx)).join(", ")}]`;
108
+ if (value === null) return "null";
109
+ if (typeof value === "boolean") return value ? "true" : "false";
110
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "null";
111
+ if (typeof value === "string") return quoteLiteral(value);
112
+ throw configError("PermDock CLI: non-portable condition value");
113
+ }
114
+ function compileRef(ref, ctx, field) {
115
+ if (ref === "principal.id") return subjectIdSql(ctx);
116
+ if (ref === "now") return "now()";
117
+ const path = claimPath(ref);
118
+ if (ref === "principal.tenant" || path?.length === 1 && path[0] === ctx.tenantClaim) return tenantClaimSql(ctx);
119
+ if (path !== void 0) return typedClaimSql(ctx, path, field === void 0 ? void 0 : ctx.columnTypes?.[field]);
120
+ if (ref === "context" || ref.startsWith("context.")) throw configError(`PermDock CLI: '${ref}' is request context, which is not in the token; RLS cannot read it (permdock doctor PD027)`);
121
+ throw configError(`PermDock CLI: non-portable subject ref '${ref}'`);
122
+ }
123
+ /**
124
+ * `value` with `\`, `%` and `_` escaped for `like ... escape '\'`, as
125
+ * `escapeLike` does in process.
126
+ */
127
+ function likeLiteralSql(value) {
128
+ return `replace(replace(replace(${value}, '\\', '\\\\'), '%', '\\%'), '_', '\\_')`;
129
+ }
130
+ function compareSql(op, field, value) {
131
+ const left = quoteIdent(field);
132
+ switch (op) {
133
+ case "eq": return `${left} = ${value}`;
134
+ case "ne": return `${left} <> ${value}`;
135
+ case "gt": return `${left} > ${value}`;
136
+ case "gte": return `${left} >= ${value}`;
137
+ case "lt": return `${left} < ${value}`;
138
+ case "lte": return `${left} <= ${value}`;
139
+ case "contains": return `${left}::text like '%' || ${likeLiteralSql(`${value}::text`)} || '%' escape '\\'`;
140
+ default: return op;
141
+ }
142
+ }
143
+ /**
144
+ * Whether the row's `rowField` is among the ids in `table.rowColumn` the
145
+ * subject holds a matching membership on. The row field stays outside the
146
+ * subquery: inside it, an unqualified name resolves to the membership table
147
+ * first, so `m.org_id = "org_id"` would compare the membership with itself.
148
+ */
149
+ function membershipSql(table, rowColumn, rowField, roles, ctx, tenantColumn, scope) {
150
+ const parts = [`m.${quoteIdent(table.user)} = ${subjectIdSql(ctx)}`];
151
+ const role = memberRoleOf(table);
152
+ if (roles.length > 0) {
153
+ const held = role.through === void 0 && !role.lateral ? `m.${quoteIdent(role.column)}` : role.lookup;
154
+ parts.push(`${held} = any(${textArrayLiteral(roles)})`);
155
+ const via = memberVia(table);
156
+ const single = sole(roles);
157
+ const kind = single === void 0 ? kindFilterSql(ctx, role.lookup, via) : roleKindSql(ctx, single, via);
158
+ if (kind !== void 0) parts.push(kind);
159
+ }
160
+ if (table.expiresAt !== void 0) parts.push(`(m.${quoteIdent(table.expiresAt)} is null or m.${quoteIdent(table.expiresAt)} > now())`);
161
+ parts.push(...activeMembershipSql(ctx, table.disabledAt === void 0 ? void 0 : `m.${quoteIdent(table.disabledAt)}`));
162
+ if (tenantColumn !== void 0 && ctx.tenants !== "all") parts.push(`m.${quoteIdent(tenantColumn)} = ${tenantClaimSql(ctx)}`);
163
+ parts.push(...activeUserSql(ctx));
164
+ if (scope !== void 0) {
165
+ const tenantOf = scope === rootScope(ctx.scopes) ? rowColumn : tenantColumn;
166
+ const keyed = keyTenantSql(ctx, tenantOf === void 0 ? void 0 : `m.${quoteIdent(tenantOf)}`);
167
+ if (keyed !== void 0) parts.push(keyed);
168
+ parts.push(...activeInstancesSql(ctx, scope, (name) => {
169
+ const held = scopeColumn(table, ctx.scopes, name);
170
+ return held === void 0 ? void 0 : `m.${quoteIdent(held)}`;
171
+ }));
172
+ }
173
+ const expand = roles.length > 0 && role.lateral ? role.join : "";
174
+ return `${quoteIdent(rowField)} in (select m.${quoteIdent(rowColumn)} from ${quoteTable(table.table)} m${expand} where ${parts.join(" and ")})`;
175
+ }
176
+ function compileMemberOf(condition, ctx) {
177
+ const scope = condition.scope === "resource" ? void 0 : resolveScope(ctx.scopes, condition.scope);
178
+ if (condition.scope !== "resource" && scope === void 0) throw configError(`PermDock CLI: memberOf ${condition.scope} names a scope the policy does not declare`);
179
+ const mapping = scope === void 0 ? condition.resource === void 0 ? void 0 : ctx.memberships?.resource?.[condition.resource] : scopeMembershipTable(ctx.memberships, ctx.scopes, scope);
180
+ if (mapping !== void 0) {
181
+ const named = scope === void 0 ? void 0 : scopeTable(ctx, scope);
182
+ const rowColumn = scope === void 0 ? mapping.id : named?.column;
183
+ if (rowColumn === void 0) throw configError(`PermDock CLI: memberships mapping for ${condition.scope} is missing the row column`);
184
+ const tenantColumn = scope === void 0 || scope === rootScope(ctx.scopes) ? void 0 : named?.tenantColumn;
185
+ const primary = membershipSql(mapping, rowColumn, condition.field, condition.roles, ctx, tenantColumn, scope);
186
+ if (condition.scope !== "resource" || condition.parents === void 0) return primary;
187
+ return `(${[primary, ...condition.parents.flatMap((parent) => {
188
+ if (typeof parent === "string") return [membershipSql(mapping, rowColumn, parent, condition.roles, ctx, tenantColumn)];
189
+ const hopTable = ctx.memberships?.resource?.[parent.resource];
190
+ return hopTable?.id === void 0 ? [] : [membershipSql(hopTable, hopTable.id, parent.field, condition.roles, ctx)];
191
+ })].join(" or ")})`;
192
+ }
193
+ if (scope !== void 0 && condition.roles.length === 0 && scopeSources(ctx, scope).length > 0) return `${quoteIdent(condition.field)} in (select ${qualified(ctx, memberIdsHelper(scope))}())`;
194
+ if (scope !== void 0 && scope === rootScope(ctx.scopes)) {
195
+ const parts = [
196
+ ctx.tenants === "all" ? `${quoteIdent(condition.field)} in (select ${qualified(ctx, memberIdsHelper(scope))}())` : `${quoteIdent(condition.field)} = ${tenantClaimSql(ctx)}`,
197
+ ...ctx.tenants === "all" ? [] : [keyTenantSql(ctx, quoteIdent(condition.field))].filter((part) => part !== void 0),
198
+ ...activeUserSql(ctx),
199
+ ...activeInstancesSql(ctx, scope, () => quoteIdent(condition.field))
200
+ ];
201
+ return parts.length === 1 ? parts.join("") : `(${parts.join(" and ")})`;
202
+ }
203
+ throw configError(`PermDock CLI: memberOf ${condition.scope} needs a memberships table mapping`);
204
+ }
205
+ function compileConditionSql(condition, ctx) {
206
+ switch (condition.op) {
207
+ case "eq":
208
+ case "ne":
209
+ case "gt":
210
+ case "gte":
211
+ case "lt":
212
+ case "lte": return compareSql(condition.op, condition.field, sqlValue(condition.value, ctx, condition.field));
213
+ case "contains": {
214
+ const element = ctx.arrayColumns?.[condition.field];
215
+ if (element !== void 0) return `${sqlValue(condition.value, {
216
+ ...ctx,
217
+ columnTypes: {
218
+ ...ctx.columnTypes,
219
+ [condition.field]: element
220
+ }
221
+ }, condition.field)} = any(${quoteIdent(condition.field)})`;
222
+ return compareSql(condition.op, condition.field, sqlValue(condition.value, ctx, condition.field));
223
+ }
224
+ case "in":
225
+ case "notIn": {
226
+ const keyword = condition.op === "in" ? "in" : "not in";
227
+ if (!Array.isArray(condition.value) && typeof condition.value === "object" && "ref" in condition.value) {
228
+ const path = claimPath(condition.value.ref);
229
+ if (path === void 0) {
230
+ compileRef(condition.value.ref, ctx);
231
+ throw configError(`PermDock CLI: non-portable ${condition.op} against '${condition.value.ref}'`);
232
+ }
233
+ const column = quoteIdent(condition.field);
234
+ const list = claimArraySql(ctx, path, ctx.columnTypes?.[condition.field]);
235
+ return condition.op === "in" ? `${column} = any (${list})` : `(${column} is not null and not (${column} = any (${list})))`;
236
+ }
237
+ const values = condition.value.map((item) => sqlValue(item, ctx));
238
+ if (values.length === 0) return condition.op === "in" ? "false" : `${quoteIdent(condition.field)} is not null`;
239
+ return `${quoteIdent(condition.field)} ${keyword} (${values.join(", ")})`;
240
+ }
241
+ case "isNull": return `${quoteIdent(condition.field)} is ${condition.value ? "" : "not "}null`;
242
+ case "and": return `(${condition.conditions.map((item) => compileConditionSql(item, ctx)).join(" and ")})`;
243
+ case "or":
244
+ if (condition.conditions.length === 0) return "false";
245
+ return `(${condition.conditions.map((item) => compileConditionSql(item, ctx)).join(" or ")})`;
246
+ case "not": return `(${compileConditionSql(condition.condition, ctx)}) is not true`;
247
+ case "memberOf": return compileMemberOf(condition, ctx);
248
+ case "related": return compileRelatedSql(condition, ctx);
249
+ case "sqlFunction":
250
+ if (ctx.inlineFunctions === true) return compileConditionSql(condition.twin, ctx);
251
+ return `${quoteTable(condition.name)}(${condition.args.map((arg) => isSqlFunctionField(arg) ? quoteIdent(arg.field) : sqlValue(arg, ctx)).join(", ")})`;
252
+ case "opaque": return condition.sql;
253
+ case "liveSession": return liveSessionSql(ctx);
254
+ default: return condition;
255
+ }
256
+ }
257
+ function andConditions(left, right) {
258
+ if (left === void 0) return right;
259
+ if (right === void 0) return left;
260
+ return {
261
+ op: "and",
262
+ conditions: [left, right]
263
+ };
264
+ }
265
+ function valueContextRefs(value) {
266
+ if (Array.isArray(value)) return value.flatMap(valueContextRefs);
267
+ if (isRecord(value) && typeof value["ref"] === "string" && (value["ref"] === "context" || value["ref"].startsWith("context."))) return [value["ref"]];
268
+ return [];
269
+ }
270
+ /**
271
+ * The `context.*` refs a condition reads. The request context is not in the
272
+ * token, so RLS cannot evaluate them.
273
+ */
274
+ function contextRefs(condition) {
275
+ if (condition === void 0) return [];
276
+ switch (condition.op) {
277
+ case "eq":
278
+ case "ne":
279
+ case "gt":
280
+ case "gte":
281
+ case "lt":
282
+ case "lte":
283
+ case "contains":
284
+ case "in":
285
+ case "notIn": return valueContextRefs(condition.value);
286
+ case "and":
287
+ case "or": return condition.conditions.flatMap((child) => contextRefs(child));
288
+ case "not": return contextRefs(condition.condition);
289
+ case "sqlFunction": return [...condition.args.flatMap(valueContextRefs), ...contextRefs(condition.twin)];
290
+ case "isNull":
291
+ case "memberOf":
292
+ case "related":
293
+ case "opaque":
294
+ case "liveSession": return [];
295
+ default: return condition;
296
+ }
297
+ }
298
+ function sqlFunctionNames(condition) {
299
+ if (condition === void 0) return [];
300
+ switch (condition.op) {
301
+ case "sqlFunction": return [condition.name, ...sqlFunctionNames(condition.twin)];
302
+ case "and":
303
+ case "or": return condition.conditions.flatMap((child) => sqlFunctionNames(child));
304
+ case "not": return sqlFunctionNames(condition.condition);
305
+ case "eq":
306
+ case "ne":
307
+ case "gt":
308
+ case "gte":
309
+ case "lt":
310
+ case "lte":
311
+ case "contains":
312
+ case "in":
313
+ case "notIn":
314
+ case "isNull":
315
+ case "memberOf":
316
+ case "related":
317
+ case "opaque":
318
+ case "liveSession": return [];
319
+ default: return condition;
320
+ }
321
+ }
322
+ /**
323
+ * A `related` condition as uncorrelated subqueries, so Postgres runs the helper
324
+ * once per statement: the row's field in the closure's descendants of the ids
325
+ * the subject holds the relation on (or those ids alone at depth 0). The helper
326
+ * sits in `array(...)` so it stays an InitPlan; a plain `in` gets pulled into a
327
+ * join that can rescan it per closure row.
328
+ */
329
+ function compileRelatedSql(condition, ctx) {
330
+ if (condition.hops !== void 0 && condition.hops.length > 0) return compileHoppedSql(condition, ctx);
331
+ const type = ctx.columnTypes?.[condition.field];
332
+ const cast = type === void 0 || type === "text" ? "" : `::${type}`;
333
+ const column = type === void 0 ? `${quoteIdent(condition.field)}::text` : quoteIdent(condition.field);
334
+ const helper = condition.permission === void 0 ? `${qualified(ctx, graphHelper(condition.resource))}(${quoteLiteral(condition.relation)})` : `${qualified(ctx, inheritedRowsHelper(condition.resource))}(${quoteLiteral(condition.permission)})`;
335
+ const cap = ctx.graph?.closures[condition.resource];
336
+ let inner;
337
+ if (condition.depth > 0 && cap !== void 0) {
338
+ const depth = condition.depth < cap ? ` and depth <= ${String(condition.depth)}` : "";
339
+ inner = `select descendant${cast} from ${qualified(ctx, CLOSURE.table)} where resource = ${quoteLiteral(condition.resource)}${depth} and ancestor = any (array(select ${helper}))`;
340
+ } else inner = cast === "" ? `select ${helper}` : `select p.id${cast} from ${helper} as p(id)`;
341
+ const reach = `${column} in (${inner})`;
342
+ if (condition.parent === true && condition.restricted !== void 0) return `(${reach} and ${quoteIdent(condition.restricted)} is not true)`;
343
+ return reach;
344
+ }
345
+ /**
346
+ * A `related` condition that crosses link hops: the reached instances of the
347
+ * last resource, carried back over each link by its security definer helper, so
348
+ * the hop reads a table the subject may not see.
349
+ */
350
+ function compileHoppedSql(condition, ctx) {
351
+ const resources = ctx.graph?.resources;
352
+ if (resources === void 0) throw configError("PermDock CLI: a related condition with link hops needs the policy resources in the RLS context");
353
+ const schema = quoteIdent(helperSchema(ctx));
354
+ return graphSqlText(relatedSql(condition, {
355
+ resources,
356
+ ...ctx.graph?.tables === void 0 ? {} : { tables: ctx.graph.tables },
357
+ closure: `${helperSchema(ctx)}.${CLOSURE.table}`,
358
+ closureDepths: ctx.graph?.closures ?? {},
359
+ qualify: qualifySqlTable,
360
+ holders: (resource, relation) => [{ text: `select ${schema}.${graphHelper(resource)}(${quoteLiteral(relation)})` }],
361
+ permitted: (resource, permission) => [{ text: `select ${schema}.${inheritedRowsHelper(resource)}(${quoteLiteral(permission)})` }],
362
+ restrictedRows: (resource) => [{ text: `select ${schema}.${restrictedHelper(resource)}()` }],
363
+ linked: (resource, link, targets) => [
364
+ { text: `select ${schema}.${linkHelper(resource, link)}(array(` },
365
+ ...targets,
366
+ { text: "))" }
367
+ ]
368
+ }), ctx);
369
+ }
370
+ //#endregion
371
+ //#region src/cli/sql/grants.ts
372
+ /**
373
+ * The `role_permissions` grant key of a break-glass grant. It differs from the
374
+ * permission key, so `authorize()` and the table policies never count it; only
375
+ * the break-glass read asks for it.
376
+ */
377
+ function breakGlassKey(permission) {
378
+ return `${permission}#break-glass`;
379
+ }
380
+ /**
381
+ * The role and scope holding a break-glass grant. `breakGlass()` sets `to:
382
+ * authenticated`, so inside `role()` the role is on the grant itself.
383
+ */
384
+ function breakGlassHolder(item) {
385
+ if (item.access.kind === "role") return {
386
+ role: item.access.role,
387
+ scope: item.access.scope
388
+ };
389
+ const { role, scope } = item.grant;
390
+ return role === null || typeof scope !== "string" ? void 0 : {
391
+ role,
392
+ scope
393
+ };
394
+ }
395
+ function granteeItems(to) {
396
+ return Array.isArray(to) ? to : [to];
397
+ }
398
+ function relationWhere(policy, grant, grantee) {
399
+ const node = policy.resources.get(grant.permission.resource);
400
+ const where = relationCondition(grantee, node, scopeList(policy.scopes), {
401
+ resources: policy.resources,
402
+ now: { ref: "now" }
403
+ });
404
+ if (where === void 0) throw configError(`PermDock CLI: grant ${grant.permission.key} names relation '${grantee.relation}', which ${grant.permission.resource} does not declare`);
405
+ return where;
406
+ }
407
+ function inheritWhere(policy, grant, grantee) {
408
+ const where = inheritCondition(grantee, policy.resources.get(grant.permission.resource), policy.resources);
409
+ if (where === void 0) throw configError(`PermDock CLI: grant ${grant.permission.key} inherits ${grantee.permission}, which ${grant.permission.resource} cannot reach`);
410
+ return where;
411
+ }
412
+ /**
413
+ * Only a deny for `oauth-client` actors compiles: Postgres sees `client_id` and
414
+ * `act`, not other actor kinds.
415
+ */
416
+ function actorAccess(grant, grantee, others) {
417
+ if (grant.effect !== "deny" || grantee.actor !== "oauth-client" || others > 0) throw configError(`PermDock CLI: grant ${grant.permission.key} is limited to an actor grantee; RLS compiles only deny(…, { to: actor('oauth-client') }) on its own, so enforce it in the application`);
418
+ return {
419
+ kind: "actor",
420
+ actor: "oauth-client"
421
+ };
422
+ }
423
+ function accessOf(grant, roles, anyone) {
424
+ const [held, ...more] = roles;
425
+ if (more.length > 0) throw configError(`PermDock CLI: grant ${grant.permission.key} requires several roles at once (${roles.map((item) => item.role).join(", ")}); RLS compiles one role per grant`);
426
+ if (held === void 0) return anyone ? { kind: "anyone" } : { kind: "authenticated" };
427
+ if (typeof held.scope === "object") return {
428
+ kind: "resource",
429
+ role: held.role,
430
+ resource: held.scope.resource
431
+ };
432
+ return {
433
+ kind: "role",
434
+ role: held.role,
435
+ scope: held.scope
436
+ };
437
+ }
438
+ /**
439
+ * Every grant RLS must enforce: role grants and top-level `definePolicy({
440
+ * grants })` alike (`policy.grants` holds both). A grantee Postgres cannot see
441
+ * (plan, actor, assurance) fails with the permission named.
442
+ */
443
+ function collectGrants(policy) {
444
+ return policy.grants.map((grant) => {
445
+ const items = granteeItems(grant.to);
446
+ const roles = [];
447
+ let anyone = true;
448
+ let where = grant.where;
449
+ let delegated;
450
+ for (const item of items) switch (item.kind) {
451
+ case "role":
452
+ roles.push(item);
453
+ break;
454
+ case "anyone": break;
455
+ case "authenticated":
456
+ anyone = false;
457
+ break;
458
+ case "relation":
459
+ anyone = false;
460
+ where = andConditions(where, relationWhere(policy, grant, item));
461
+ break;
462
+ case "inherit":
463
+ anyone = false;
464
+ where = andConditions(where, inheritWhere(policy, grant, item));
465
+ break;
466
+ case "actor":
467
+ delegated = actorAccess(grant, item, items.length - 1);
468
+ break;
469
+ case "plan":
470
+ case "assurance": throw configError(`PermDock CLI: grant ${grant.permission.key} is limited to a ${item.kind} grantee, which RLS cannot compile; enforce it in the application`);
471
+ default: return item;
472
+ }
473
+ const access = delegated ?? accessOf(grant, roles, anyone);
474
+ const label = access.kind === "role" || access.kind === "resource" ? access.role : access.kind;
475
+ return where === void 0 ? {
476
+ grant,
477
+ label,
478
+ access
479
+ } : {
480
+ grant,
481
+ label,
482
+ access,
483
+ where
484
+ };
485
+ });
486
+ }
487
+ /**
488
+ * The declared roles a custom role may draw grants from: the custom-role
489
+ * ceiling.
490
+ */
491
+ function assignableRoles(policy) {
492
+ return [...roleNames(policy)].toSorted().filter((name) => policy.rolesByName.get(name)?.assignable ?? listRoles(policy.vocabulary.roles).some((leaf) => leaf.key === name && leaf.assignable));
493
+ }
494
+ /**
495
+ * Declared role names (bindings and `defineRoles` leaves) plus any role a
496
+ * top-level grant names.
497
+ */
498
+ function roleNames(policy) {
499
+ const names = new Set(policy.roles.map((item) => item.name));
500
+ for (const leaf of listRoles(policy.vocabulary.roles)) names.add(leaf.key);
501
+ for (const item of collectGrants(policy)) if (item.access.kind === "role" || item.access.kind === "resource") names.add(item.access.role);
502
+ return [...names];
503
+ }
504
+ //#endregion
505
+ //#region src/cli/rls/assignments.ts
506
+ /**
507
+ * The client roles whose writes the assignment triggers check; any other role
508
+ * is a trusted path.
509
+ */
510
+ const CLIENT_ROLES = [
511
+ "anon",
512
+ "anonymous",
513
+ "authenticated"
514
+ ];
515
+ /**
516
+ * The mapped membership tables, `rls.assignments.tables` and the global-roles
517
+ * table `rls.roles`.
518
+ */
519
+ function assignedTables(ctx) {
520
+ const out = [];
521
+ for (const { name } of ctx.scopes) {
522
+ const mapped = scopeTable(ctx, name);
523
+ if (mapped === void 0) continue;
524
+ out.push({
525
+ table: mapped.table.table,
526
+ scope: name,
527
+ id: mapped.column,
528
+ tenant: mapped.tenantColumn ?? mapped.column,
529
+ role: mapped.table.role,
530
+ user: mapped.table.user
531
+ });
532
+ }
533
+ if (ctx.roles !== void 0) out.push({
534
+ table: ctx.roles.table,
535
+ scope: "global",
536
+ role: ctx.roles.role ?? "role",
537
+ user: ctx.roles.user ?? "user_id"
538
+ });
539
+ for (const extra of ctx.assignments?.tables ?? []) {
540
+ const scope = resolveScope(ctx.scopes, extra.scope);
541
+ if (scope === void 0) throw configError(`PermDock CLI: rls.assignments.tables names scope '${extra.scope}', which the policy does not declare`);
542
+ if (scope !== ctx.scopes[0]?.name && extra.tenant === void 0) throw configError(`PermDock CLI: rls.assignments.tables entry ${extra.table} assigns at ${scope}, below the first scope: name its tenant column`);
543
+ out.push({
544
+ table: extra.table,
545
+ scope,
546
+ id: extra.id,
547
+ tenant: extra.tenant ?? extra.id,
548
+ role: extra.role,
549
+ ...extra.user === void 0 ? {} : { user: extra.user }
550
+ });
551
+ }
552
+ return out;
553
+ }
554
+ /**
555
+ * The tables `rls.assignments.ownRole` refuses a caller's own rows on, by table
556
+ * key.
557
+ */
558
+ function ownRoleTables(ctx, tables) {
559
+ const own = ctx.assignments?.ownRole;
560
+ if (own === void 0) return /* @__PURE__ */ new Set();
561
+ if (own === "refuse") return new Set(tables.filter((entry) => entry.user !== void 0).map((entry) => qualifySqlTable(entry.table)));
562
+ const out = /* @__PURE__ */ new Set();
563
+ for (const [name, value] of Object.entries(own)) {
564
+ const entry = tables.find((table) => qualifySqlTable(table.table) === qualifySqlTable(name));
565
+ if (entry === void 0) throw configError(`PermDock CLI: rls.assignments.ownRole names ${name}, which no assignment trigger guards`);
566
+ if (value !== "refuse") throw configError(`PermDock CLI: rls.assignments.ownRole.${name} must be 'refuse'`);
567
+ if (entry.user === void 0) throw configError(`PermDock CLI: rls.assignments.ownRole names ${name}, which has no user column: set its user in rls.assignments.tables`);
568
+ out.add(qualifySqlTable(entry.table));
569
+ }
570
+ return out;
571
+ }
572
+ /**
573
+ * The tables `rls.assignments` guards, schema-qualified: each scope's mapped
574
+ * membership table, the global-roles table (`rls.roles`, else
575
+ * `supabase.hook.roles`) and `rls.assignments.tables`. Empty without
576
+ * `rls.assignments`.
577
+ */
578
+ function guardedTables(config, scopes) {
579
+ const rls = config.rls;
580
+ if (rls?.assignments === void 0) return [];
581
+ const hook = config.supabase?.hook?.roles;
582
+ const roles = rls.roles ?? (hook === false ? void 0 : hook);
583
+ const tables = [
584
+ ...scopes.flatMap((scope) => {
585
+ const mapped = memberForTable({
586
+ scopes,
587
+ ...rls.memberships === void 0 ? {} : { memberships: rls.memberships }
588
+ }, scope.name);
589
+ return mapped === void 0 ? [] : [mapped.table];
590
+ }),
591
+ ...roles === void 0 ? [] : [roles.table],
592
+ ...(rls.assignments === true ? [] : rls.assignments.tables ?? []).map((entry) => entry.table)
593
+ ];
594
+ return [...new Set(tables.map(qualifySqlTable))];
595
+ }
596
+ function isRoleList(role) {
597
+ return Array.isArray(role);
598
+ }
599
+ /** The role keys a row variable holds, one scalar per role source. */
600
+ function rowRoles(entry, row) {
601
+ return (isRoleList(entry.role) ? entry.role : [entry.role]).map((part) => roleColumn(part, qualifySqlTable(entry.table), row, {
602
+ label: `rls.assignments ${entry.table} role`,
603
+ prefix: "PermDock CLI"
604
+ }).lookup);
605
+ }
606
+ /**
607
+ * `permdock_can_assign_custom_role`: whether the signed-in caller may assign a
608
+ * custom role of the tenant at the instance, by the checks the custom-role
609
+ * write functions run on its stored definition.
610
+ */
611
+ function canAssignCustomSql(ctx, forUser = false) {
612
+ const tenantType = tenantTypeOf(ctx);
613
+ const fn = qualified(ctx, forUser ? ASSIGNMENTS.customFor : ASSIGNMENTS.custom);
614
+ const perms = qualified(ctx, CUSTOM_ROLES.permissions);
615
+ const includes = qualified(ctx, CUSTOM_ROLES.includes);
616
+ const guard = qualified(ctx, forUser ? CUSTOM_ROLES.guardFor : CUSTOM_ROLES.guard);
617
+ const userParam = forUser ? "p_user uuid, " : "";
618
+ const userArg = forUser ? "uuid, " : "";
619
+ const stored = `${storedTenant(ctx)} and c.scope = p_scope and c.role = p_role and (c.scope_id is null or c.scope_id = p_scope_id)`;
620
+ const grants = forUser ? `revoke execute on function ${fn}(${userArg}${tenantType}, text, text, text) from public, anon, authenticated;` : `revoke execute on function ${fn}(${tenantType}, text, text, text) from public, anon;
621
+ grant execute on function ${fn}(${tenantType}, text, text, text) to authenticated;`;
622
+ return `-- whether ${forUser ? "user p_user" : "the caller"} may assign custom role p_role at instance p_scope_id (a platform role: null tenant, scope global): the custom-role write checks on its stored definition${forUser ? "; no client role may execute it" : ""}
623
+ create or replace function ${fn}(${userParam}p_tenant ${tenantType}, p_scope text, p_scope_id text, p_role text)
624
+ returns boolean
625
+ language plpgsql
626
+ stable
627
+ security definer
628
+ set search_path = ''
629
+ as $$
630
+ declare
631
+ v_scope_id text;
632
+ v_found boolean := false;
633
+ begin
634
+ select true, c.scope_id into v_found, v_scope_id
635
+ from (
636
+ select c.scope_id from ${perms} c where ${stored}
637
+ union all
638
+ select c.scope_id from ${includes} c where ${stored}
639
+ ) c
640
+ order by c.scope_id nulls first
641
+ limit 1;
642
+ if not coalesce(v_found, false) then
643
+ return false;
644
+ end if;
645
+ perform ${guard}(${forUser ? "p_user, " : ""}p_tenant, p_scope, v_scope_id, p_role);
646
+ return true;
647
+ exception
648
+ when insufficient_privilege or invalid_parameter_value then
649
+ return false;
650
+ end;
651
+ $$;
652
+ ${grants}`;
653
+ }
654
+ /**
655
+ * The assignment triggers (\`rls.assignments\`): before a client role inserts,
656
+ * updates or deletes a row that assigns a role, every role the old and new row
657
+ * hold must be one the caller may assign at that instance, by
658
+ * \`permdock_can_assign\` for a declared role and
659
+ * \`permdock_can_assign_custom_role\` for a custom one. The functions run as
660
+ * the invoker, so \`current_user\` tells a client write from a trusted one.
661
+ */
662
+ function assignmentSql(ctx) {
663
+ const own = ctx.ownership;
664
+ if (ctx.assignments === void 0 || own === void 0 || own.assigns.length === 0) return "";
665
+ const canAssign = qualified(ctx, OWNERSHIP.canAssign);
666
+ const custom = ctx.customRoles !== void 0 && ctx.authorize === "database";
667
+ const declared = ctx.customRoles?.declared;
668
+ const tenantType = tenantTypeOf(ctx);
669
+ const chunks = [];
670
+ const clients = `current_user::text = any(array[${CLIENT_ROLES.map(quoteLiteral).join(", ")}])`;
671
+ const tables = assignedTables(ctx);
672
+ const ownRole = ownRoleTables(ctx, tables);
673
+ for (const entry of tables) {
674
+ const table = quoteQualified(entry.table);
675
+ const suffix = entry.table.replaceAll(/[^a-z0-9_]/gu, "_");
676
+ const fn = qualified(ctx, quoteIdent(`${ASSIGNMENTS.trigger}_${suffix}`));
677
+ const ownUser = entry.user !== void 0 && ownRole.has(qualifySqlTable(entry.table)) ? entry.user : void 0;
678
+ const ownCheck = (row, reason) => ownUser === void 0 ? "" : ` if ${row}.${quoteIdent(ownUser)}::text = (${subjectIdSql(ctx)})::text then
679
+ raise exception using
680
+ errcode = '42501',
681
+ message = 'permdock: the caller may not change their own roles',
682
+ hint = '${reason}';
683
+ end if;
684
+ `;
685
+ const check = (row) => {
686
+ const id = entry.id === void 0 ? "null::text" : `${row}.${quoteIdent(entry.id)}::text`;
687
+ const customFn = qualified(ctx, ASSIGNMENTS.custom);
688
+ let allowed = `${canAssign}(v_role, ${id})`;
689
+ if (custom && declared !== void 0) {
690
+ const platform = `${customFn}(null, 'global', null, v_role)`;
691
+ allowed = entry.id === void 0 || entry.tenant === void 0 ? `case when v_role = any(${declaredArray(declared)}) then ${canAssign}(v_role, ${id}) else ${platform} end` : `case when v_role = any(${declaredArray(declared)}) then ${canAssign}(v_role, ${id}) when ${id} is null then ${platform} else ${customFn}(${row}.${quoteIdent(entry.tenant)}::${tenantType}, ${quoteLiteral(entry.scope)}, ${id}, v_role) end`;
692
+ }
693
+ return ` foreach v_role in array array[${rowRoles(entry, row).join(", ")}]::text[] loop
694
+ if v_role is not null and not coalesce(${allowed}, false) then
695
+ raise exception using
696
+ errcode = '42501',
697
+ message = 'permdock: the caller may not assign ' || v_role || ' in ' || coalesce(${id}, 'null'),
698
+ hint = 'not-assignable-by';
699
+ end if;
700
+ end loop;`;
701
+ };
702
+ const what = entry.id === void 0 ? "global roles" : `${entry.scope} roles`;
703
+ chunks.push(`-- ${entry.table}: a client role may write only the ${what} it may assign${ownUser === void 0 ? "" : ", and none on its own rows"}
704
+ create or replace function ${fn}()
705
+ returns trigger
706
+ language plpgsql
707
+ volatile
708
+ set search_path = ''
709
+ as $$
710
+ declare
711
+ v_role text;
712
+ begin
713
+ if not (${clients}) then
714
+ return coalesce(new, old);
715
+ end if;
716
+ if tg_op in ('UPDATE', 'DELETE') then
717
+ ${ownCheck("old", "self-demotion")}${check("old")}
718
+ end if;
719
+ if tg_op in ('INSERT', 'UPDATE') then
720
+ ${ownCheck("new", "not-assignable-by")}${check("new")}
721
+ end if;
722
+ return coalesce(new, old);
723
+ end;
724
+ $$;
725
+ revoke execute on function ${fn}() from public, anon, authenticated;
726
+ drop trigger if exists "permdock_assignment" on ${table};
727
+ create trigger "permdock_assignment"
728
+ before insert or update or delete on ${table}
729
+ for each row execute function ${fn}();`);
730
+ }
731
+ return `${chunks.join("\n\n")}\n`;
732
+ }
733
+ //#endregion
734
+ //#region src/cli/rls/can-assign.ts
735
+ /**
736
+ * Whether the signed-in user (or `p_user` in the `_for` form) holds, in
737
+ * instance `p_scope_id`, a role whose `assigns` lists `p_role`.
738
+ */
739
+ function canAssignSql(base, own, forUser = false) {
740
+ const ctx = forUser ? {
741
+ ...base,
742
+ subjectId: "p_user",
743
+ tenants: "all"
744
+ } : base;
745
+ const fn = qualified(ctx, forUser ? OWNERSHIP.canAssignFor : OWNERSHIP.canAssign);
746
+ const parts = [];
747
+ const used = [];
748
+ const userOf = (source) => {
749
+ const index = used.includes(source) ? used.indexOf(source) : used.push(source) - 1;
750
+ return `v_user_${String(index)}`;
751
+ };
752
+ const global = own.assigns.filter((pair) => pair.scope === "global");
753
+ for (const [instance, pairs] of [["p_scope_id is not null", global.filter((pair) => pair.at !== "global")], ["p_scope_id is null", global.filter((pair) => pair.at === "global")]]) {
754
+ if (pairs.length === 0) continue;
755
+ if (ctx.authorize === "database") {
756
+ const ur = globalRoleRows(ctx);
757
+ const kind = globalKindFilterSql(ctx, ur.roleSql);
758
+ parts.push(`${instance} and exists (
759
+ select 1 from ${ur.from}
760
+ where ${ur.userSql} = ${subjectIdSql(ctx)}
761
+ and (${ur.roleSql}, p_role) in (${pairsSql(pairs)})${kind === void 0 ? "" : `\n and ${kind}`}
762
+ )`);
763
+ } else {
764
+ const kind = globalKindFilterSql(ctx, "r.role");
765
+ parts.push(`${instance} and exists (
766
+ select 1 from ${roleRows(ctx)}
767
+ where (r.role, p_role) in (${pairsSql(pairs)})${kind === void 0 ? "" : `\n and ${kind}`}
768
+ )`);
769
+ }
770
+ }
771
+ for (const { name } of ctx.scopes) {
772
+ const pairs = own.assigns.filter((pair) => pair.scope === name);
773
+ if (pairs.length === 0) continue;
774
+ const sources = scopeSources(ctx, name);
775
+ if (sources.length > 0) {
776
+ const kind = kindFilterSql(ctx, "r.role", "ms.via");
777
+ parts.push(`exists (
778
+ select 1
779
+ from (
780
+ ${sourceRowsSql(sources, userOf)}
781
+ ) ms
782
+ cross join lateral jsonb_array_elements_text(
783
+ case jsonb_typeof(ms.roles) when 'array' then ms.roles else '[]'::jsonb end
784
+ ) r(role)
785
+ where ms.scope = ${quoteLiteral(name)}
786
+ and ms.id = p_scope_id
787
+ and (r.role, p_role) in (${pairsSql(pairs)})${kind === void 0 ? "" : `\n and ${kind}`}${sourceFilters(ctx, name, void 0, void 0, sourcesKeep(sources)).replaceAll("\n and ", "\n and ")}
788
+ )`);
789
+ continue;
790
+ }
791
+ if (ctx.authorize === "database") {
792
+ const mapped = scopeTable(ctx, name);
793
+ if (mapped === void 0) continue;
794
+ const { table, column } = mapped;
795
+ const role = memberRoleOf(table, "m", " ");
796
+ const filters = [
797
+ `${memberColumn(table.user)} = ${subjectIdSql(ctx)}`,
798
+ `${memberColumn(column)}::text = p_scope_id`,
799
+ `(${role.sql}, p_role) in (${pairsSql(pairs)})`
800
+ ];
801
+ if (table.expiresAt !== void 0) {
802
+ const expires = memberColumn(table.expiresAt);
803
+ filters.push(`(${expires} is null or ${expires} > now())`);
804
+ }
805
+ const disabled = disabledColumn(table);
806
+ if (disabled !== void 0) filters.push(`${disabled} is null`);
807
+ const kind = kindFilterSql(ctx, role.sql, memberVia(table));
808
+ if (kind !== void 0) filters.push(kind);
809
+ parts.push(`exists (
810
+ select 1 from ${quoteQualified(table.table)} m${role.join}
811
+ where ${filters.join("\n and ")}
812
+ )`);
813
+ } else {
814
+ const kind = kindFilterSql(ctx, "r.role", "m ->> 'via'");
815
+ parts.push(`exists (
816
+ select 1 from ${membershipRows(ctx)}
817
+ where m ->> 'scope' = ${quoteLiteral(name)}
818
+ and m ->> 'id' = p_scope_id
819
+ and (r.role, p_role) in (${pairsSql(pairs)})
820
+ and case jsonb_typeof(m -> 'expires_at')
821
+ when 'number' then (m ->> 'expires_at')::numeric > extract(epoch from now())
822
+ else true
823
+ end${kind === void 0 ? "" : `\n and ${kind}`}${claimKeptLines(ctx, " ").map((line) => `\n${line}`).join("")}
824
+ )`);
825
+ }
826
+ }
827
+ const body = parts.length === 0 ? "false" : parts.join("\n or ");
828
+ const language = used.length === 0 ? `language sql
829
+ stable
830
+ security definer
831
+ set search_path = ''
832
+ as $$
833
+ select ${signedIn(ctx)} and (
834
+ ${body}
835
+ )
836
+ $$;` : `language plpgsql
837
+ stable
838
+ security definer
839
+ set search_path = ''
840
+ as $$
841
+ declare
842
+ ${used.map((source, index) => ` v_user_${String(index)} ${source.sql.userType} := ${subjectIdSql(ctx)};`).join("\n")}
843
+ begin
844
+ return ${signedIn(ctx)} and (
845
+ ${body}
846
+ );
847
+ end;
848
+ $$;`;
849
+ if (forUser) {
850
+ const user = ctx.dialect === "supabase" ? "uuid" : "text";
851
+ return `-- who may assign, for a user the caller names: trusted SQL acting later for a stored user; no client role may execute it
852
+ create or replace function ${fn}(p_user ${user}, p_role text, p_scope_id text)
853
+ returns boolean
854
+ ${language}
855
+ revoke execute on function ${fn}(${user}, text, text) from public, anon, authenticated;`;
856
+ }
857
+ return `-- who may assign: a held role whose assigns lists p_role, in instance p_scope_id (its scope or an ancestor's); a null p_scope_id assigns a global role, which only global assigners may
858
+ create or replace function ${fn}(p_role text, p_scope_id text)
859
+ returns boolean
860
+ ${language}
861
+ revoke execute on function ${fn}(text, text) from public, anon;
862
+ grant execute on function ${fn}(text, text) to authenticated;`;
863
+ }
864
+ /**
865
+ * Whether the helpers keep custom roles in tables, so assigning one is checked
866
+ * against its stored definition.
867
+ */
868
+ function assignsCustomRoles(ctx) {
869
+ return ctx.customRoles !== void 0 && ctx.authorize === "database";
870
+ }
871
+ /**
872
+ * Whether `permdock_can_assign_any_for` is written: every function it calls has
873
+ * a `_for` form.
874
+ */
875
+ function hasCanAssignAnyFor(ctx) {
876
+ return ctx.authorize === "database" && (!assignsCustomRoles(ctx) || hasCustomRoleChecksFor(ctx));
877
+ }
878
+ /**
879
+ * `permdock_can_assign_any`: one check for a declared or a custom role, so SQL
880
+ * that assigns roles calls one function: `permdock_can_assign` for a declared
881
+ * role, `permdock_can_assign_custom_role` for a custom one. `p_scope`
882
+ * `'global'` (no tenant, no instance) assigns a platform role.
883
+ */
884
+ function canAssignAnySql(ctx, custom, forUser = false) {
885
+ const tenantType = tenantTypeOf(ctx);
886
+ const fn = qualified(ctx, forUser ? OWNERSHIP.canAssignAnyFor : OWNERSHIP.canAssignAny);
887
+ const declaredFn = qualified(ctx, forUser ? OWNERSHIP.canAssignFor : OWNERSHIP.canAssign);
888
+ const customFn = qualified(ctx, forUser ? ASSIGNMENTS.customFor : ASSIGNMENTS.custom);
889
+ const userType = ctx.dialect === "supabase" ? "uuid" : "text";
890
+ const userParam = forUser ? `p_user ${userType}, ` : "";
891
+ const userArg = forUser ? `${userType}, ` : "";
892
+ const user = forUser ? "p_user, " : "";
893
+ const declared = `${declaredFn}(${user}p_role, case when p_scope = 'global' then null else p_scope_id end)`;
894
+ const body = custom && ctx.customRoles !== void 0 ? `case
895
+ when p_role = any(${declaredArray(ctx.customRoles.declared)}) then ${declared}
896
+ when p_scope = 'global' then ${customFn}(${user}null, 'global', null, p_role)
897
+ else ${customFn}(${user}p_tenant, p_scope, p_scope_id, p_role)
898
+ end` : declared;
899
+ const grants = forUser ? `revoke execute on function ${fn}(${userArg}text, ${tenantType}, text, text) from public, anon, authenticated;` : `revoke execute on function ${fn}(text, ${tenantType}, text, text) from public, anon;
900
+ grant execute on function ${fn}(text, ${tenantType}, text, text) to authenticated;`;
901
+ return `-- whether ${forUser ? "user p_user" : "the caller"} may assign p_role at instance p_scope_id of p_scope in tenant p_tenant, declared or custom (p_scope 'global' for a platform role)${forUser ? "; no client role may execute it" : ""}
902
+ create or replace function ${fn}(${userParam}p_role text, p_tenant ${tenantType}, p_scope text, p_scope_id text)
903
+ returns boolean
904
+ language sql
905
+ stable
906
+ security definer
907
+ set search_path = ''
908
+ as $$
909
+ select coalesce(${body}, false)
910
+ $$;
911
+ ${grants}`;
912
+ }
913
+ //#endregion
914
+ //#region src/cli/rls/ownership.ts
915
+ function roleScope(policy, scopes, name) {
916
+ const on = policy.rolesByName.get(name)?.on ?? findRole(policy.vocabulary.roles, name)?.on;
917
+ return typeof on === "string" ? resolveScope(scopes, on) : void 0;
918
+ }
919
+ function isGlobalRole(policy, name) {
920
+ const binding = policy.rolesByName.get(name);
921
+ if (binding !== void 0) return binding.on === void 0;
922
+ const leaf = findRole(policy.vocabulary.roles, name);
923
+ return leaf !== void 0 && leaf.on === void 0;
924
+ }
925
+ /** The rules `rls generate` enforces; `undefined` when no role declares one. */
926
+ function ownershipRules(policy, scopes) {
927
+ const kinds = {};
928
+ const assigns = [];
929
+ const counted = [];
930
+ for (const binding of policy.roles) {
931
+ const scope = roleScope(policy, scopes, binding.name);
932
+ if (binding.for !== void 0) kinds[binding.name] = binding.for;
933
+ const assigner = scope ?? (binding.on === void 0 ? "global" : void 0);
934
+ for (const target of binding.assigns ?? []) {
935
+ const at = roleScope(policy, scopes, target);
936
+ if (assigner !== void 0 && at !== void 0 && (assigner === "global" || scopeChain(scopes, at).includes(assigner))) assigns.push({
937
+ assigner: binding.name,
938
+ scope: assigner,
939
+ role: target,
940
+ at
941
+ });
942
+ else if (assigner === "global" && isGlobalRole(policy, target)) assigns.push({
943
+ assigner: binding.name,
944
+ scope: "global",
945
+ role: target,
946
+ at: "global"
947
+ });
948
+ }
949
+ const min = binding.min ?? 0;
950
+ const transferOnly = binding.transferOnly === true;
951
+ if (scope !== void 0 && (min > 0 || binding.max !== void 0 || transferOnly)) counted.push(binding.max === void 0 ? {
952
+ role: binding.name,
953
+ scope,
954
+ min,
955
+ transferOnly
956
+ } : {
957
+ role: binding.name,
958
+ scope,
959
+ min,
960
+ max: binding.max,
961
+ transferOnly
962
+ });
963
+ }
964
+ if (Object.keys(kinds).length === 0 && assigns.length === 0 && counted.length === 0) return;
965
+ return {
966
+ kinds,
967
+ assigns,
968
+ counted
969
+ };
970
+ }
971
+ /**
972
+ * The roles whose `for` lists kinds that no membership source of the role's
973
+ * scope can hold: such a role resolves to no one. A `via` read from a column
974
+ * can hold any kind, and so does a source with no `via` (it is not compared)
975
+ * and a scope with no table or source.
976
+ */
977
+ function unsatisfiedKinds(ctx, policy) {
978
+ const out = [];
979
+ for (const [role, kinds] of Object.entries(ctx.ownership?.kinds ?? {})) {
980
+ const scope = roleScope(policy, ctx.scopes, role);
981
+ if (scope === void 0) continue;
982
+ const held = [];
983
+ const mapped = scopeTable(ctx, scope)?.table;
984
+ if (mapped === void 0) for (const source of ctx.memberSources ?? ctx.sources ?? []) {
985
+ if (source.sql.scope !== void 0 && source.sql.scope !== scope) continue;
986
+ const via = source.sql.manifest.via;
987
+ held.push({
988
+ label: source.sql.table,
989
+ via: via === void 0 ? void 0 : "value" in via && typeof via.value === "string" ? via.value : void 0
990
+ });
991
+ }
992
+ else {
993
+ const via = memberVia(mapped);
994
+ held.push({
995
+ label: mapped.table,
996
+ via: typeof via === "string" ? void 0 : via.value ?? void 0
997
+ });
998
+ }
999
+ if (held.length === 0 || held.some((entry) => entry.via === void 0 || kinds.includes(entry.via ?? ""))) continue;
1000
+ out.push({
1001
+ role,
1002
+ for: kinds,
1003
+ sources: held.map((entry) => `${entry.label} (via ${entry.via ?? ""})`)
1004
+ });
1005
+ }
1006
+ return out;
1007
+ }
1008
+ /**
1009
+ * The ownership objects: holder-count and transfer-only triggers on each
1010
+ * scope's membership table, and `permdock_can_assign` for the application's own
1011
+ * policies on those tables. Empty when no role declares a rule.
1012
+ */
1013
+ function ownershipSql(ctx) {
1014
+ const own = ctx.ownership;
1015
+ if (own === void 0) return "";
1016
+ const chunks = [];
1017
+ const skipped = ctx.skipOwnershipTriggers;
1018
+ for (const { name } of ctx.scopes) {
1019
+ const counted = own.counted.filter((rule) => rule.scope === name);
1020
+ if (counted.length === 0) continue;
1021
+ if (skipped === "all" || skipped?.includes(name) === true) {
1022
+ chunks.push(`-- ${name}: rls.ownershipTriggers leaves out the triggers, so min, max and transferOnly are checked only by decideRoleChange`);
1023
+ continue;
1024
+ }
1025
+ const transfer = counted.filter((rule) => rule.transferOnly).map((rule) => rule.role);
1026
+ const mapped = scopeTable(ctx, name);
1027
+ if (mapped === void 0) {
1028
+ const sources = holderSources(ctx, name);
1029
+ if (sources === void 0) chunks.push(`-- ${name}: no memberships table configured, so min, max and transferOnly are checked only by decideRoleChange`);
1030
+ else if (sources === "not-tables") chunks.push(`-- ${name}: a membership source is not a table, so min, max and transferOnly are checked only by decideRoleChange`);
1031
+ else {
1032
+ chunks.push(sourceHoldersTriggerSql(ctx, name, sources, counted));
1033
+ if (transfer.length > 0) chunks.push(sourceTransferTriggerSql(ctx, name, sources, transfer));
1034
+ }
1035
+ continue;
1036
+ }
1037
+ chunks.push(holdersTriggerSql(ctx, name, mapped.table, mapped.column, counted));
1038
+ if (transfer.length > 0) chunks.push(transferTriggerSql(ctx, name, mapped.table, mapped.column, transfer));
1039
+ }
1040
+ if (own.assigns.length > 0) {
1041
+ chunks.push(canAssignSql(ctx, own));
1042
+ if (ctx.authorize === "database") chunks.push(canAssignSql(ctx, own, true));
1043
+ const custom = assignsCustomRoles(ctx);
1044
+ if (custom) {
1045
+ chunks.push(canAssignCustomSql(ctx));
1046
+ if (hasCustomRoleChecksFor(ctx)) chunks.push(canAssignCustomSql(ctx, true));
1047
+ }
1048
+ chunks.push(canAssignAnySql(ctx, custom));
1049
+ if (hasCanAssignAnyFor(ctx)) chunks.push(canAssignAnySql(ctx, custom, true));
1050
+ }
1051
+ return chunks.length === 0 ? "" : `${chunks.join("\n\n")}\n`;
1052
+ }
1053
+ //#endregion
1054
+ export { guardedTables as a, breakGlassKey as c, andConditions as d, compileConditionSql as f, assignmentSql as i, collectGrants as l, sqlFunctionNames as m, ownershipSql as n, assignableRoles as o, contextRefs as p, unsatisfiedKinds as r, breakGlassHolder as s, ownershipRules as t, roleNames as u };