permdock 0.5.0 → 0.7.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 (399) hide show
  1. package/README.md +1 -0
  2. package/dist/{2020-C9VN-x8c.js → 2020-CJbO8Bvz.js} +1 -3
  3. package/dist/a2a/index.d.ts +5 -5
  4. package/dist/a2a/index.js +4 -4
  5. package/dist/{adoption-scan-B4R5fnMU.js → adoption-scan-D-feE7BE.js} +1 -1
  6. package/dist/agent/index.d.ts +3 -3
  7. package/dist/agent/index.js +1 -1
  8. package/dist/ai-sdk/index.d.ts +21 -6
  9. package/dist/ai-sdk/index.js +19 -9
  10. package/dist/{approval-prompt-Djo_PyZc.d.ts → approval-prompt-K0faOLFp.d.ts} +2 -2
  11. package/dist/approvals/index.d.ts +4 -4
  12. package/dist/approvals/index.js +4 -4
  13. package/dist/{approvals-DJ6Yd5z1.js → approvals-CMRfsbBh.js} +74 -48
  14. package/dist/{arazzo-B6lebmiQ.js → arazzo-ClrF3PVb.js} +2 -2
  15. package/dist/{arazzo-BWhNF-k0.js → arazzo-rdeJ8n1J.js} +4 -4
  16. package/dist/{args-IIolxxKA.js → args-CC3OwyHW.js} +112 -2
  17. package/dist/astro/index.d.ts +6 -6
  18. package/dist/astro/index.js +2 -2
  19. package/dist/{audience-Dg8XsRaO.js → audience-BrMs8c4o.js} +1 -1
  20. package/dist/{auth-DRLEizbL.js → auth-CscUX8Sy.js} +3 -4
  21. package/dist/authzen/index.d.ts +162 -22
  22. package/dist/authzen/index.js +315 -146
  23. package/dist/{automation-BMZPIVUM.d.ts → automation-DOtAFWdy.d.ts} +3 -3
  24. package/dist/{automation-DVjOckjV.js → automation-ySsxp_Yp.js} +1 -1
  25. package/dist/base-url-BQbddZO5.js +9 -0
  26. package/dist/better-auth/index.d.ts +2 -2
  27. package/dist/better-auth/index.js +2 -2
  28. package/dist/better-supabase/index.d.ts +50 -8
  29. package/dist/better-supabase/index.js +94 -32
  30. package/dist/{bind-CZzhx-Vj.js → bind-D1nO6fiC.js} +5 -5
  31. package/dist/{bind--9EFVYWF.d.ts → bind-JDuvxjuW.d.ts} +7 -7
  32. package/dist/{build-instance-BMnAudHn.js → build-instance-DxE7czo9.js} +1 -1
  33. package/dist/{canonical-json-BC8_nMTw.js → canonical-json-DwilZ1iB.js} +6 -3
  34. package/dist/{capability-BSslw1QV.d.ts → capability-D4UC9TTW.d.ts} +2 -2
  35. package/dist/{capability-N1K9IpqS.js → capability-L7NnfhiE.js} +1 -1
  36. package/dist/{casbin-Cr7RLtA3.js → casbin-BHijLuHY.js} +2 -2
  37. package/dist/{casbin-Dyu2gnUD.js → casbin-BW9pS47J.js} +1 -1
  38. package/dist/{casl-64gpT-8x.js → casl-CmJlgziS.js} +2 -2
  39. package/dist/{casl-DjEDhTCP.js → casl-UbI8v-Wq.js} +1 -1
  40. package/dist/catalog/index.d.ts +70 -10
  41. package/dist/catalog/index.js +112 -6
  42. package/dist/catalog-BCCjSAdH.js +1 -0
  43. package/dist/{catalog-R_A__RsH.js → catalog-BaMQfQ6Y.js} +3 -3
  44. package/dist/{catalog-BECMPrwc.js → catalog-D69WhFii.js} +43 -13
  45. package/dist/{catalog-doc-C9wjsfNY.js → catalog-doc-CV9s6B1S.js} +28 -5
  46. package/dist/{catalog-fingerprint-CCP0-yQS.js → catalog-fingerprint-C144oW4M.js} +1 -1
  47. package/dist/{create-BWRSXgOF.js → challenge-nGWma08S.js} +122 -25
  48. package/dist/chat/index.d.ts +1 -1
  49. package/dist/chat/index.js +2 -2
  50. package/dist/chat-sdk/index.d.ts +3 -3
  51. package/dist/checks-BC_0mPIq.js +37 -0
  52. package/dist/claude-agent/index.d.ts +3 -3
  53. package/dist/claude-agent/index.js +2 -2
  54. package/dist/clerk/index.d.ts +3 -3
  55. package/dist/clerk/index.js +1 -1
  56. package/dist/cli/bin.js +2 -2
  57. package/dist/cli/index.d.ts +3 -3
  58. package/dist/cli/index.js +3 -3
  59. package/dist/cloud/index.d.ts +127 -11
  60. package/dist/cloud/index.js +251 -3
  61. package/dist/{cloud-CIoHNevm.js → cloud-CO8pYtwr.js} +5 -5
  62. package/dist/{codemod-Cxvvc70T.js → codemod-BP6n8N9L.js} +3 -3
  63. package/dist/{codemod-Bmj9dWMH.js → codemod-i4N2BhDc.js} +3 -3
  64. package/dist/{collect-CrZJJnEF.js → collect-BaWeMjwV.js} +17 -8
  65. package/dist/{collect-DloHbDVa.js → collect-DNm3oKOk.js} +6 -5
  66. package/dist/collect-k_Dulxr5.js +1 -0
  67. package/dist/compile/index.d.ts +1 -1
  68. package/dist/compile/index.js +1 -1
  69. package/dist/{compile-CMqMx_IN.js → compile-BAEO5bOk.js} +2 -2
  70. package/dist/{compile-Ckm2HqBZ.d.ts → compile-COM2VKuN.d.ts} +3 -3
  71. package/dist/{completion-BqhRBJD8.js → completion-BNdVf7X2.js} +3 -3
  72. package/dist/{config-bs_kZeYq.js → config-CoQHDrDi.js} +7 -3
  73. package/dist/{config-B46rm9sc.js → config-DGZzMV1B.js} +2 -2
  74. package/dist/{config-report-DUgj62Ai.js → config-report-Cm7UITNA.js} +3 -3
  75. package/dist/connector-schema-_VCSsdtD.js +433 -0
  76. package/dist/{context-bbFHR-0D.js → context--uM9V3Ui.js} +2 -2
  77. package/dist/convex/index.d.ts +5 -5
  78. package/dist/convex/index.js +2 -2
  79. package/dist/core-B5-w6Kw9.js +335 -0
  80. package/dist/core-CQkE8Esr.d.ts +179 -0
  81. package/dist/{create-0VZ7Pdiu.d.ts → create-B2-CQqCI.d.ts} +5 -5
  82. package/dist/{create-C3b4B5eF.js → create-Cb86Z8Im.js} +9 -8
  83. package/dist/{create-DnrmLnLW.js → create-DJrlhEp9.js} +5 -5
  84. package/dist/{create-BFfm17UA.d.ts → create-QHuuPw3q.d.ts} +7 -7
  85. package/dist/{create-BDS7wc3y.d.ts → create-UTnUVETj.d.ts} +30 -10
  86. package/dist/{credential-DM2um3ha.js → credential-CIM7wHwA.js} +4 -4
  87. package/dist/{credentials-DPyHmYz5.js → credentials-BpuTwd7a.js} +1 -1
  88. package/dist/{deciding-columns-Sq12mEA6.js → deciding-columns-DRo2QM6E.js} +13 -2
  89. package/dist/{delegation-DaXVdDhM.js → delegation-C5rOdTp5.js} +5 -5
  90. package/dist/delivery/index.d.ts +5 -5
  91. package/dist/delivery/index.js +4 -3
  92. package/dist/{delivery-DCAgNyCn.js → delivery-rwOKLWRm.js} +51 -2
  93. package/dist/{denied-text-D8jDHgsl.d.ts → denied-text-D4qkEtFz.d.ts} +2 -2
  94. package/dist/{describe-BybMRY7A.js → describe-DZlnEtLy.js} +1 -0
  95. package/dist/{describe-BZUsixiL.d.ts → describe-O0SwYIK8.d.ts} +2 -2
  96. package/dist/{diff-CxZo9pTq.js → diff-Btr1c1Ow.js} +2 -2
  97. package/dist/{diff-DCePiN6M.js → diff-DzT-xD13.js} +10 -10
  98. package/dist/{doctor-DFjUxf2f.js → doctor-BU1szn63.js} +241 -49
  99. package/dist/{doctor-CxiwSfqH.js → doctor-BoK_y0KO.js} +4 -4
  100. package/dist/drizzle/index.d.ts +3 -3
  101. package/dist/drizzle/index.js +1 -1
  102. package/dist/elysia/index.d.ts +5 -5
  103. package/dist/elysia/index.js +3 -3
  104. package/dist/{errors-C2PXIv4c.d.ts → errors-B_Qg9D3e.d.ts} +2 -2
  105. package/dist/{errors-CWTY6uih.js → errors-DpP_U6Bf.js} +1 -0
  106. package/dist/{evaluate-_R8QkWaf.js → evaluate-B_oqFbWC.js} +130 -34
  107. package/dist/{evaluations-16UqqQ6W.d.ts → evaluations-BCddEOfO.d.ts} +4 -4
  108. package/dist/{evaluations-DZ2CbV5k.js → evaluations-DReoiVBw.js} +4 -4
  109. package/dist/eve/index.d.ts +5 -5
  110. package/dist/eve/index.js +3 -3
  111. package/dist/express/index.d.ts +5 -5
  112. package/dist/express/index.js +3 -3
  113. package/dist/fastify/index.d.ts +5 -5
  114. package/dist/fastify/index.js +3 -3
  115. package/dist/{fetch-adapter-qKJBuRqy.d.ts → fetch-adapter-CuhyYwC1.d.ts} +4 -4
  116. package/dist/{fetch-adapter-g0ypLkID.js → fetch-adapter-De-u6vhJ.js} +3 -3
  117. package/dist/{fields-D9tPVUUS.js → fields-ClcQLrVc.js} +48 -13
  118. package/dist/{files-C5ZI27eV.js → files-acUbNwWt.js} +15 -2
  119. package/dist/{fixtures-B7XrLeY7.js → fixtures-BTMW6zgU.js} +2 -2
  120. package/dist/{flags-C3DktBDY.js → flags-aaeRAdiD.js} +2 -2
  121. package/dist/{from-snapshot-D2lZt4Dd.js → from-snapshot-Bz469dIh.js} +17 -10
  122. package/dist/generate-3FNO5P5Q.js +159 -0
  123. package/dist/{grantee-Cn1HyUsI.js → grantee-BrRANrpT.js} +14 -4
  124. package/dist/{grantee-conditions-CcXf8hMM.js → grantee-conditions-C6P1Tvol.js} +1 -1
  125. package/dist/{grantee-match-DHArqY82.js → grantee-match-0RtHWQDx.js} +3 -3
  126. package/dist/h3/index.d.ts +4 -4
  127. package/dist/h3/index.js +3 -3
  128. package/dist/{helpers-DTcZOzhF.js → helpers-DY3vXuGs.js} +3 -3
  129. package/dist/hono/index.d.ts +5 -5
  130. package/dist/hono/index.js +3 -3
  131. package/dist/{hosted-DBDX0M-P.d.ts → hosted-BmjzxQhp.d.ts} +14 -2
  132. package/dist/{hosted-BZIAYvon.js → hosted-XBgU6RGT.js} +34 -12
  133. package/dist/{http-DXJ37RDA.js → http-Ca3Sr5x1.js} +1 -1
  134. package/dist/{import-DMmOG27O.js → import-Bz0GefWg.js} +5 -5
  135. package/dist/{import-CNV7I2Dw.js → import-DB2EG_iy.js} +3 -3
  136. package/dist/{index-CxGUswIC.d.ts → index-BE8y3moU.d.ts} +50 -8
  137. package/dist/{index-Chrs5fQ-.d.ts → index-BSfRl0hZ.d.ts} +6 -6
  138. package/dist/{index-DOVf7RJv.d.ts → index-BTkwrK7v.d.ts} +155 -17
  139. package/dist/index-CMiPH2Tv.d.ts +206 -0
  140. package/dist/{index-SGdIQyzc.d.ts → index-DH9DUDEM.d.ts} +18 -3
  141. package/dist/{index-BcHcPyIo.d.ts → index-DLwcuCN_.d.ts} +86 -7
  142. package/dist/index.d.ts +18 -17
  143. package/dist/index.js +27 -25
  144. package/dist/{init-GG6Jh8HD.js → init-5TXNji88.js} +5 -5
  145. package/dist/{init-DeMYsnYJ.js → init-B-4t1NzC.js} +4 -4
  146. package/dist/{instance-options-Omfd793B.d.ts → instance-options-CU0YQCLH.d.ts} +1 -1
  147. package/dist/{instance-snapshot-Cxq4ygFc.js → instance-snapshot-CjcwnEiV.js} +20 -14
  148. package/dist/jwt/index.d.ts +83 -5
  149. package/dist/jwt/index.js +143 -5
  150. package/dist/{kernel-5JatXyND.js → kernel-DVExUwkp.js} +138 -12
  151. package/dist/kysely/index.d.ts +3 -3
  152. package/dist/kysely/index.js +1 -1
  153. package/dist/load-DrMHXzgN.js +1 -0
  154. package/dist/{load-DFS_ry0W.js → load-DxroEzH1.js} +2 -2
  155. package/dist/{login-Dfe5RlYk.js → login-ClSJh5t5.js} +4 -4
  156. package/dist/{login-imhuwvn3.js → login-WC9HPJpU.js} +6 -10
  157. package/dist/{manifest-C8IzW3Do.js → manifest-B79YuF2T.js} +6 -2
  158. package/dist/{manifest-mx5ghSFM.d.ts → manifest-BVhExYhw.d.ts} +23 -2
  159. package/dist/{manifest-CtKR3GXL.js → manifest-Dv6q4i5s.js} +54 -35
  160. package/dist/{manifest-schema-C0kK_8V0.js → manifest-schema-Cv492Qev.js} +37 -7
  161. package/dist/{map-claims-D3oRmTk0.js → map-claims-etGIS_Dv.js} +14 -11
  162. package/dist/{map-error-TCAdw-eW.js → map-error-BQGyDm_M.js} +1 -1
  163. package/dist/mcp/index.d.ts +64 -10
  164. package/dist/mcp/index.js +151 -22
  165. package/dist/{migrate-BShP7Vf4.js → migrate-Dodel0IJ.js} +77 -24
  166. package/dist/nest/index.d.ts +5 -5
  167. package/dist/nest/index.js +3 -3
  168. package/dist/next/index.d.ts +9 -9
  169. package/dist/next/index.js +5 -5
  170. package/dist/next/plugin.d.ts +1 -1
  171. package/dist/next/plugin.js +2 -2
  172. package/dist/node/index.d.ts +5 -5
  173. package/dist/node/index.js +2 -2
  174. package/dist/openai/index.d.ts +5 -5
  175. package/dist/openai/index.js +3 -3
  176. package/dist/openapi/index.d.ts +14 -4
  177. package/dist/openapi/index.js +1 -1
  178. package/dist/{openapi-ahr8rHu3.js → openapi-DMocl1bh.js} +4 -4
  179. package/dist/{openapi-B7HZ0f-r.js → openapi-Ddb4628T.js} +2 -7
  180. package/dist/{openapi-DTaEmTSW.js → openapi-ztVaux6j.js} +8 -8
  181. package/dist/{operation-findings-DgATDpvh.js → operation-findings-kRcEp8lE.js} +1 -1
  182. package/dist/{operations-CxybZErY.d.ts → operations-BNLes61x.d.ts} +1 -1
  183. package/dist/orpc/index.d.ts +6 -6
  184. package/dist/orpc/index.js +4 -4
  185. package/dist/otel/index.d.ts +3 -3
  186. package/dist/otel/index.js +1 -1
  187. package/dist/{output-Dyw8fyPF.js → output-DgSDLrta.js} +7 -3
  188. package/dist/{output-files-DhRBBE4n.js → output-files-CCMdcFWb.js} +2 -2
  189. package/dist/output-files-DPAY7-GX.js +1 -0
  190. package/dist/{ownership-BatFgAA4.js → ownership-Z2LpxsGa.js} +1349 -883
  191. package/dist/parse-Ddhz2xf4.js +148 -0
  192. package/dist/{parse-local-manifest-CVSs6J9I.js → parse-local-manifest-T1Q8X3A2.js} +24 -1
  193. package/dist/{parse-local-manifest-DgqtruPn.d.ts → parse-local-manifest-e4mdwAKd.d.ts} +1 -1
  194. package/dist/pdp/index.d.ts +3 -3
  195. package/dist/pdp/index.js +7 -3
  196. package/dist/peer-12Q5I_RH.js +976 -0
  197. package/dist/{peer-CRvC7Hg1.js → peer-DOzzMfZL.js} +1 -1
  198. package/dist/{permdock-B9JxkBwC.js → permdock-BfWEeMqk.js} +177 -49
  199. package/dist/{permdock-D7eeLJER.d.ts → permdock-Dco6dyCK.d.ts} +34 -5
  200. package/dist/{permission-registry-Br4jSNVi.js → permission-registry-DpPtSKNZ.js} +1 -1
  201. package/dist/{vocabulary-D6lPdb4Z.d.ts → permission-types-DhNEmoRG.d.ts} +4 -62
  202. package/dist/{permissions-oEWfl-kl.d.ts → permissions-CoqCOfJ3.d.ts} +2 -1
  203. package/dist/{permissions-B-wCP5ZC.js → permissions-CyH2MV_B.js} +1 -1
  204. package/dist/{permissions-CZKiUfFM.js → permissions-DArULThq.js} +4 -4
  205. package/dist/pkce-5h8NgMQJ.js +21 -0
  206. package/dist/{policies-CO1oOymN.js → policies-B2lZIurj.js} +3 -3
  207. package/dist/{policy-Czo4n3Hs.d.ts → policy-B7dg_yzu.d.ts} +2 -2
  208. package/dist/{policy-DLZJ5gAp.js → policy-DaJy4nK4.js} +17 -8
  209. package/dist/{policy-from-catalog-DzhEc3Y9.js → policy-from-catalog-DFWYkNdu.js} +9 -9
  210. package/dist/{policy-types-DzwivBgR.d.ts → policy-types-B-F-qAZk.d.ts} +109 -5
  211. package/dist/postgres-store-BL9M_CA1.js +1001 -0
  212. package/dist/{postgrest-NUqZT-RB.d.ts → postgrest-CYacM_u7.d.ts} +12 -1
  213. package/dist/{postgrest-CW0IqC-U.js → postgrest-r5faDIzD.js} +47 -5
  214. package/dist/{powersync-BHfuehf3.js → powersync-13odBwiM.js} +3 -3
  215. package/dist/powersync-53ryOZip.js +1059 -0
  216. package/dist/powersync-CExtTLyA.js +1 -0
  217. package/dist/preset/index.js +1 -1
  218. package/dist/{preset-DZdU0tne.js → preset-CHTbd-DQ.js} +2 -2
  219. package/dist/prisma/index.d.ts +2 -2
  220. package/dist/prisma/index.js +1 -1
  221. package/dist/{problem-details-DXlt-vks.d.ts → problem-details-Tcfmj3bV.d.ts} +1 -1
  222. package/dist/prompt-DwtVemER.js +935 -0
  223. package/dist/{protected-DEPHc2xV.d.ts → protected-BwZYL1X_.d.ts} +6 -5
  224. package/dist/{protected-DfjY5mLA.js → protected-DXE3cQYg.js} +2 -2
  225. package/dist/{provider-CC-u3bYP.js → provider-BQsTYYy0.js} +2 -2
  226. package/dist/{provider-DMVt6yYn.d.ts → provider-Csk-THAn.d.ts} +1 -1
  227. package/dist/{provider-store-B5Yrkhzr.js → provider-store-IgqQipCO.js} +2 -2
  228. package/dist/{pull-BgIfno6w.js → pull-CN5OLxrF.js} +7 -7
  229. package/dist/pull-Cty6Ovyu.js +1 -0
  230. package/dist/{push-CmFVBOeI.js → push-tVdG8dUL.js} +54 -14
  231. package/dist/{pushed-policy-BImMTTIM.d.ts → pushed-policy-BbcY9r_4.d.ts} +1 -1
  232. package/dist/{pushed-policy-DobP7AHI.js → pushed-policy-CmYeSQqq.js} +1 -1
  233. package/dist/react/index.d.ts +6 -6
  234. package/dist/react/index.js +3 -3
  235. package/dist/react/provider-client.d.ts +1 -1
  236. package/dist/react/provider-client.js +1 -1
  237. package/dist/react-native/index.d.ts +25 -11
  238. package/dist/react-native/index.js +214 -24
  239. package/dist/{refs-K6eWUJ0H.js → refs-CNJBiTFo.js} +15 -1
  240. package/dist/{replay-D7iKcLFe.d.ts → replay-DCDD_ZfL.d.ts} +1 -1
  241. package/dist/{request-context-BTRTG7OT.js → request-context-BykKLmyE.js} +2 -2
  242. package/dist/resend/index.d.ts +4 -4
  243. package/dist/{retire-CALjIQ7e.js → retire-Wj6dkyDE.js} +2 -2
  244. package/dist/{rls-BA8an5Ap.js → rls-Ck_PocSp.js} +32 -8
  245. package/dist/{rls-j6t43t7n.js → rls-CxBZb4rZ.js} +478 -534
  246. package/dist/{role-builder-CXbis5-X.js → role-builder-C1VJzvcr.js} +3 -3
  247. package/dist/rolldown-runtime-C3I60J0A.js +4 -0
  248. package/dist/{rpc-aPyNi6tA.js → rpc-Bk1bE-ch.js} +1 -1
  249. package/dist/run-Bz7DXGEv.js +1 -0
  250. package/dist/{run-ticket-sxFI6LAk.js → run-ticket-B5d_63Ma.js} +22 -1
  251. package/dist/{run-ticket-BjhTOi6u.d.ts → run-ticket-BpNi7BCi.d.ts} +8 -3
  252. package/dist/{run-DOfMtc9V.js → run-uLD2aWuO.js} +7 -7
  253. package/dist/{runtime-D3VTAiCA.js → runtime-Vif3_-zf.js} +1 -1
  254. package/dist/{saas-FO-Q8oj0.js → saas-Az_Kz-4D.js} +7 -7
  255. package/dist/{scan-BOI5tJ-6.js → scan-DSljDE1Y.js} +1 -1
  256. package/dist/{schema-yLuBWWsh.js → schema-gIcCx7zM.js} +1 -1
  257. package/dist/scim/index.d.ts +3 -2
  258. package/dist/scim/index.js +3 -1
  259. package/dist/scim-C7JYhySg.js +44 -0
  260. package/dist/{scim-ClHtpyV3.js → scim-YNieBO1U.js} +3 -537
  261. package/dist/{scopes-CUPSjo9q.js → scopes-BHsc-wp-.js} +1 -1
  262. package/dist/server/index.d.ts +11 -11
  263. package/dist/server/index.js +7 -7
  264. package/dist/{server-DqCT4CgZ.js → server-Bnga6I50.js} +3 -3
  265. package/dist/{server-types-BLd4MnBX.d.ts → server-types-C4gZUEZy.d.ts} +9 -9
  266. package/dist/{shared-DvvFzYXe.js → shared-C8LjUdVU.js} +1 -1
  267. package/dist/{shared-CD11nBbC.js → shared-fMKOv8hP.js} +46 -39
  268. package/dist/{sink-Bj_lDUDq.d.ts → sink-Cp_Eot9W.d.ts} +4 -4
  269. package/dist/{skills-B6lVdD_W.js → skills-Dcjw9_1C.js} +5 -5
  270. package/dist/{skills-CTYwkl44.js → skills-g_3BS9NC.js} +3 -3
  271. package/dist/{snapshot-CXUWfsNy.js → snapshot-CbGmYiJx.js} +4 -4
  272. package/dist/{snapshot-cache-DZHQ0KF6.js → snapshot-cache-DT2Kx1F8.js} +1 -1
  273. package/dist/{snapshot-cache-DqK9eDmM.d.ts → snapshot-cache-Pahd3IYJ.d.ts} +1 -1
  274. package/dist/solid/index.d.ts +6 -5
  275. package/dist/solid/index.js +4 -4
  276. package/dist/solid-start/index.d.ts +6 -6
  277. package/dist/solid-start/index.js +3 -3
  278. package/dist/{sources-vs5dGOsS.js → sources-B-zYB4GS.js} +111 -25
  279. package/dist/{sources-BV9j0DeZ.d.ts → sources-DEEuGb8S.d.ts} +63 -14
  280. package/dist/sources-qoIJQrJv.js +11 -0
  281. package/dist/{sql-B5T1IL83.js → sql-B96movIM.js} +5 -1
  282. package/dist/sql-CDEPCA0g.d.ts +10 -0
  283. package/dist/{src-DLfUWFAI.js → src-DLFrtrrC.js} +154 -53
  284. package/dist/ssf/index.d.ts +4 -4
  285. package/dist/ssf/index.js +640 -211
  286. package/dist/{standard-webhooks-6lg8v_is.d.ts → standard-webhooks-B_qRg0ws.d.ts} +2 -2
  287. package/dist/{store-4u_hxjWa.js → store-DSP9oGvh.js} +15 -7
  288. package/dist/{store-options-BqEakYRa.js → store-options-B_poyYvg.js} +6 -6
  289. package/dist/{stores-ClZUgeoP.d.ts → stores-BAZwSYZA.d.ts} +6 -5
  290. package/dist/{stores-BbsD4fAR.js → stores-BqEuHC05.js} +2 -2
  291. package/dist/{stream-7-xmnf3U.d.ts → stream-2Vwhl7Er.d.ts} +2 -2
  292. package/dist/{style-Uao76wO7.js → style-Cqo7-73x.js} +1 -0
  293. package/dist/{style-DiKWnAvn.js → style-Ds1gNm77.js} +1 -1
  294. package/dist/supabase/index.d.ts +8 -7
  295. package/dist/supabase/index.js +5 -5
  296. package/dist/supabase/middleware.d.ts +6 -6
  297. package/dist/supabase/middleware.js +6 -6
  298. package/dist/{supabase-Dxlp8A94.js → supabase--0aJdLEd.js} +9 -7
  299. package/dist/{supabase-9pqI57pW.js → supabase-Bqp7iIY2.js} +3 -3
  300. package/dist/supabase-hook-DJxC4PoP.js +1 -0
  301. package/dist/{supabase-hook-DdDQhMlw.js → supabase-hook-Dg0SrQWR.js} +1069 -123
  302. package/dist/supautils-MESd81bF.js +689 -0
  303. package/dist/{support-session-C6xJQYut.js → support-session-Cna49-3f.js} +2 -2
  304. package/dist/svelte/index.d.ts +5 -5
  305. package/dist/svelte/index.js +5 -5
  306. package/dist/svelte/runtime.d.ts +3 -3
  307. package/dist/svelte/runtime.js +3 -3
  308. package/dist/svelte/source.d.ts +5 -5
  309. package/dist/svelte/source.js +2 -2
  310. package/dist/sveltekit/index.d.ts +6 -6
  311. package/dist/sveltekit/index.js +2 -2
  312. package/dist/tanstack-start/index.d.ts +6 -6
  313. package/dist/tanstack-start/index.js +2 -2
  314. package/dist/{tenancy-DN2QAx9z.js → tenancy-CmeBQ6Nv.js} +12 -3
  315. package/dist/terminal/index.d.ts +6 -6
  316. package/dist/terminal/index.js +3 -3
  317. package/dist/testing/core.d.ts +2 -0
  318. package/dist/testing/core.js +1 -0
  319. package/dist/testing/fixtures/index.d.ts +12 -0
  320. package/dist/testing/fixtures/index.js +770 -0
  321. package/dist/testing/index.d.ts +41 -174
  322. package/dist/testing/index.js +241 -731
  323. package/dist/testing/saas/index.d.ts +5 -5
  324. package/dist/testing/saas/index.js +2 -2
  325. package/dist/testing/saas/permissions.d.ts +1 -1
  326. package/dist/testing/saas/permissions.js +1 -1
  327. package/dist/text-diff-DhITNCnD.js +444 -0
  328. package/dist/{token-BLZcjQgt.js → token-2qYDvXz2.js} +1 -1
  329. package/dist/{tool-refusal-CMLN5xhn.js → tool-refusal-reAhIzdl.js} +1 -1
  330. package/dist/trpc/index.d.ts +6 -6
  331. package/dist/trpc/index.js +3 -3
  332. package/dist/{types-5Ut_pbKy.d.ts → types-BWZybqs9.d.ts} +112 -8
  333. package/dist/{types-CZTnPFzM.d.ts → types-BXMYB7BY.d.ts} +2 -2
  334. package/dist/{types-CdlxsYQh.d.ts → types-BfVmNJO5.d.ts} +14 -3
  335. package/dist/{types-BqAKcRNW.d.ts → types-CIeZcG8v.d.ts} +2 -2
  336. package/dist/{types-BNORmDM8.d.ts → types-CKV71kKh.d.ts} +4 -4
  337. package/dist/{types-tIgIeIKJ.d.ts → types-CQVEQawv.d.ts} +4 -4
  338. package/dist/{types-BjV-fqcA.d.ts → types-CeIscIKp.d.ts} +4 -4
  339. package/dist/{types-_sHy8BQf.d.ts → types-CfiKC5aN.d.ts} +1 -1
  340. package/dist/{types-ClZaWzfb.d.ts → types-D3A19w4A.d.ts} +8 -4
  341. package/dist/{types-C8-KNsFf.d.ts → types-DBHftjgS.d.ts} +15 -8
  342. package/dist/{types-CCpc2Dcv.d.ts → types-DC44-hqb.d.ts} +2 -2
  343. package/dist/{types-fbZ7JEXr.d.ts → types-DXmwu78Z.d.ts} +4 -4
  344. package/dist/{types-DiQjupG2.d.ts → types-cTos-H7p.d.ts} +2 -2
  345. package/dist/{types-DX0LaKTb.d.ts → types-g7Oy6Zg4.d.ts} +3 -3
  346. package/dist/unplugin/index.d.ts +1 -1
  347. package/dist/unplugin/index.js +2 -2
  348. package/dist/{usage-T5mXq98v.js → usage-Bybmck7f.js} +7 -7
  349. package/dist/{usage-DHtE8j4E.js → usage-CDaLXCfL.js} +2 -2
  350. package/dist/usage-y-kBNdqs.js +1 -0
  351. package/dist/{validation-error-Bg5Tpluk.d.ts → validation-error-CQpoquwj.d.ts} +1 -1
  352. package/dist/{verify-DbCL9bnB.js → verify-pe8rL_Qw.js} +350 -83
  353. package/dist/{views-DTIIO-oQ.js → views-BB8E9dTP.js} +1 -1
  354. package/dist/vocabulary-Bg3eeT2H.d.ts +67 -0
  355. package/dist/vue/index.d.ts +6 -5
  356. package/dist/vue/index.js +4 -4
  357. package/dist/{waiter-CKy4MQSY.d.ts → waiter-DwEyouan.d.ts} +2 -2
  358. package/dist/watch-Bd9mx3rd.js +1 -0
  359. package/dist/{watch-CszoTJMq.js → watch-C-4VmFlL.js} +3 -3
  360. package/dist/webmcp/index.d.ts +2 -2
  361. package/dist/webmcp/index.js +2 -2
  362. package/dist/{where-scope-Dv-WTP-w.js → where-scope-wq2coopv.js} +41 -21
  363. package/dist/{who-can-D0QoYbEb.js → who-can-BwNsI_Js.js} +6 -6
  364. package/dist/workflow/index.d.ts +3 -3
  365. package/dist/workflow/index.js +5 -5
  366. package/dist/workflow-sdk/index.d.ts +5 -5
  367. package/dist/{wrap-Bd1Tejur.d.ts → wrap-B6R0cMRL.d.ts} +2 -2
  368. package/dist/{wrap-gX61EtpB.js → wrap-CiSc_KCq.js} +8 -2
  369. package/package.json +22 -11
  370. package/schemas/cli-result-v1.json +1 -0
  371. package/schemas/cloud-api-v1.json +152 -7
  372. package/schemas/connector-v1.json +8 -0
  373. package/schemas/supabase-claims-v1.json +5 -0
  374. package/schemas/supabase-manifest-v1.json +276 -75
  375. package/skills/permdock/SKILL.md +1 -0
  376. package/skills/permdock-agents/references/runtimes.md +3 -1
  377. package/skills/permdock-approvals/references/stores-and-resume.md +2 -1
  378. package/skills/permdock-data/references/queries-and-rls.md +5 -2
  379. package/skills/permdock-tenancy/SKILL.md +1 -1
  380. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +2 -0
  381. package/skills/permdock-wire/references/adapters.md +14 -0
  382. package/skills/permdock-wire/references/policy-options.md +1 -0
  383. package/dist/catalog-DjhMYYCq.js +0 -1
  384. package/dist/collect-FlXJlhus.js +0 -1
  385. package/dist/index-D8EovfsP.d.ts +0 -91
  386. package/dist/load-BxEtwlBS.js +0 -1
  387. package/dist/output-files-B3IZJksC.js +0 -1
  388. package/dist/parse-Cxq0WxrA.js +0 -53
  389. package/dist/peer-C8swJ2GH.js +0 -50
  390. package/dist/powersync-CbzkqL_M.js +0 -1
  391. package/dist/powersync-bYUDLOAO.js +0 -538
  392. package/dist/prompt-DfZLJLIn.js +0 -32
  393. package/dist/pull-ByOks_Tg.js +0 -1
  394. package/dist/run-CNsApDpd.js +0 -1
  395. package/dist/supabase-hook-CXcGpHqq.js +0 -1
  396. package/dist/supautils-B6HYL9eL.js +0 -91
  397. package/dist/text-diff-BQcUapOb.js +0 -15
  398. package/dist/usage-CHOtwL19.js +0 -1
  399. package/dist/watch-Cb-NcaUw.js +0 -1
@@ -1,33 +1,37 @@
1
1
  import { a as sole, r as isRecord } from "./compact-CAf557ZB.js";
2
- import { a as hasConditionOp, c as isConditionRef } from "./refs-K6eWUJ0H.js";
3
- import { E as memoryCustomRoleSource, g as memoryRelationSource } from "./src-DLfUWFAI.js";
4
- import { c as listPermissions, h as formerKeys, n as findPermission } from "./permission-registry-Br4jSNVi.js";
2
+ import { l as isConditionRef, o as hasConditionOp } from "./refs-CNJBiTFo.js";
3
+ import { A as memoryCustomRoleSource, b as memoryRelationSource } from "./src-DLFrtrrC.js";
4
+ import { c as listPermissions, h as formerKeys, n as findPermission } from "./permission-registry-DpPtSKNZ.js";
5
5
  import { a as expandRelation, c as isEdgeRelation, d as isSelfParented, l as isFieldRelation, o as groupEntries, p as restrictedFor, u as isPrincipalRelation } from "./resource-relations-D_jw0BFx.js";
6
6
  import { f as nowMillis, u as isoAt } from "./time-DkWjdL98.js";
7
- import { t as canonicalJson } from "./canonical-json-BC8_nMTw.js";
8
- import { d as scopeList } from "./scopes-CUPSjo9q.js";
9
- import { o as requiresStandIn } from "./delegation-DaXVdDhM.js";
10
- import { o as flattenGrantee } from "./grantee-Cn1HyUsI.js";
11
- import { r as relationCondition, t as inheritCondition } from "./grantee-conditions-CcXf8hMM.js";
12
- import { p as scopeField } from "./tenancy-DN2QAx9z.js";
13
- import { s as policyLevels } from "./policy-DLZJ5gAp.js";
7
+ import { t as canonicalJson } from "./canonical-json-DwilZ1iB.js";
8
+ import { f as scopeList, l as rootScope, o as normalizeMemberships } from "./scopes-BHsc-wp-.js";
9
+ import { o as requiresStandIn } from "./delegation-C5rOdTp5.js";
10
+ import { o as flattenGrantee } from "./grantee-BrRANrpT.js";
11
+ import { r as relationCondition, t as inheritCondition } from "./grantee-conditions-C6P1Tvol.js";
12
+ import { p as scopeField } from "./tenancy-CmeBQ6Nv.js";
13
+ import { c as policyLevels } from "./policy-DaJy4nK4.js";
14
14
  import { t as requiresApproval } from "./approval-required-TzNB9oQA.js";
15
- import { _ as membershipsClaim, c as andWhere, g as leveled, p as customRoleScope } from "./evaluate-_R8QkWaf.js";
16
- import { t as getPermDock } from "./permdock-B9JxkBwC.js";
17
- import { a as describeError, i as configError, u as usageResult } from "./errors-CWTY6uih.js";
15
+ import { c as andWhere, m as customRoleScope, v as leveled, y as membershipsClaim } from "./evaluate-B_oqFbWC.js";
16
+ import { t as getPermDock } from "./permdock-BfWEeMqk.js";
17
+ import { a as describeError, i as configError, u as usageResult } from "./errors-DpP_U6Bf.js";
18
18
  import { t as policyRowConditionKeys } from "./row-conditions-h2HythXQ.js";
19
- import { s as jsonSchemaOf } from "./catalog-doc-C9wjsfNY.js";
20
- import { o as loadPolicyAt } from "./load-DFS_ry0W.js";
21
- import { c as relationArmSql, u as restrictedRowsSql } from "./compile-CMqMx_IN.js";
19
+ import { s as writeFileEnsuringDir } from "./files-D_JIzUrP.js";
20
+ import { c as jsonSchemaOf } from "./catalog-doc-CV9s6B1S.js";
21
+ import { o as loadPolicyAt } from "./load-DxroEzH1.js";
22
+ import { i as qualifySqlTable, n as defaultSqlCommand, t as SQL_IDENT } from "./sql-B96movIM.js";
23
+ import { c as relationArmSql, i as scopeMembershipTable, r as scopeColumn, u as restrictedRowsSql } from "./compile-BAEO5bOk.js";
22
24
  import "./budget-NbEtbJC_.js";
23
- import { i as qualifySqlTable, n as defaultSqlCommand } from "./sql-B5T1IL83.js";
24
- import "./sources-vs5dGOsS.js";
25
+ import "./sources-B-zYB4GS.js";
25
26
  import { t as beforeFirst } from "./text-BMFRfBqc.js";
26
- import { n as fixtureSubject, r as loadFixtures, t as fixtureRow } from "./fixtures-B7XrLeY7.js";
27
- import { F as quoteQualified, I as quoteTable, M as qualified, N as quoteIdent, P as quoteLiteral, T as columnTypesOf, _ as subjectClaimJsonSql, a as customRolesOn, j as helperSchema, r as HELPERS, v as subjectClaimSql, w as arrayColumnsOf } from "./shared-CD11nBbC.js";
28
- import { d as connectPgPool, f as pgConnector, l as validitySql, s as andSql, u as wrapSql } from "./policies-CO1oOymN.js";
29
- import { B as linkHelper, D as breakGlassHolder, F as graphHelper, I as graphSqlName, J as restrictedHelper, L as graphSqlText, M as contextRefs, N as sqlFunctionNames, O as breakGlassKey, P as CLOSURE, Q as activeUserSql, X as scopeTable, j as compileConditionSql, k as collectGrants, m as accessSql, p as requiresSql, v as capabilityAccessSql, w as apiKeyAllowsCall } from "./ownership-BatFgAA4.js";
30
- import { s as viewName, t as FIELD_VIEWS } from "./fields-D9tPVUUS.js";
27
+ import { t as DOCS_BASE } from "./manifest-Dv6q4i5s.js";
28
+ import { n as fixtureSubject, r as loadFixtures, t as fixtureRow } from "./fixtures-BTMW6zgU.js";
29
+ import { A as quoteQualified, D as qualified, E as helperSchema, N as arrayColumnsOf, O as quoteIdent, P as columnTypesOf, _ as subjectClaimJsonSql, a as customRolesOn, j as quoteTable, k as quoteLiteral, r as HELPERS, v as subjectClaimSql } from "./shared-fMKOv8hP.js";
30
+ import { B as sqlFunctionNames, F as collectGrants, H as graphHelper, N as breakGlassHolder, P as breakGlassKey, R as compileConditionSql, U as graphSqlName, V as CLOSURE, W as graphSqlText, at as activeUserSql, et as permittedIdsHelper, h as accessSql, k as apiKeyAllowsCall, m as requiresSql, q as linkHelper, rt as scopeTable, tt as restrictedHelper, x as capabilityAccessSql, y as tokenScopeAllowsCall, z as contextRefs } from "./ownership-Z2LpxsGa.js";
31
+ import { t as membershipSourcesOf } from "./sources-qoIJQrJv.js";
32
+ import { d as connectPgPool, f as pgConnector, l as validitySql, s as andSql, u as wrapSql } from "./policies-B2lZIurj.js";
33
+ import { s as viewName, t as FIELD_VIEWS } from "./fields-ClcQLrVc.js";
34
+ import { resolve } from "node:path";
31
35
  import { createHash, randomUUID } from "node:crypto";
32
36
  //#region src/cli/rls/indexes.ts
33
37
  /** Postgres truncates identifiers longer than this, in bytes. */
@@ -279,7 +283,7 @@ function capabilityAccess(item, policy, ctx) {
279
283
  if (hops.length === 0) return;
280
284
  return hops.length === 1 ? hops[0] : hops.map(wrapSql).join(" or ");
281
285
  }
282
- function prepare(item, tables, warnings, skipClosures, actions, rowActions = false) {
286
+ function prepare(item, tables, warnings, skipClosures, sql, rowActions = false) {
283
287
  const { grant, label } = item;
284
288
  if (grant.breakGlass !== void 0) {
285
289
  warnings.push(`break-glass grant ${label}/${grant.permission.key} reads through permdock_break_glass_${grant.permission.resource}, not a policy`);
@@ -304,9 +308,14 @@ function prepare(item, tables, warnings, skipClosures, actions, rowActions = fal
304
308
  warnings.push(`skipped approval grant ${label}/${grant.permission.key}`);
305
309
  return;
306
310
  }
307
- const command = commandFor(grant.permission.action, actions);
311
+ const tableless = sql.tableless?.has(grant.permission.resource) === true;
312
+ const command = tableless ? void 0 : commandFor(grant.permission.action, sql.actions);
308
313
  const table = tableFor$1(grant.permission.resource, tables);
309
314
  if (command === void 0) {
315
+ if (tableless && item.access.kind !== "role") {
316
+ warnings.push(`skipped ${label}/${grant.permission.key}: rls.tables.${grant.permission.resource} is false, so the resource has no table, and only role grants are seeded`);
317
+ return;
318
+ }
310
319
  if (item.access.kind !== "role" && rowActions) return {
311
320
  item,
312
321
  command: "none",
@@ -384,19 +393,19 @@ function groupOf(permission, list) {
384
393
  return names[0];
385
394
  }
386
395
  /**
387
- * One entry per level for every allow of an assignable role on a resource
388
- * with levels, keyed `<grant key>@<level>`. Only `permdock_custom_keys`
389
- * hands these keys out, to a custom role whose stored allow names the level.
396
+ * One entry per level for every allow of a role on a resource with levels,
397
+ * keyed `<grant key>@<level>`, whether or not the role is assignable: every
398
+ * role holds the same leveled keys, and `permdock_ceiling` keeps only the
399
+ * assignable roles'. Only `permdock_custom_keys` hands these keys out, to a
400
+ * custom role whose stored allow names the level.
390
401
  */
391
402
  function levelEntries(policy, ctx, keys, tables, warnings, skipClosures) {
392
- const custom = ctx.customRoles;
393
- if (custom?.levels !== true) return [];
394
- const assignable = new Set(custom.assignable);
403
+ if (ctx.customRoles?.levels !== true) return [];
395
404
  const out = [];
396
405
  for (const [entry, grantKey] of Array.from(keys)) {
397
406
  const { item } = entry;
398
407
  const { grant } = item;
399
- if (item.access.kind !== "role" || grant.effect !== "allow" || grant.permission.kind !== "instance" || !assignable.has(item.access.role)) continue;
408
+ if (item.access.kind !== "role" || grant.effect !== "allow" || grant.permission.kind !== "instance") continue;
400
409
  if (grant.permission.key.includes("@")) throw configError(`PermDock CLI: permission key '${grant.permission.key}' holds '@', which separates a level in custom-role grant keys`);
401
410
  for (const [level, condition] of policyLevels(policy, grant.permission.resource)) {
402
411
  const where = andWhere(item.where, condition);
@@ -404,7 +413,7 @@ function levelEntries(policy, ctx, keys, tables, warnings, skipClosures) {
404
413
  ...item,
405
414
  grant: leveled(grant, level, condition),
406
415
  ...where === void 0 ? {} : { where }
407
- }, tables, warnings, skipClosures, ctx.actions);
416
+ }, tables, warnings, skipClosures, ctx);
408
417
  if (prepared !== void 0) {
409
418
  keys.set(prepared, `${grantKey}@${level}`);
410
419
  out.push(prepared);
@@ -432,10 +441,10 @@ const PERMANENT_USER = `((select auth.jwt()) ->> 'is_anonymous') is distinct fro
432
441
  function compileGrants(policy, ctx, tables, warnings, skipClosures, rowActions = false) {
433
442
  const items = collectGrants(policy);
434
443
  const entries = items.flatMap((item) => {
435
- const entry = prepare(item, tables, warnings, skipClosures, ctx.actions, rowActions);
444
+ const entry = prepare(item, tables, warnings, skipClosures, ctx, rowActions);
436
445
  return entry === void 0 ? [] : [entry];
437
446
  });
438
- const keys = assignKeys(entries, ctx.fields === "views");
447
+ const keys = assignKeys(entries, ctx.fields !== void 0);
439
448
  entries.push(...levelEntries(policy, ctx, keys, tables, warnings, skipClosures));
440
449
  const conditionedKeys = /* @__PURE__ */ new Set();
441
450
  for (const [entry, grantKey] of keys) if (entry.using !== void 0 || entry.check !== void 0 || entry.item.grant.validity !== void 0 || entry.item.grant.requires !== void 0) conditionedKeys.add(grantKey);
@@ -492,7 +501,7 @@ function compileGrants(policy, ctx, tables, warnings, skipClosures, rowActions =
492
501
  };
493
502
  rows.set(`${row.role}\u0000${row.grantKey}\u0000${row.scope}`, row);
494
503
  }
495
- if (!rowActions) continue;
504
+ if (!rowActions || ctx.tableless?.has(grant.permission.resource)) continue;
496
505
  }
497
506
  const actionOnly = entry.command === "none";
498
507
  const command = actionOnly ? "select" : entry.command;
@@ -506,8 +515,10 @@ function compileGrants(policy, ctx, tables, warnings, skipClosures, rowActions =
506
515
  const grantKey = keys.get(entry);
507
516
  let accessExpr;
508
517
  if (access.kind === "role" && grantKey !== void 0) {
509
- const column = access.scope === "global" ? void 0 : scopeField(policy.resources.get(grant.permission.resource), access.scope, policy.scopes);
510
- accessExpr = accessSql(ctx, access.scope, grantKey, column);
518
+ const via = ctx.vias?.[grant.permission.resource];
519
+ if (via !== void 0 && access.scope !== "global" && access.scope !== via.scope) throw configError(`PermDock CLI: ${label}/${grant.permission.key} is granted at scope ${access.scope}, but rls.tables.${grant.permission.resource}.via reaches ${via.scope}; map the scope with via.scope or grant at ${via.scope}`);
520
+ const column = access.scope === "global" ? void 0 : via?.key ?? scopeField(policy.resources.get(grant.permission.resource), access.scope, policy.scopes);
521
+ accessExpr = accessSql(ctx, access.scope, grantKey, column, access.scope === "global" ? void 0 : via?.helper);
511
522
  if (column !== void 0) filters(grant.permission.resource, table, column);
512
523
  const row = {
513
524
  role: access.role,
@@ -529,8 +540,10 @@ function compileGrants(policy, ctx, tables, warnings, skipClosures, rowActions =
529
540
  accessExpr = andSql(accessExpr, validity);
530
541
  for (const key of grant.requires ?? []) accessExpr = andSql(accessExpr, requiresSql(ctx, key, policy.resources.get(grant.permission.resource)));
531
542
  if (ctx.anonymousSignIns === "deny" && access.kind !== "anyone") accessExpr = andSql(accessExpr, PERMANENT_USER);
532
- if (ctx.apiKeys !== void 0 && grant.effect === "allow" && access.kind !== "anyone" && access.kind !== "role") {
533
- const calls = (requiresStandIn(grant) ? grant.requires ?? [] : [grant.permission.key, ...grant.requires ?? []]).map((key) => `(select ${apiKeyAllowsCall(ctx, quoteLiteral(key))})`);
543
+ if ((ctx.apiKeys !== void 0 || ctx.tokenScopes !== void 0) && grant.effect === "allow" && access.kind !== "anyone" && access.kind !== "role") {
544
+ const covered = requiresStandIn(grant) ? grant.requires ?? [] : [grant.permission.key, ...grant.requires ?? []];
545
+ const ceilings = [...ctx.apiKeys === void 0 ? [] : [apiKeyAllowsCall], ...ctx.tokenScopes === void 0 ? [] : [tokenScopeAllowsCall]];
546
+ const calls = covered.flatMap((key) => ceilings.map((call) => `(select ${call(ctx, quoteLiteral(key))})`));
534
547
  accessExpr = andSql(accessExpr, calls.length === 1 ? calls[0] ?? "" : `(${calls.join(" and ")})`);
535
548
  }
536
549
  const using = compileOptional(entry.using, rowCtx);
@@ -697,6 +710,229 @@ function rowConditionMessage(policy, keys) {
697
710
  }
698
711
  const ROW_CONDITION_FIX = "call permitted_<scope>_ids_by_permission('<key>') or permdock_has_permission('<key>'), which count only the allows without a row condition (a relationship grant never reaches a topic or a folder), or use a permission whose catalog entry has rowConditions: false";
699
712
  //#endregion
713
+ //#region src/cli/sql/tables.ts
714
+ /** The `schema.table` an `rls.tables` entry names, or `resource` when it names none or is `false`. */
715
+ function tableNameOf(entry, resource) {
716
+ if (entry === void 0 || entry === false) return resource;
717
+ return typeof entry === "string" ? entry : entry.table ?? resource;
718
+ }
719
+ /** `rls.tables` as resource to table name, the `via` objects reduced to their `table` and the `false` entries left out. */
720
+ function tableNames(tables) {
721
+ return tables === void 0 ? void 0 : Object.fromEntries(Object.entries(tables).filter(([, entry]) => entry !== false).map(([resource, entry]) => [resource, tableNameOf(entry, resource)]));
722
+ }
723
+ /** The resources `rls.tables` marks `false`: no table, so no policies. */
724
+ function tablelessResources(tables) {
725
+ return new Set(Object.entries(tables ?? {}).filter(([, entry]) => entry === false).map(([resource]) => resource));
726
+ }
727
+ function singular(name) {
728
+ if (name.endsWith("ies")) return `${name.slice(0, -3)}y`;
729
+ if (name.endsWith("sses")) return name.slice(0, -2);
730
+ return name.endsWith("s") && !name.endsWith("ss") ? name.slice(0, -1) : name;
731
+ }
732
+ /** The `via` entries of `rls.tables`, by resource. */
733
+ function resolveVias(tables, scopes, dialect) {
734
+ const out = {};
735
+ for (const [resource, entry] of Object.entries(tables ?? {})) {
736
+ if (typeof entry === "string" || entry === false) continue;
737
+ const { via } = entry;
738
+ const scope = via.scope ?? scopes[0]?.name;
739
+ if (scope === void 0 || !scopes.some((item) => item.name === scope)) throw configError(`PermDock CLI: rls.tables.${resource}.via.scope '${scope ?? ""}' is not a scope of the policy (${scopes.map((item) => item.name).join(", ")})`);
740
+ const name = singular(via.table.slice(via.table.lastIndexOf(".") + 1));
741
+ out[resource] = {
742
+ helper: permittedIdsHelper(name),
743
+ key: via.key ?? `${name}_id`,
744
+ scope,
745
+ table: via.table.includes(".") ? via.table : `public.${via.table}`,
746
+ column: via.column,
747
+ id: via.id ?? "id",
748
+ type: via.type ?? (dialect === "supabase" ? "uuid" : "text")
749
+ };
750
+ }
751
+ const helpers = /* @__PURE__ */ new Map();
752
+ for (const [resource, via] of Object.entries(out)) {
753
+ const seen = helpers.get(via.helper);
754
+ if (seen !== void 0 && (seen.table !== via.table || seen.column !== via.column || seen.id !== via.id || seen.scope !== via.scope || seen.type !== via.type)) throw configError(`PermDock CLI: rls.tables.${resource}.via names ${via.helper}, which another resource defines over a different parent; give the parents different table names`);
755
+ helpers.set(via.helper, via);
756
+ }
757
+ return Object.keys(out).length === 0 ? void 0 : out;
758
+ }
759
+ //#endregion
760
+ //#region src/cli/rls/verify-findings.ts
761
+ const VERIFY_DOCS = `${DOCS_BASE}/rls#verify`;
762
+ function rlsFinding(code, table, key, message, severity = "error") {
763
+ return {
764
+ code,
765
+ table,
766
+ key,
767
+ message,
768
+ severity
769
+ };
770
+ }
771
+ /** `<code>:<table>:<key>`: what `--ignore` and `rls.verify.ignore` name. */
772
+ function findingId(finding) {
773
+ return `${finding.code}:${finding.table}:${finding.key}`;
774
+ }
775
+ /** `rls.verify.ignore`, checked, then one entry per `--ignore` id. */
776
+ function verifyIgnores(config, flags = []) {
777
+ const entries = config.rls?.verify?.ignore ?? [];
778
+ if (!Array.isArray(entries)) throw configError("PermDock CLI: rls.verify.ignore must be a list of { id, reason }");
779
+ const out = [];
780
+ for (const [index, entry] of entries.entries()) {
781
+ if (!isRecord(entry) || typeof entry["id"] !== "string" || entry["id"] === "" || typeof entry["reason"] !== "string" || entry["reason"].trim() === "") throw configError(`PermDock CLI: rls.verify.ignore[${String(index)}] needs an id and a non-empty reason`);
782
+ out.push({
783
+ id: entry["id"],
784
+ reason: entry["reason"]
785
+ });
786
+ }
787
+ for (const id of flags) out.push({
788
+ id,
789
+ reason: "--ignore"
790
+ });
791
+ return out;
792
+ }
793
+ /** Splits `findings` by `ignores`; an id listed twice counts once, with its first reason. */
794
+ function applyIgnores(findings, ignores) {
795
+ const reasons = /* @__PURE__ */ new Map();
796
+ for (const entry of ignores) if (!reasons.has(entry.id)) reasons.set(entry.id, entry.reason);
797
+ const matched = /* @__PURE__ */ new Set();
798
+ const kept = [];
799
+ const ignored = [];
800
+ for (const finding of findings) {
801
+ const id = findingId(finding);
802
+ const reason = reasons.get(id);
803
+ if (reason === void 0) kept.push({
804
+ ...finding,
805
+ id
806
+ });
807
+ else {
808
+ matched.add(id);
809
+ ignored.push({
810
+ id,
811
+ reason,
812
+ message: finding.message
813
+ });
814
+ }
815
+ }
816
+ return {
817
+ findings: kept,
818
+ ignored,
819
+ stale: [...reasons].filter(([id]) => !matched.has(id)).map(([id, reason]) => ({
820
+ id,
821
+ reason
822
+ }))
823
+ };
824
+ }
825
+ function prefixOf(severity) {
826
+ switch (severity) {
827
+ case "error": return "";
828
+ case "warning": return "warning: ";
829
+ case "info": return "info: ";
830
+ default: return severity;
831
+ }
832
+ }
833
+ /**
834
+ * The `rls verify` result: exit 1 when an error finding is left after the
835
+ * ignores. Text lines carry each finding's id; `--json` data is
836
+ * `{ findings, ignored, stale }`; `--format github|sarif` renders `findings`.
837
+ */
838
+ function verifyResult(input) {
839
+ const report = applyIgnores(input.findings, input.ignore);
840
+ const failed = report.findings.some((item) => item.severity === "error");
841
+ const lines = [
842
+ ...report.findings.map((item) => `${prefixOf(item.severity)}${item.message} [${item.id}]`),
843
+ ...report.ignored.map((item) => `ignored ${item.id}: ${item.reason}`),
844
+ ...report.stale.map((item) => `warning: ignore entry ${item.id} matches no finding; remove it from rls.verify.ignore`),
845
+ ...failed ? [] : [input.summary],
846
+ ...input.notes ?? []
847
+ ];
848
+ return {
849
+ code: failed ? 1 : 0,
850
+ output: lines.join("\n"),
851
+ data: report,
852
+ findings: [...report.findings.map((item) => ({
853
+ code: item.code,
854
+ id: item.id,
855
+ severity: item.severity,
856
+ message: item.message,
857
+ docs: VERIFY_DOCS
858
+ })), ...report.stale.map((item) => ({
859
+ code: "ignore-stale",
860
+ id: `ignore-stale:${item.id}`,
861
+ severity: "warning",
862
+ message: `ignore entry ${item.id} matches no finding`,
863
+ fix: "remove it from rls.verify.ignore",
864
+ docs: VERIFY_DOCS
865
+ }))]
866
+ };
867
+ }
868
+ //#endregion
869
+ //#region src/cli/rls/verify-pgtap-memberships.ts
870
+ function insert(table, columns) {
871
+ return `insert into ${quoteTable(table)} (${columns.map(([name]) => quoteIdent(name)).join(", ")}) values (${columns.map(([, value]) => quoteLiteral(value)).join(", ")}) on conflict do nothing;`;
872
+ }
873
+ /** The rows of a table mapped by `rls.memberships`: one per role, for a plain role column. */
874
+ function mappedRows(config, scopes, user, membership) {
875
+ const { scope, id } = membership;
876
+ if (scope === void 0 || id === void 0) return [];
877
+ const table = scopeMembershipTable(config.rls?.memberships, scopes, scope);
878
+ const idColumn = table === void 0 ? void 0 : scopeColumn(table, scopes, scope);
879
+ const roleColumn = table?.role;
880
+ if (table === void 0 || idColumn === void 0 || typeof roleColumn !== "string") return [];
881
+ const rootName = rootScope(scopes);
882
+ const tenantColumn = rootName === void 0 || rootName === scope ? void 0 : scopeColumn(table, scopes, rootName);
883
+ const tenant = rootName === void 0 ? void 0 : membership.within?.[rootName];
884
+ const extra = [];
885
+ for (const [name, value] of Object.entries(membership.within ?? {})) {
886
+ const column = scopeColumn(table, scopes, name);
887
+ if (column !== void 0 && name !== scope) extra.push([column, value]);
888
+ }
889
+ if (tenantColumn !== void 0 && tenant !== void 0 && !extra.some(([column]) => column === tenantColumn)) extra.push([tenantColumn, tenant]);
890
+ return membership.roles.map((role) => insert(table.table, [
891
+ [table.user, user],
892
+ [idColumn, id],
893
+ ...extra,
894
+ [roleColumn, role]
895
+ ]));
896
+ }
897
+ /** The rows of a `membershipSources` source: only a source whose columns are plain, never a `through` or `map`. */
898
+ function sourceRows(source, scopes, user, membership) {
899
+ const { scope, id } = membership;
900
+ if (scope === void 0 || id === void 0) return [];
901
+ const names = new Set(scopes.map((entry) => entry.name));
902
+ if ("through" in source.user || !names.has(scope) || "value" in source.scope && source.scope.value !== scope) return [];
903
+ const role = source.role;
904
+ const roleColumns = Array.isArray(role) || !("column" in role) || "through" in role ? void 0 : "map" in role ? void 0 : role.column;
905
+ const fixed = "value" in source.scope ? [] : [[source.scope.column, scope]];
906
+ const within = source.within;
907
+ const ancestors = within === void 0 || !("columns" in within) ? [] : Object.entries(within.columns).flatMap(([name, column]) => {
908
+ const value = membership.within?.[name];
909
+ return value === void 0 ? [] : [[column, value]];
910
+ });
911
+ const base = [
912
+ [source.user.column, user],
913
+ [source.id.column, id],
914
+ ...fixed,
915
+ ...ancestors
916
+ ];
917
+ if (roleColumns === void 0) return [];
918
+ return membership.roles.map((value) => insert(source.table, [...base, [roleColumns, value]]));
919
+ }
920
+ /**
921
+ * The statements that put a fixture's memberships into the configured
922
+ * membership tables and sources, so the helpers of `authorize: 'database'`
923
+ * find them. A membership no plain table or source can hold (a `through`
924
+ * or mapped role column, an `on` membership) is listed in a comment.
925
+ */
926
+ function fixtureMembershipSql(config, scopes, fixture, sources) {
927
+ const lines = [];
928
+ for (const membership of normalizeMemberships(fixture.subject.memberships ?? [], scopes)) {
929
+ const rows = [...mappedRows(config, scopes, fixture.subject.id, membership), ...sources.flatMap((source) => sourceRows(source, scopes, fixture.subject.id, membership))];
930
+ if (rows.length === 0) lines.push(`-- no membership table holds ${membership.scope ?? "on"} ${membership.id ?? ""}: not seeded`);
931
+ lines.push(...rows);
932
+ }
933
+ return lines;
934
+ }
935
+ //#endregion
700
936
  //#region src/cli/rls/verify-pgtap.ts
701
937
  /** A custom role's scope and pinned instance, as the `custom_role_*` tables store them. */
702
938
  function customRoleAt(role, scopes) {
@@ -789,7 +1025,16 @@ function subjectSettings(fixture, subject) {
789
1025
  const roles = fixture.subject.roles ?? [];
790
1026
  const memberships = membershipsClaim(fixture.subject.memberships ?? [], subject.customRoles, subject.scopes);
791
1027
  if (subject.dialect === "guc") {
1028
+ const fixed = /* @__PURE__ */ new Set([
1029
+ "user_id",
1030
+ "sub",
1031
+ "role",
1032
+ "memberships",
1033
+ subject.roleClaim,
1034
+ subject.tenantClaim
1035
+ ]);
792
1036
  const settings = [
1037
+ ...Object.entries(fixture.subject.claims ?? {}).flatMap(([name, value]) => fixed.has(name) || !SQL_IDENT.test(name) ? [] : [[`${subject.gucPrefix}.${name}`, typeof value === "string" ? value : JSON.stringify(value)]]),
793
1038
  [`${subject.gucPrefix}.user_id`, fixture.subject.id],
794
1039
  [`${subject.gucPrefix}.${subject.roleClaim}`, roles.join(",")],
795
1040
  [`${subject.gucPrefix}.memberships`, JSON.stringify(memberships)]
@@ -839,9 +1084,12 @@ function customRoleRows(schema, customRoles, scopes) {
839
1084
  }
840
1085
  return rows;
841
1086
  }
842
- function seedsCustomRoleTables(config) {
1087
+ function databaseMode(config) {
843
1088
  const rls = config.rls;
844
- return customRolesOn(rls) && (rls?.authorize ?? rls?.rbac?.authorize ?? "jwt") === "database";
1089
+ return (rls?.authorize ?? rls?.rbac?.authorize ?? "jwt") === "database";
1090
+ }
1091
+ function seedsCustomRoleTables(config) {
1092
+ return customRolesOn(config.rls) && databaseMode(config);
845
1093
  }
846
1094
  function customRoleSchema(config) {
847
1095
  return config.rls?.schema ?? config.rls?.rbac?.schema ?? "permdock";
@@ -859,6 +1107,7 @@ function emitPgtap(input) {
859
1107
  PGTAP_DECISION_SQL
860
1108
  ];
861
1109
  if (seedsCustomRoleTables(input.config)) for (const row of customRoleRows(customRoleSchema(input.config), input.customRoles, scopes)) lines.push(`${inlineStatement(row)};`);
1110
+ const sources = membershipSourcesOf(input.config).map((source) => source.sql.manifest);
862
1111
  for (const [index, fixture] of input.fixtures.entries()) {
863
1112
  const permission = findPermission(input.policy.permissions, fixture.action);
864
1113
  const status = input.inProcess[index];
@@ -868,10 +1117,14 @@ function emitPgtap(input) {
868
1117
  lines.push(`select skip(${quoteLiteral(`${label}: opaque grant untestable app-side`)}, 1);`);
869
1118
  continue;
870
1119
  }
1120
+ if (input.config.rls?.tables?.[permission.resource] === false) {
1121
+ lines.push(`select skip(${quoteLiteral(`${label}: rls.tables.${permission.resource} is false, so there is no table`)}, 1);`);
1122
+ continue;
1123
+ }
871
1124
  const outcome = status.granted ? "granted" : "denied";
872
- const table = input.config.rls?.tables?.[permission.resource] ?? permission.resource;
1125
+ const table = tableNameOf(input.config.rls?.tables?.[permission.resource], permission.resource);
873
1126
  const statement = inlineStatement(statementFor(fixture, permission.action, table));
874
- lines.push(`-- ${label}`, "savepoint permdock_fixture;", "set local role \"authenticated\";", ...subjectSettings(fixture, subject).map(([name, value]) => `select set_config(${quoteLiteral(name)}, ${quoteLiteral(value)}, true);`), `select is(${PGTAP_DECISION}(${quoteLiteral(statement)}), ${quoteLiteral(outcome)}, ${quoteLiteral(`${label} ${outcome}`)});`, "rollback to savepoint permdock_fixture;");
1127
+ lines.push(`-- ${label}`, "savepoint permdock_fixture;", ...databaseMode(input.config) ? fixtureMembershipSql(input.config, scopes, fixture, sources) : [], "set local role \"authenticated\";", ...subjectSettings(fixture, subject).map(([name, value]) => `select set_config(${quoteLiteral(name)}, ${quoteLiteral(value)}, true);`), `select is(${PGTAP_DECISION}(${quoteLiteral(statement)}), ${quoteLiteral(outcome)}, ${quoteLiteral(`${label} ${outcome}`)});`, "rollback to savepoint permdock_fixture;");
875
1128
  }
876
1129
  lines.push("select * from finish();", "rollback;");
877
1130
  return `${lines.join("\n")}\n`;
@@ -1399,7 +1652,7 @@ async function seedRows(query, table, rows, given, entropy) {
1399
1652
  async function verifyTree(input) {
1400
1653
  const { policy, query } = input;
1401
1654
  const entropy = input.entropy ?? SYSTEM_ENTROPY;
1402
- const tables = input.config.rls?.tables;
1655
+ const tables = tableNames(input.config.rls?.tables);
1403
1656
  const treeValues = input.config.rls?.treeValues ?? {};
1404
1657
  const seed = (table, list) => seedRows(query, table, list, treeValues[table] ?? {}, entropy);
1405
1658
  const walked = [...graphPlan(policy).values()].filter((entry) => entry.closure !== void 0);
@@ -1506,7 +1759,7 @@ async function verifyTree(input) {
1506
1759
  checked += 1;
1507
1760
  const id = String(row[node.id]);
1508
1761
  const allowed = permdock.can(permission, row);
1509
- if (allowed !== seen.has(id)) mismatches.push(`${permission.key} ${id}: in-process ${allowed ? "granted" : "denied"}, database ${seen.has(id) ? "allowed" : "filtered"}`);
1762
+ if (allowed !== seen.has(id)) mismatches.push(rlsFinding("tree-mismatch", node.name, permission.key, `${permission.key} ${id}: in-process ${allowed ? "granted" : "denied"}, database ${seen.has(id) ? "allowed" : "filtered"}`));
1510
1763
  else if (allowed) granted += 1;
1511
1764
  }
1512
1765
  }
@@ -1520,6 +1773,10 @@ async function verifyTree(input) {
1520
1773
  }
1521
1774
  //#endregion
1522
1775
  //#region src/cli/rls/verify-database.ts
1776
+ /** A fixture's part of a finding id: its subject and row. */
1777
+ function fixtureKey(fixture) {
1778
+ return `${fixture.subject.id}/${String(rowId(fixture.row))}`;
1779
+ }
1523
1780
  /** Columns of `row` that hold a value; a masked column reads as null. */
1524
1781
  function valuedColumns(row) {
1525
1782
  return isRecord(row) ? Object.keys(row).filter((name) => row[name] !== null && row[name] !== void 0).toSorted() : [];
@@ -1536,8 +1793,9 @@ function expectedFields(granted, picked, key, row) {
1536
1793
  }
1537
1794
  function fieldsMismatch(fixture, want, seen) {
1538
1795
  const kept = want.join(", ");
1539
- if (typeof seen === "string") return [`${fixture.action}: field view read failed (${seen}), pick keeps [${kept}]`];
1540
- return seen.join(", ") === kept ? [] : [`${fixture.action} ${String(rowId(fixture.row))}: field view returns [${seen.join(", ")}], pick keeps [${kept}]`];
1796
+ const mismatch = (message) => rlsFinding("field-mismatch", fixture.action, fixtureKey(fixture), message);
1797
+ if (typeof seen === "string") return [mismatch(`${fixture.action}: field view read failed (${seen}), pick keeps [${kept}]`)];
1798
+ return seen.join(", ") === kept ? [] : [mismatch(`${fixture.action} ${String(rowId(fixture.row))}: field view returns [${seen.join(", ")}], pick keeps [${kept}]`)];
1541
1799
  }
1542
1800
  /** The field view's columns for the fixture's row: the view, or the table itself when no grant limits its fields. */
1543
1801
  async function viewFields(query, table, key) {
@@ -1590,7 +1848,7 @@ async function verifyAgainstDatabase(input) {
1590
1848
  const conditioned = policyRowConditionKeys(input.policy);
1591
1849
  for (const found of helperTablePoliciesFromRows((await query(HELPER_TABLE_POLICIES_SQL)).rows)) {
1592
1850
  const keys = found.keys.filter((key) => conditioned.has(key));
1593
- if (keys.length > 0) mismatches.push(`PD037 ${rowConditionMessage(found, keys)}`);
1851
+ if (keys.length > 0) mismatches.push(rlsFinding("condition-blind", found.table, found.name, `PD037 ${rowConditionMessage(found, keys)}`));
1594
1852
  }
1595
1853
  for (const [index, fixture] of input.fixtures.entries()) {
1596
1854
  const permission = findPermission(input.policy.permissions, fixture.action);
@@ -1600,7 +1858,11 @@ async function verifyAgainstDatabase(input) {
1600
1858
  notes.push(`${fixture.action}: opaque grant untestable app-side`);
1601
1859
  continue;
1602
1860
  }
1603
- const table = input.config.rls?.tables?.[permission.resource] ?? permission.resource;
1861
+ if (input.config.rls?.tables?.[permission.resource] === false) {
1862
+ notes.push(`${fixture.action}: rls.tables.${permission.resource} is false, so there is no table`);
1863
+ continue;
1864
+ }
1865
+ const table = tableNameOf(input.config.rls?.tables?.[permission.resource], permission.resource);
1604
1866
  await query("begin");
1605
1867
  try {
1606
1868
  if (seedsTables) await seedCustomRoles(query, schema, input.customRoles, scopes);
@@ -1609,7 +1871,7 @@ async function verifyAgainstDatabase(input) {
1609
1871
  const result = await query(statement.sql, statement.values);
1610
1872
  const count = result.rowCount ?? result.rows.length;
1611
1873
  const database = result.code === "42501" ? "rejected" : count > 0 ? "allowed" : "filtered";
1612
- if (!(status.granted ? database === "allowed" : database === "filtered" || database === "rejected")) mismatches.push(`${fixture.action}: in-process ${status.granted ? "granted" : "denied"}, database ${database}`);
1874
+ if (!(status.granted ? database === "allowed" : database === "filtered" || database === "rejected")) mismatches.push(rlsFinding("parity-mismatch", fixture.action, fixtureKey(fixture), `${fixture.action}: in-process ${status.granted ? "granted" : "denied"}, database ${database}`));
1613
1875
  else if (status.kind === "sqlFunction") notes.push(`${fixture.action}: verified through twin`);
1614
1876
  mismatches.push(...status.fields === void 0 ? [] : fieldsMismatch(fixture, status.fields, await viewFields(query, table, rowId(fixture.row))));
1615
1877
  } finally {
@@ -1625,7 +1887,7 @@ async function verifyAgainstDatabase(input) {
1625
1887
  };
1626
1888
  }
1627
1889
  /** `--tree`: seeds a generated object graph in a rolled-back transaction and compares `can()` with RLS. */
1628
- async function verifyTreeAgainstDatabase(db, policy, config, connect) {
1890
+ async function verifyTreeAgainstDatabase(db, policy, config, connect, ignore) {
1629
1891
  const client = await connect(db);
1630
1892
  const scopes = scopeList(policy.scopes);
1631
1893
  const query = async (sql, values) => {
@@ -1647,15 +1909,12 @@ async function verifyTreeAgainstDatabase(db, policy, config, connect) {
1647
1909
  action: "read"
1648
1910
  }, subjectOf(config, [], scopes))
1649
1911
  });
1650
- if (result.mismatches.length > 0) return {
1651
- code: 1,
1652
- output: [...result.mismatches, ...result.notes].join("\n")
1653
- };
1654
- const verified = `verified ${String(result.checked)} tree check(s) against the database (${String(result.granted)} granted)`;
1655
- return {
1656
- code: 0,
1657
- output: result.notes.length === 0 ? verified : `${verified}\n${result.notes.join("\n")}`
1658
- };
1912
+ return verifyResult({
1913
+ findings: result.mismatches,
1914
+ ignore,
1915
+ notes: result.notes,
1916
+ summary: `verified ${String(result.checked)} tree check(s) against the database (${String(result.granted)} granted)`
1917
+ });
1659
1918
  } catch (cause) {
1660
1919
  return {
1661
1920
  code: 2,
@@ -1668,6 +1927,8 @@ async function verifyTreeAgainstDatabase(db, policy, config, connect) {
1668
1927
  }
1669
1928
  //#endregion
1670
1929
  //#region src/cli/rls/verify.ts
1930
+ /** Where `rls verify --kind pgtap` writes, the folder `supabase test db` reads. */
1931
+ const PGTAP_OUT = "supabase/tests/permdock_rls.test.sql";
1671
1932
  function canFixture(permdock, permission, row) {
1672
1933
  if (permission.kind === "collection") return permdock.can(permission, row);
1673
1934
  return permdock.can(permission, row);
@@ -1679,6 +1940,11 @@ function grantKind(policy, key) {
1679
1940
  return "portable";
1680
1941
  }
1681
1942
  async function runRlsVerify(input) {
1943
+ const ignore = input.ignore ?? [];
1944
+ if (input.out !== void 0 && input.format !== "pgtap") return {
1945
+ code: 2,
1946
+ output: "PermDock CLI: rls verify --out needs --kind pgtap"
1947
+ };
1682
1948
  const connect = input.connect ?? pgConnector("permdock rls verify --db-url-stdin", input.cwd);
1683
1949
  const policyPath = input.from ?? input.config.policy;
1684
1950
  if (policyPath === void 0) return {
@@ -1692,7 +1958,7 @@ async function runRlsVerify(input) {
1692
1958
  output: "PermDock CLI: rls verify --tree needs a database: --db-url-stdin, DATABASE_URL or SUPABASE_DB_URL"
1693
1959
  };
1694
1960
  try {
1695
- return await verifyTreeAgainstDatabase(input.db, policy, input.config, connect);
1961
+ return await verifyTreeAgainstDatabase(input.db, policy, input.config, connect, ignore);
1696
1962
  } catch (cause) {
1697
1963
  return usageResult(cause);
1698
1964
  }
@@ -1702,11 +1968,11 @@ async function runRlsVerify(input) {
1702
1968
  const mismatches = [];
1703
1969
  const notes = [];
1704
1970
  const inProcess = [];
1705
- const fieldsMode = input.config.rls?.fields === "views";
1971
+ const fieldsMode = input.config.rls?.fields !== void 0;
1706
1972
  for (const fixture of fixtures) {
1707
1973
  const permission = findPermission(policy.permissions, fixture.action);
1708
1974
  if (permission === void 0) {
1709
- mismatches.push(`${fixture.action}: unknown permission`);
1975
+ mismatches.push(rlsFinding("unknown-permission", fixture.action, fixtureKey(fixture), `${fixture.action}: unknown permission`));
1710
1976
  inProcess.push({
1711
1977
  action: fixture.action,
1712
1978
  granted: false,
@@ -1718,7 +1984,7 @@ async function runRlsVerify(input) {
1718
1984
  const permdock = await getPermDock(policy, fixtureSubject(fixture.subject), { customRoles: memoryCustomRoleSource(customRoles) });
1719
1985
  const granted = canFixture(permdock, permission, fixtureRow(fixture, permission.kind));
1720
1986
  const outcome = granted ? "granted" : "denied";
1721
- if (fixture.expected !== void 0 && fixture.expected !== outcome) mismatches.push(`${fixture.action}: in-process ${outcome}, expected ${fixture.expected}`);
1987
+ if (fixture.expected !== void 0 && fixture.expected !== outcome) mismatches.push(rlsFinding("expected-mismatch", fixture.action, fixtureKey(fixture), `${fixture.action}: in-process ${outcome}, expected ${fixture.expected}`));
1722
1988
  if (kind === "opaque") notes.push(`${fixture.action}: opaque grant untestable app-side`);
1723
1989
  const fields = fieldsMode && permission.kind === "instance" && commandFor(permission.action, input.config.rls?.actions) === "select" ? expectedFields(granted, permdock.pick(permission, fixture.row), policy.resources.get(permission.resource)?.id ?? "id", fixture.row) : void 0;
1724
1990
  inProcess.push({
@@ -1728,19 +1994,23 @@ async function runRlsVerify(input) {
1728
1994
  ...fields === void 0 ? {} : { fields }
1729
1995
  });
1730
1996
  }
1731
- if (input.format === "pgtap") return mismatches.length > 0 ? {
1732
- code: 1,
1733
- output: mismatches.join("\n")
1734
- } : {
1735
- code: 0,
1736
- output: emitPgtap({
1997
+ if (input.format === "pgtap") {
1998
+ const outRel = input.out ?? PGTAP_OUT;
1999
+ const result = verifyResult({
2000
+ findings: mismatches,
2001
+ ignore,
2002
+ summary: `wrote ${outRel}`
2003
+ });
2004
+ if (result.code !== 0) return result;
2005
+ writeFileEnsuringDir(resolve(input.cwd, outRel), emitPgtap({
1737
2006
  fixtures,
1738
2007
  inProcess,
1739
2008
  policy,
1740
2009
  config: input.config,
1741
2010
  customRoles
1742
- })
1743
- };
2011
+ }));
2012
+ return result;
2013
+ }
1744
2014
  if (input.db !== void 0) try {
1745
2015
  const database = await verifyAgainstDatabase({
1746
2016
  db: input.db,
@@ -1756,15 +2026,12 @@ async function runRlsVerify(input) {
1756
2026
  } catch (cause) {
1757
2027
  return usageResult(cause);
1758
2028
  }
1759
- if (mismatches.length > 0) return {
1760
- code: 1,
1761
- output: [...mismatches, ...notes].join("\n")
1762
- };
1763
- const verified = `verified ${String(fixtures.length)} fixture(s) ${input.db === void 0 ? "in-process" : "in-process and against the database"}`;
1764
- return {
1765
- code: 0,
1766
- output: notes.length === 0 ? verified : `${verified}\n${notes.join("\n")}`
1767
- };
2029
+ return verifyResult({
2030
+ findings: mismatches,
2031
+ ignore,
2032
+ notes,
2033
+ summary: `verified ${String(fixtures.length)} fixture(s) ${input.db === void 0 ? "in-process" : "in-process and against the database"}`
2034
+ });
1768
2035
  }
1769
2036
  //#endregion
1770
- export { indexesSql as _, graphSql as a, callsHelper as c, rowConditionMessage as d, commandFor as f, indexTargets as g, COLUMNS_SQL as h, graphPlan as i, helperCallKeys as l, tableFor$1 as m, runRlsVerify as n, HELPER_TABLES as o, compileGrants as p, closureDepths as r, ROW_CONDITION_FIX as s, canFixture as t, helperTablePolicies as u, pruneIndexTargets as v, readTableIndexFacts as y };
2037
+ export { INDEX_COLUMNS_SQL as C, readTableIndexFacts as D, pruneIndexTargets as E, COLUMNS_SQL as S, indexesSql as T, helperTablePolicies as _, graphSql as a, compileGrants as b, verifyResult as c, tableNames as d, tablelessResources as f, helperCallKeys as g, callsHelper as h, graphPlan as i, resolveVias as l, ROW_CONDITION_FIX as m, runRlsVerify as n, rlsFinding as o, HELPER_TABLES as p, closureDepths as r, verifyIgnores as s, canFixture as t, tableNameOf as u, rowConditionMessage as v, indexTargets as w, tableFor$1 as x, commandFor as y };