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,312 +1,69 @@
1
- import { t as require__2020 } from "../2020-C9VN-x8c.js";
2
1
  import { r as isRecord } from "../compact-CAf557ZB.js";
3
2
  import { n as freezeDeep } from "../freeze-CrU8nQeX.js";
4
- import { r as principal } from "../refs-K6eWUJ0H.js";
5
- import { n as role, r as allow } from "../role-builder-CXbis5-X.js";
6
- import { E as memoryCustomRoleSource, _ as limits, s as snapshotFor, v as memoryLimitStore, x as approvalPoliciesFor } from "../src-DLfUWFAI.js";
3
+ import { i as principal } from "../refs-CNJBiTFo.js";
4
+ import { n as role, r as allow } from "../role-builder-C1VJzvcr.js";
5
+ import { A as memoryCustomRoleSource, S as memoryLimitStore, T as approvalPoliciesFor, d as snapshotFor, x as limits } from "../src-DLFrtrrC.js";
7
6
  import { t as memoryRevocationFeed } from "../revocations-Bhr0aMIC.js";
8
7
  import { n as loadPrincipalByIdentity, t as loadPrincipal } from "../principal-source-pHneukrx.js";
9
- import { _ as resource, c as listPermissions } from "../permission-registry-Br4jSNVi.js";
8
+ import { v as resource } from "../permission-registry-DpPtSKNZ.js";
10
9
  import { d as isoNow, f as nowMillis, p as nowSeconds, u as isoAt } from "../time-DkWjdL98.js";
11
- import { r as parseAutomation } from "../automation-DVjOckjV.js";
12
- import { a as normalizeMemberships, d as scopeList } from "../scopes-CUPSjo9q.js";
13
- import { u as evaluateCondition } from "../delegation-DaXVdDhM.js";
14
- import { a as authenticated } from "../grantee-Cn1HyUsI.js";
15
- import { n as definePolicy } from "../policy-DLZJ5gAp.js";
10
+ import { r as parseAutomation } from "../automation-ySsxp_Yp.js";
11
+ import { f as scopeList, o as normalizeMemberships } from "../scopes-BHsc-wp-.js";
12
+ import { u as evaluateCondition } from "../delegation-C5rOdTp5.js";
13
+ import { a as authenticated } from "../grantee-BrRANrpT.js";
14
+ import { n as definePolicy } from "../policy-DaJy4nK4.js";
16
15
  import { t as byCodePoint } from "../compare-pfyVnBjE.js";
17
- import { a as mergeHostedGrants, o as parsePolicyDocument } from "../hosted-BZIAYvon.js";
18
- import { t as definePermissions } from "../permissions-B-wCP5ZC.js";
19
- import { _ as membershipsClaim, x as validateCustomRole } from "../evaluate-_R8QkWaf.js";
20
- import { n as parseSnapshot } from "../snapshot-CXUWfsNy.js";
21
- import { n as fromSnapshot } from "../from-snapshot-D2lZt4Dd.js";
22
- import { t as getPermDock } from "../permdock-B9JxkBwC.js";
16
+ import { c as mergeHostedGrants, l as parsePolicyDocument } from "../hosted-XBgU6RGT.js";
17
+ import { t as definePermissions } from "../permissions-CyH2MV_B.js";
18
+ import { T as validateCustomRole } from "../evaluate-B_oqFbWC.js";
19
+ import { n as parseSnapshot } from "../snapshot-CbGmYiJx.js";
20
+ import { n as fromSnapshot } from "../from-snapshot-Bz469dIh.js";
21
+ import { t as getPermDock } from "../permdock-BfWEeMqk.js";
23
22
  import { t as APPROVAL_HEADER } from "../types-DqzsnlSA.js";
24
- import { i as memoryApprovalStore } from "../store-4u_hxjWa.js";
25
- import { t as catalogFingerprint } from "../catalog-fingerprint-CCP0-yQS.js";
26
- import { s as parseCredential } from "../credential-DM2um3ha.js";
23
+ import { i as memoryApprovalStore } from "../store-DSP9oGvh.js";
24
+ import { t as catalogFingerprint } from "../catalog-fingerprint-C144oW4M.js";
25
+ import { s as parseCredential } from "../credential-CIM7wHwA.js";
27
26
  import { s as problemFromDecision } from "../problem-CTviyH5L.js";
28
- import { o as resolveApproval } from "../helpers-DTcZOzhF.js";
27
+ import { o as resolveApproval } from "../helpers-DY3vXuGs.js";
29
28
  import { t as APPROVAL_REQUEST_SCHEMA } from "../request-schema-CMreVuFM.js";
30
29
  import { t as catalogSchema } from "../schema-B4v0Qrac.js";
31
- import { c as parseApiKey } from "../server-DqCT4CgZ.js";
30
+ import { c as parseApiKey } from "../server-Bnga6I50.js";
32
31
  import { n as discoverAuthorizationServer } from "../device-BARQ8eYG.js";
33
- import { T as sha256Hex, n as directoryMembershipSource, r as scimHandler } from "../scim-ClHtpyV3.js";
34
- import { a as approverHeaders, r as cloudEndpoints, t as cloud } from "../create-BWRSXgOF.js";
32
+ import { t as CONNECTOR_SCHEMA } from "../connector-schema-_VCSsdtD.js";
33
+ import { l as sha256Hex, n as scimHandler, t as directoryMembershipSource } from "../scim-YNieBO1U.js";
34
+ import { i as cloudEndpoints, n as cloud, s as approverHeaders, t as bearerChallenge } from "../challenge-nGWma08S.js";
35
35
  import { t as supabaseMembershipsBudget } from "../budget-NbEtbJC_.js";
36
- import { c as quoteSqlTable, n as defaultSqlCommand, o as quoteSqlIdent, t as SQL_IDENT } from "../sql-B5T1IL83.js";
37
- import { t as supabaseManifestSchema } from "../manifest-schema-C0kK_8V0.js";
38
- import { t as PUSHED_POLICY_SCHEMA } from "../pushed-policy-DobP7AHI.js";
39
- import { i as saasPermissions } from "../permissions-CZKiUfFM.js";
40
- import { C as saasOrg, E as saasSeed, S as saasMemberships, a as saasProject, g as verifySaasSession, h as signSaasToken, k as saasPolicy, t as saasDoc, w as saasPrincipal, x as saasCustomRoles } from "../saas-FO-Q8oj0.js";
36
+ import { t as supabaseManifestSchema } from "../manifest-schema-Cv492Qev.js";
37
+ import { t as PUSHED_POLICY_SCHEMA } from "../pushed-policy-CmYeSQqq.js";
38
+ import { i as policyMatrixLayout, n as testRlsParity, r as policyMatrix, t as testOrmParity } from "../core-B5-w6Kw9.js";
39
+ import { i as saasPermissions } from "../permissions-DArULThq.js";
40
+ import { C as saasOrg, E as saasSeed, S as saasMemberships, a as saasProject, g as verifySaasSession, h as signSaasToken, k as saasPolicy, t as saasDoc, w as saasPrincipal, x as saasCustomRoles } from "../saas-Az_Kz-4D.js";
41
41
  import { t as POLICY_NOT_PUBLISHED } from "../problem-types-CJ2325SZ.js";
42
+ import { t as require__2020 } from "../2020-CJbO8Bvz.js";
42
43
  import { afterAll, beforeAll, describe, expect, expectTypeOf, it, vi } from "vitest";
43
44
  //#region src/testing/describe-policy.ts
44
- function isOutcomeCell(value) {
45
- return value === "granted" || value === "denied" || value === "approval-required" || value !== null && typeof value === "object" && ("denials" in value || "outcome" in value || "alternatives" in value || "obligations" in value || "deniedBy" in value);
46
- }
47
- /** Asserts `deniedBy` against the trace of a fresh `explain` call for the same arguments. */
48
- function assertDeniedBy(instance, permission, data, cell) {
49
- if (typeof cell !== "object" || cell.deniedBy === void 0) return;
50
- const explained = instance.explain(permission, data);
51
- expect(explained.outcome).toBe("denied");
52
- expect(explained.trace.denies[0]?.name).toBe(cell.deniedBy);
53
- }
54
- function expectedOutcome(cell) {
55
- return typeof cell === "string" ? cell : cell.outcome ?? "denied";
56
- }
57
- function assertCell(decision, cell) {
58
- expect(decision.outcome).toBe(expectedOutcome(cell));
59
- if (typeof cell === "object" && cell.denials !== void 0 && decision.outcome === "denied") for (const denial of cell.denials) expect(decision.denials.some((item) => item.reason === denial.reason && (denial.role === void 0 || item.role === denial.role))).toBe(true);
60
- if (typeof cell === "object" && cell.alternatives !== void 0 && decision.outcome === "denied") expect(decision.alternatives.map((leaf) => leaf.key)).toEqual(cell.alternatives);
61
- if (typeof cell === "object" && cell.obligations !== void 0 && decision.outcome === "granted") expect((decision.obligations ?? []).map((item) => item.kind)).toEqual(cell.obligations);
62
- }
63
- function assertSnapshotCell(instance, permission, data, cell) {
64
- const outcome = expectedOutcome(cell);
65
- if (outcome === "approval-required") return;
66
- const client = fromSnapshot(JSON.parse(JSON.stringify(instance.snapshot())));
67
- expect(client.can(permission, data), "snapshot client disagrees with the server").toBe(outcome === "granted");
68
- }
45
+ /** `policyMatrix` under Vitest: one test per cell, plus the exhaustive check. */
69
46
  function describePolicy(policy, config) {
70
47
  describe("policy matrix", () => {
71
- const permissions = listPermissions(policy.permissions);
72
- const permdocks = /* @__PURE__ */ new Map();
48
+ const state = {};
73
49
  beforeAll(async () => {
74
- for (const [name, user] of Object.entries(config.subjects)) permdocks.set(name, await getPermDock(policy, user, config.options));
50
+ state.report = await policyMatrix(policy, config);
75
51
  });
76
52
  it("covers every permission", () => {
77
- if (config.exhaustive === false) return;
78
- for (const permission of permissions) expect(config.matrix[permission.key], `missing matrix for ${permission.key}`).toBeDefined();
79
- });
80
- for (const permission of permissions) {
81
- const spec = config.matrix[permission.key];
82
- if (spec === void 0) continue;
83
- describe(permission.key, () => {
84
- if (!Object.values(spec).some((value) => !isOutcomeCell(value))) {
85
- for (const [subjectName, cell] of Object.entries(spec)) it(`${subjectName}`, async () => {
86
- const instance = permdocks.get(subjectName) ?? await getPermDock(policy, config.subjects[subjectName], config.options);
87
- const data = permission.kind === "instance" ? Object.values(config.fixtures ?? {})[0] : void 0;
88
- assertCell(instance.decide(permission, data), cell);
89
- assertDeniedBy(instance, permission, data, cell);
90
- if (config.snapshot === true) assertSnapshotCell(instance, permission, data, cell);
91
- });
92
- return;
93
- }
94
- for (const [fixtureName, row] of Object.entries(spec)) {
95
- if (isOutcomeCell(row)) continue;
96
- for (const [subjectName, cell] of Object.entries(row)) it(`${fixtureName} / ${subjectName}`, async () => {
97
- const instance = permdocks.get(subjectName) ?? await getPermDock(policy, config.subjects[subjectName], config.options);
98
- const fixture = config.fixtures?.[fixtureName];
99
- assertCell(instance.decide(permission, fixture), cell);
100
- assertDeniedBy(instance, permission, fixture, cell);
101
- if (config.snapshot === true) assertSnapshotCell(instance, permission, fixture, cell);
102
- });
103
- }
104
- });
105
- }
106
- });
107
- }
108
- //#endregion
109
- //#region src/testing/rls-parity.ts
110
- function toSubject(input) {
111
- return {
112
- principal: {
113
- id: input.id,
114
- roles: input.roles ?? [],
115
- ...input.tenant === void 0 ? {} : { tenant: input.tenant },
116
- memberships: input.memberships ?? [],
117
- ...input.claims === void 0 ? {} : { claims: input.claims }
118
- },
119
- context: {}
120
- };
121
- }
122
- function rowId(row) {
123
- return row["id"];
124
- }
125
- function setting(name, value) {
126
- return {
127
- sql: "select set_config($1, $2, true)",
128
- values: [name, value]
129
- };
130
- }
131
- /**
132
- * The session state the generated helpers read: JWT claims for `supabase`,
133
- * GUCs for `guc` (roles as a comma list, memberships as JSON).
134
- */
135
- function subjectSettings(dialect, subject, gucPrefix, tenantClaim, roleClaim, customRoles, scopes) {
136
- const roles = subject.roles ?? [];
137
- const memberships = membershipsClaim(subject.memberships ?? [], customRoles, scopes);
138
- if (dialect === "supabase" || dialect === "neon") {
139
- const claims = {
140
- ...subject.claims,
141
- sub: subject.id,
142
- role: "authenticated",
143
- [roleClaim]: roles.length === 1 ? roles[0] : roles,
144
- [tenantClaim]: subject.tenant,
145
- memberships
146
- };
147
- return [setting("request.jwt.claims", JSON.stringify(claims))];
148
- }
149
- const settings = [
150
- ...Object.entries(subject.claims ?? {}).map(([name, value]) => {
151
- if (!SQL_IDENT.test(name)) throw new Error(`PermDock: unsafe claim name '${name}'`);
152
- return setting(`${gucPrefix}.${name}`, typeof value === "string" ? value : JSON.stringify(value));
153
- }),
154
- setting(`${gucPrefix}.user_id`, subject.id),
155
- setting(`${gucPrefix}.${roleClaim}`, roles.join(",")),
156
- setting(`${gucPrefix}.memberships`, JSON.stringify(memberships))
157
- ];
158
- return subject.tenant === void 0 ? settings : [...settings, setting(`${gucPrefix}.${tenantClaim}`, subject.tenant)];
159
- }
160
- /**
161
- * The statement a case runs. With field views it reads back only the key, so
162
- * a base table whose restricted columns are revoked does not reject it.
163
- */
164
- function statementSql(action, table, keyOnly) {
165
- const quoted = quoteSqlTable(table);
166
- const id = quoteSqlIdent("id");
167
- const back = keyOnly ? id : "*";
168
- const command = defaultSqlCommand(action) ?? "select";
169
- switch (command) {
170
- case "select": return `select ${back} from ${quoted} where ${id} = $1`;
171
- case "update": return `update ${quoted} set ${id} = ${id} where ${id} = $1 returning ${back}`;
172
- case "insert": return `insert into ${quoted} (${id}) values ($1) returning ${back}`;
173
- case "delete": return `delete from ${quoted} where ${id} = $1 returning ${back}`;
174
- default: return command;
175
- }
176
- }
177
- function valued(row) {
178
- if (row === null || typeof row !== "object") return [];
179
- const record = row;
180
- return Object.keys(record).filter((name) => record[name] !== null && record[name] !== void 0).toSorted();
181
- }
182
- function isRead(action) {
183
- return action === "read" || action === "get" || action === "list";
184
- }
185
- async function viewColumns(query, table, key) {
186
- const id = quoteSqlIdent("id");
187
- await query("savepoint permdock_fields");
188
- const view = await query(`select * from ${quoteSqlTable(`${table}_visible`)} where ${id} = $1`, [key]);
189
- if (view.code === void 0) return valued(view.rows[0]);
190
- await query("rollback to savepoint permdock_fields");
191
- if (view.code !== "42P01") return view.code;
192
- const base = await query(`select * from ${quoteSqlTable(table)} where ${id} = $1`, [key]);
193
- return base.code ?? valued(base.rows[0]);
194
- }
195
- function dbOutcome(result) {
196
- if (result.code === "42501") return "rejected";
197
- return (result.rowCount ?? result.rows.length) > 0 ? "allowed" : "filtered";
198
- }
199
- async function testRlsParity(policy, options) {
200
- const dialect = options.dialect ?? "guc";
201
- const gucPrefix = options.gucPrefix ?? "app";
202
- const tenantClaim = options.tenantClaim ?? "tenant_id";
203
- const roleClaim = options.roleClaim ?? "user_role";
204
- const role = options.role ?? "authenticated";
205
- const customRoles = options.customRoles ?? [];
206
- const scopes = scopeList(policy.scopes);
207
- async function runCase(fixture) {
208
- const permdock = await getPermDock(policy, toSubject(fixture.subject), { customRoles: memoryCustomRoleSource(customRoles) });
209
- const granted = fixture.permission.kind === "collection" ? permdock.can(fixture.permission, fixture.row) : permdock.can(fixture.permission, fixture.row);
210
- let fromClient;
211
- if (options.snapshot === true) {
212
- const snapshot = permdock.snapshot();
213
- if (typeof snapshot !== "object" || snapshot instanceof Promise) throw new TypeError("PermDock: testRlsParity needs an unsigned snapshot");
214
- fromClient = fromSnapshot(parseSnapshot(JSON.stringify(snapshot))).can(fixture.permission, fixture.row);
215
- }
216
- await options.query("begin");
217
- try {
218
- await options.query(`set local role ${quoteSqlIdent(role === "anon" && dialect === "neon" ? "anonymous" : role)}`);
219
- for (const item of subjectSettings(dialect, fixture.subject, gucPrefix, tenantClaim, roleClaim, customRoles, scopes)) await options.query(item.sql, item.values);
220
- const database = dbOutcome(await options.query(statementSql(fixture.permission.action, fixture.table, options.fieldViews === true), [rowId(fixture.row)]));
221
- const agrees = granted ? database === "allowed" : database === "filtered" || database === "rejected";
222
- let fields;
223
- if (options.fieldViews === true && fixture.permission.kind === "instance" && isRead(fixture.permission.action)) {
224
- const key = policy.resources.get(fixture.permission.resource)?.id ?? "id";
225
- const kept = new Set(granted ? valued(permdock.pick(fixture.permission, fixture.row)) : []);
226
- if (granted && fixture.row[key] !== null && fixture.row[key] !== void 0) kept.add(key);
227
- fields = {
228
- app: [...kept].toSorted(),
229
- database: await viewColumns(options.query, fixture.table, rowId(fixture.row))
230
- };
53
+ for (const key of state.report?.missing ?? []) expect.fail(`missing matrix for ${key}`);
54
+ });
55
+ const layout = policyMatrixLayout(policy, config);
56
+ for (const permission of new Set(layout.map((cell) => cell.permission))) describe(permission, () => {
57
+ for (const cell of layout.filter((item) => item.permission === permission)) {
58
+ const title = cell.fixture === void 0 ? cell.subject : `${cell.fixture} / ${cell.subject}`;
59
+ it(title, () => {
60
+ const decided = state.report?.cells.find((item) => item.name === cell.name);
61
+ expect(decided, `cell ${cell.name} was not decided`).toBeDefined();
62
+ expect(decided?.failures).toEqual([]);
63
+ });
231
64
  }
232
- const fieldsOk = fields === void 0 || typeof fields.database !== "string" && fields.database.join("\0") === fields.app.join("\0");
233
- const ok = agrees && fieldsOk && (fromClient === void 0 || fromClient === granted);
234
- return {
235
- name: fixture.name,
236
- granted,
237
- database,
238
- ...fromClient === void 0 ? {} : { snapshot: fromClient },
239
- ...fields === void 0 ? {} : { fields },
240
- ok
241
- };
242
- } finally {
243
- await options.query("rollback");
244
- }
245
- }
246
- async function runAll(remaining, acc) {
247
- const [head, ...tail] = remaining;
248
- if (head === void 0) return acc;
249
- return runAll(tail, [...acc, await runCase(head)]);
250
- }
251
- const results = await runAll(options.fixtures, []);
252
- return {
253
- ok: results.every((item) => item.ok),
254
- results
255
- };
256
- }
257
- //#endregion
258
- //#region src/testing/orm-parity.ts
259
- function sortedIds(values) {
260
- return values.map(String).toSorted();
261
- }
262
- function subsetOf(small, large) {
263
- return small.every((value) => large.includes(value));
264
- }
265
- /**
266
- * ORM parity: for each scenario, the rows `permdock.filter()` keeps in memory
267
- * must be exactly the rows the database returns for `toWhere(permdock.where())`.
268
- * With a `relations` option, the graph is loaded for the rows first, so the
269
- * in-memory side walks the same graph the database query does.
270
- * A partial `where()` (a closure grant it cannot compile) may be refused or
271
- * return fewer rows, never more.
272
- */
273
- async function testOrmParity(policy, scenarios, options) {
274
- const idField = options.id ?? "id";
275
- async function runCase(scenario) {
276
- const permdock = await getPermDock(policy, scenario.user, scenario.options);
277
- if (scenario.options?.relations !== void 0) await permdock.prefetchRelations(scenario.permission, scenario.rows);
278
- const expected = sortedIds(permdock.filter(scenario.permission, scenario.rows).map((row) => row[idField]));
279
- const where = permdock.where(scenario.permission);
280
- try {
281
- const actual = sortedIds(await options.run({
282
- scenario,
283
- where
284
- }));
285
- const ok = where.partial ? subsetOf(actual, expected) : actual.length === expected.length && subsetOf(actual, expected);
286
- return {
287
- name: scenario.name,
288
- expected,
289
- actual,
290
- partial: where.partial,
291
- ok
292
- };
293
- } catch (error) {
294
- return {
295
- name: scenario.name,
296
- expected,
297
- actual: [],
298
- partial: where.partial,
299
- error: error instanceof Error ? error.message : String(error),
300
- ok: where.partial
301
- };
302
- }
303
- }
304
- const results = [];
305
- for (const scenario of scenarios) results.push(await runCase(scenario));
306
- return {
307
- ok: results.every((item) => item.ok),
308
- results
309
- };
65
+ });
66
+ });
310
67
  }
311
68
  //#endregion
312
69
  //#region src/testing/client-parity.ts
@@ -2121,6 +1878,18 @@ function testApprovalStore(store, options = {}) {
2121
1878
  expect(await reopened.consume("restart-token")).not.toBeNull();
2122
1879
  expect(await store.consume("restart-token")).toBeNull();
2123
1880
  });
1881
+ it.skipIf(options.capabilities?.expire === void 0)("replaces an expired request on a new ask", async () => {
1882
+ await store.create(sampleApproval("renew-token"));
1883
+ await options.capabilities.expire("renew-token");
1884
+ const renewed = {
1885
+ ...sampleApproval("renew-token"),
1886
+ id: "apr_renewed"
1887
+ };
1888
+ await store.create(renewed);
1889
+ const loaded = await store.get("renew-token");
1890
+ expect(loaded?.id).toBe("apr_renewed");
1891
+ expect(loaded?.status).toBe("pending");
1892
+ });
2124
1893
  it("creates, gets, lists, resolves and expires", async () => {
2125
1894
  const request = sampleApproval("opaque-token");
2126
1895
  await store.create(request);
@@ -2649,7 +2418,9 @@ const OAUTH_FORM$1 = "application/x-www-form-urlencoded";
2649
2418
  const PLATFORM_SCOPES = {
2650
2419
  "projects:read": "List and read the projects the person belongs to",
2651
2420
  "policy:read": "Read a project's pushed catalog, manifest and policy",
2652
- "catalog:write": "Push a catalog and policy with permdock cloud push"
2421
+ "catalog:write": "Push a catalog and policy with permdock cloud push",
2422
+ "evidence:read": "Read a project's decision log and exports, the evidence an access review uses",
2423
+ "approvals:read": "Read a project's approval requests and their verdicts"
2653
2424
  };
2654
2425
  const ref$1 = (name) => ({ $ref: `#/components/schemas/${name}` });
2655
2426
  const RATE_LIMIT_HEADERS = {
@@ -2683,14 +2454,19 @@ const TOO_MANY = problem$1("Rate limited; retry after Retry-After seconds", {
2683
2454
  schema: { type: "string" }
2684
2455
  }
2685
2456
  });
2457
+ /** The RFC 6750 section 3 challenge a refused read carries, so a client tells a dead token from a missing scope. */
2458
+ const challenge = (example) => ({ "WWW-Authenticate": {
2459
+ description: `RFC 6750 Bearer challenge (\`${example}\`)`,
2460
+ schema: { type: "string" }
2461
+ } });
2686
2462
  const READ_SECURITY = (scope) => [{ platform: [scope] }, { cloudToken: [] }];
2687
2463
  const read = (scope, summary, responses) => ({ get: {
2688
2464
  security: READ_SECURITY(scope),
2689
2465
  summary,
2690
2466
  responses: {
2691
2467
  ...responses,
2692
- "401": problem$1("Missing, expired or revoked token"),
2693
- "403": problem$1("The token may not read this project; a PERMDOCK_CLOUD_TOKEN reads only its own environment"),
2468
+ "401": problem$1("Missing, expired or revoked token; a refused token carries `error=\"invalid_token\"`", challenge("Bearer realm=\"permdock\", error=\"invalid_token\"")),
2469
+ "403": problem$1(`The token lacks ${scope} (\`error="insufficient_scope"\` with \`scope\`), or may not read this project; a PERMDOCK_CLOUD_TOKEN reads only its own environment`, challenge(`Bearer realm="permdock", error="insufficient_scope", scope="${scope}"`)),
2694
2470
  "429": TOO_MANY
2695
2471
  }
2696
2472
  } });
@@ -2776,6 +2552,10 @@ const PLATFORM_SCHEMAS = {
2776
2552
  minLength: 1
2777
2553
  },
2778
2554
  name: { type: "string" },
2555
+ slug: {
2556
+ type: "string",
2557
+ description: "The project's URL-safe name, unique in its organization"
2558
+ },
2779
2559
  environment: {
2780
2560
  type: "string",
2781
2561
  minLength: 1
@@ -2794,6 +2574,11 @@ const PLATFORM_SCHEMAS = {
2794
2574
  },
2795
2575
  fingerprint: { type: "string" }
2796
2576
  }
2577
+ },
2578
+ updatedAt: {
2579
+ type: "string",
2580
+ format: "date-time",
2581
+ description: "When the project last changed, RFC 3339"
2797
2582
  }
2798
2583
  }
2799
2584
  },
@@ -2849,6 +2634,14 @@ const PLATFORM_PATHS = {
2849
2634
  summary: "RFC 8414 metadata of the platform issuer. For the issuer https://permdock.com/api it is served at https://permdock.com/.well-known/oauth-authorization-server/api (section 3.1) and here.",
2850
2635
  responses: { "200": oauthJson("The metadata", ref$1("AuthorizationServerMetadata")) }
2851
2636
  } },
2637
+ "/openapi.json": { get: {
2638
+ security: [],
2639
+ summary: "This document, the contract of https://permdock.com/api. permdock/schemas/cloud-api-v1.json ships the same document in the npm package.",
2640
+ responses: { "200": oauthJson("The OpenAPI 3.1 document", {
2641
+ type: "object",
2642
+ required: ["openapi", "paths"]
2643
+ }) }
2644
+ } },
2852
2645
  "/oauth/authorize": { get: {
2853
2646
  security: [],
2854
2647
  summary: "Authorization code with PKCE S256 for public clients, including the RFC 8252 loopback redirect http://127.0.0.1:{port}/callback",
@@ -2981,17 +2774,25 @@ const PLATFORM_PATHS = {
2981
2774
  "400": oauthJson("invalid_redirect_uri or invalid_client_metadata", ref$1("OAuthError"))
2982
2775
  }
2983
2776
  } },
2984
- "/v1/projects": read("projects:read", "The projects the token reads", { "200": limited("The projects", {
2985
- type: "object",
2986
- required: ["items"],
2987
- properties: {
2988
- items: {
2989
- type: "array",
2990
- items: ref$1("Project")
2991
- },
2992
- next: { type: "string" }
2993
- }
2994
- }) }),
2777
+ "/v1/projects": {
2778
+ parameters: [{
2779
+ name: "cursor",
2780
+ in: "query",
2781
+ description: "The `next` of the previous page",
2782
+ schema: { type: "string" }
2783
+ }],
2784
+ ...read("projects:read", "The projects the token reads", { "200": limited("The projects", {
2785
+ type: "object",
2786
+ required: ["items"],
2787
+ properties: {
2788
+ items: {
2789
+ type: "array",
2790
+ items: ref$1("Project")
2791
+ },
2792
+ next: { type: "string" }
2793
+ }
2794
+ }) })
2795
+ },
2995
2796
  "/v1/projects/{id}": {
2996
2797
  parameters: [PROJECT_ID],
2997
2798
  ...read("projects:read", "One project", {
@@ -3038,6 +2839,7 @@ function rateLimitField(value, keys) {
3038
2839
  function rateLimited(response) {
3039
2840
  return rateLimitField(response.headers.get("ratelimit"), ["r", "t"]) && rateLimitField(response.headers.get("ratelimit-policy"), ["q", "w"]);
3040
2841
  }
2842
+ const challengeOf = (response) => bearerChallenge(response.headers.get("www-authenticate"));
3041
2843
  function problemType(response, body) {
3042
2844
  return (response.headers.get("content-type") ?? "").startsWith("application/problem+json") && isRecord(body) ? body["type"] : void 0;
3043
2845
  }
@@ -3106,6 +2908,38 @@ function testCloudPlatform(url, environment, options, fetchFn) {
3106
2908
  expect(response.status).toBe(401);
3107
2909
  expect(response.headers.get("content-type")).toMatch(/^application\/problem\+json/u);
3108
2910
  });
2911
+ it("answers 401 with an error=\"invalid_token\" challenge to an unknown token", async () => {
2912
+ const response = await read("/v1/projects", `unknown-${globalThis.crypto.randomUUID()}`);
2913
+ expect(response.status).toBe(401);
2914
+ expect(challengeOf(response)).toMatchObject({
2915
+ scheme: "bearer",
2916
+ params: { error: "invalid_token" }
2917
+ });
2918
+ });
2919
+ it("answers 403 with an error=\"insufficient_scope\" challenge naming the scope", async (context) => {
2920
+ if (options.projectsOnly === void 0) {
2921
+ context.skip();
2922
+ return;
2923
+ }
2924
+ const response = await read(`/v1/projects/${encodeURIComponent(project)}/policy`, options.projectsOnly);
2925
+ expect(response.status).toBe(403);
2926
+ expect(challengeOf(response)).toMatchObject({
2927
+ scheme: "bearer",
2928
+ params: {
2929
+ error: "insufficient_scope",
2930
+ scope: "policy:read"
2931
+ }
2932
+ });
2933
+ });
2934
+ it("serves its OpenAPI document at /openapi.json", async () => {
2935
+ const response = await read("/openapi.json", null);
2936
+ expect(response.status).toBe(200);
2937
+ const body = await response.json();
2938
+ expect(body).toMatchObject({
2939
+ openapi: expect.stringMatching(/^3\.[1-9]\d*\./u),
2940
+ paths: expect.objectContaining({ "/v1/projects": expect.any(Object) })
2941
+ });
2942
+ });
3109
2943
  it("refuses a catalog push with the read-only token", async () => {
3110
2944
  const response = await fetchFn(`${url}/v1/environments/${encodeURIComponent(project)}/catalog`, {
3111
2945
  method: "POST",
@@ -3149,432 +2983,8 @@ function testCloudPlatform(url, environment, options, fetchFn) {
3149
2983
  });
3150
2984
  }
3151
2985
  //#endregion
3152
- //#region src/testing/cloud-api/connector-schema.ts
3153
- var import__2020 = require__2020();
3154
- /**
3155
- * `schemas/connector-v1.json`: the body of a PermDock Cloud connector, one
3156
- * `oneOf` branch per kind with a closed `config`. No branch holds a secret.
3157
- */
3158
- const CONNECTOR_SCHEMA = freezeDeep({
3159
- $schema: "https://json-schema.org/draft/2020-12/schema",
3160
- $id: "https://permdock.com/schemas/connector-v1.json",
3161
- title: "PermDock Cloud connector",
3162
- description: "A connector on PermDock Cloud's /connectors route, wire format v1: the closed list of kinds, one branch per kind. Trusted issuers have their own route (/trusted-issuers).",
3163
- oneOf: [
3164
- {
3165
- description: "CloudEvents batches signed with Standard Webhooks.",
3166
- type: "object",
3167
- required: [
3168
- "kind",
3169
- "name",
3170
- "config"
3171
- ],
3172
- properties: {
3173
- id: {
3174
- type: "string",
3175
- minLength: 1,
3176
- maxLength: 256
3177
- },
3178
- kind: { const: "webhook" },
3179
- name: {
3180
- type: "string",
3181
- minLength: 1,
3182
- maxLength: 200
3183
- },
3184
- config: {
3185
- type: "object",
3186
- additionalProperties: false,
3187
- required: ["url"],
3188
- properties: {
3189
- url: {
3190
- type: "string",
3191
- pattern: "^https://"
3192
- },
3193
- types: {
3194
- type: "array",
3195
- items: {
3196
- type: "string",
3197
- minLength: 1
3198
- },
3199
- uniqueItems: true,
3200
- description: "CloudEvents types to deliver; all when absent."
3201
- }
3202
- }
3203
- }
3204
- }
3205
- },
3206
- {
3207
- description: "OTLP/HTTP log records and spans with the permdock.* attributes.",
3208
- type: "object",
3209
- required: [
3210
- "kind",
3211
- "name",
3212
- "config"
3213
- ],
3214
- properties: {
3215
- id: {
3216
- type: "string",
3217
- minLength: 1,
3218
- maxLength: 256
3219
- },
3220
- kind: { const: "otlp" },
3221
- name: {
3222
- type: "string",
3223
- minLength: 1,
3224
- maxLength: 200
3225
- },
3226
- config: {
3227
- type: "object",
3228
- additionalProperties: false,
3229
- required: ["endpoint"],
3230
- properties: {
3231
- endpoint: {
3232
- type: "string",
3233
- pattern: "^https://"
3234
- },
3235
- headers: {
3236
- type: "object",
3237
- additionalProperties: { type: "string" }
3238
- },
3239
- signals: {
3240
- type: "array",
3241
- items: { enum: ["logs", "traces"] },
3242
- minItems: 1,
3243
- uniqueItems: true
3244
- }
3245
- }
3246
- }
3247
- }
3248
- },
3249
- {
3250
- description: "The OCSF projection posted to a SIEM ingest API.",
3251
- type: "object",
3252
- required: [
3253
- "kind",
3254
- "name",
3255
- "config"
3256
- ],
3257
- properties: {
3258
- id: {
3259
- type: "string",
3260
- minLength: 1,
3261
- maxLength: 256
3262
- },
3263
- kind: { const: "siem" },
3264
- name: {
3265
- type: "string",
3266
- minLength: 1,
3267
- maxLength: 200
3268
- },
3269
- config: {
3270
- type: "object",
3271
- additionalProperties: false,
3272
- required: ["destination", "endpoint"],
3273
- properties: {
3274
- destination: { enum: [
3275
- "splunk-hec",
3276
- "sentinel",
3277
- "security-lake",
3278
- "google-secops",
3279
- "elastic",
3280
- "datadog"
3281
- ] },
3282
- endpoint: {
3283
- type: "string",
3284
- pattern: "^https://"
3285
- }
3286
- }
3287
- }
3288
- }
3289
- },
3290
- {
3291
- description: "A scheduled decision-log export.",
3292
- type: "object",
3293
- required: [
3294
- "kind",
3295
- "name",
3296
- "config"
3297
- ],
3298
- properties: {
3299
- id: {
3300
- type: "string",
3301
- minLength: 1,
3302
- maxLength: 256
3303
- },
3304
- kind: { const: "evidence" },
3305
- name: {
3306
- type: "string",
3307
- minLength: 1,
3308
- maxLength: 200
3309
- },
3310
- config: {
3311
- type: "object",
3312
- additionalProperties: false,
3313
- required: ["format", "destination"],
3314
- properties: {
3315
- format: { enum: [
3316
- "jws",
3317
- "ocsf",
3318
- "csv"
3319
- ] },
3320
- destination: {
3321
- type: "string",
3322
- pattern: "^https://"
3323
- },
3324
- schedule: { enum: ["hourly", "daily"] }
3325
- }
3326
- }
3327
- }
3328
- },
3329
- {
3330
- description: "A hosted SCIM 2.0 relay for one tenant, replayed to the application's scimHandler.",
3331
- type: "object",
3332
- required: [
3333
- "kind",
3334
- "name",
3335
- "config"
3336
- ],
3337
- properties: {
3338
- id: {
3339
- type: "string",
3340
- minLength: 1,
3341
- maxLength: 256
3342
- },
3343
- kind: { const: "scim" },
3344
- name: {
3345
- type: "string",
3346
- minLength: 1,
3347
- maxLength: 200
3348
- },
3349
- config: {
3350
- type: "object",
3351
- additionalProperties: false,
3352
- required: ["tenant", "target"],
3353
- properties: {
3354
- tenant: {
3355
- type: "string",
3356
- minLength: 1,
3357
- maxLength: 256
3358
- },
3359
- target: {
3360
- type: "string",
3361
- pattern: "^https://"
3362
- },
3363
- groupRoles: {
3364
- type: "object",
3365
- description: "Group id to declared assignable role.",
3366
- additionalProperties: {
3367
- type: "string",
3368
- minLength: 1,
3369
- maxLength: 256
3370
- }
3371
- }
3372
- }
3373
- }
3374
- }
3375
- },
3376
- {
3377
- description: "An SSF transmitter whose SETs the Cloud receives (POST /ssf/receive/:connector, or poll).",
3378
- type: "object",
3379
- required: [
3380
- "kind",
3381
- "name",
3382
- "config"
3383
- ],
3384
- properties: {
3385
- id: {
3386
- type: "string",
3387
- minLength: 1,
3388
- maxLength: 256
3389
- },
3390
- kind: { const: "caep-transmitter" },
3391
- name: {
3392
- type: "string",
3393
- minLength: 1,
3394
- maxLength: 200
3395
- },
3396
- config: {
3397
- type: "object",
3398
- additionalProperties: false,
3399
- required: ["issuer", "delivery"],
3400
- properties: {
3401
- issuer: {
3402
- type: "string",
3403
- pattern: "^https://"
3404
- },
3405
- jwks_uri: {
3406
- type: "string",
3407
- pattern: "^https://"
3408
- },
3409
- delivery: { enum: ["push", "poll"] },
3410
- poll_endpoint: {
3411
- type: "string",
3412
- pattern: "^https://"
3413
- }
3414
- }
3415
- }
3416
- }
3417
- },
3418
- {
3419
- description: "An OIDC upstream the Cloud issuer federates to with authorization code plus PKCE.",
3420
- type: "object",
3421
- required: [
3422
- "kind",
3423
- "name",
3424
- "config"
3425
- ],
3426
- properties: {
3427
- id: {
3428
- type: "string",
3429
- minLength: 1,
3430
- maxLength: 256
3431
- },
3432
- kind: { const: "federated-upstream" },
3433
- name: {
3434
- type: "string",
3435
- minLength: 1,
3436
- maxLength: 200
3437
- },
3438
- config: {
3439
- type: "object",
3440
- additionalProperties: false,
3441
- required: ["discovery", "client_id"],
3442
- properties: {
3443
- discovery: {
3444
- type: "string",
3445
- pattern: "^https://"
3446
- },
3447
- client_id: {
3448
- type: "string",
3449
- minLength: 1,
3450
- maxLength: 256
3451
- },
3452
- scopes: {
3453
- type: "array",
3454
- items: {
3455
- type: "string",
3456
- minLength: 1
3457
- },
3458
- uniqueItems: true
3459
- }
3460
- }
3461
- }
3462
- }
3463
- },
3464
- {
3465
- description: "Approval cards through the Vercel Chat SDK.",
3466
- type: "object",
3467
- required: [
3468
- "kind",
3469
- "name",
3470
- "config"
3471
- ],
3472
- properties: {
3473
- id: {
3474
- type: "string",
3475
- minLength: 1,
3476
- maxLength: 256
3477
- },
3478
- kind: { const: "chat" },
3479
- name: {
3480
- type: "string",
3481
- minLength: 1,
3482
- maxLength: 200
3483
- },
3484
- config: {
3485
- type: "object",
3486
- additionalProperties: false,
3487
- required: ["platform", "workspace"],
3488
- properties: {
3489
- platform: { enum: ["slack", "teams"] },
3490
- workspace: {
3491
- type: "string",
3492
- minLength: 1,
3493
- maxLength: 256
3494
- }
3495
- }
3496
- }
3497
- }
3498
- },
3499
- {
3500
- description: "The Cloud's hosted email sender for approval and delivery messages.",
3501
- type: "object",
3502
- required: [
3503
- "kind",
3504
- "name",
3505
- "config"
3506
- ],
3507
- properties: {
3508
- id: {
3509
- type: "string",
3510
- minLength: 1,
3511
- maxLength: 256
3512
- },
3513
- kind: { const: "email" },
3514
- name: {
3515
- type: "string",
3516
- minLength: 1,
3517
- maxLength: 200
3518
- },
3519
- config: {
3520
- type: "object",
3521
- additionalProperties: false,
3522
- required: ["from"],
3523
- properties: { from: {
3524
- type: "string",
3525
- pattern: "^[^@\\s]+@[^@\\s]+$"
3526
- } }
3527
- }
3528
- }
3529
- },
3530
- {
3531
- description: "Vercel OIDC federation tokens accepted as hosted ADS callers.",
3532
- type: "object",
3533
- required: [
3534
- "kind",
3535
- "name",
3536
- "config"
3537
- ],
3538
- properties: {
3539
- id: {
3540
- type: "string",
3541
- minLength: 1,
3542
- maxLength: 256
3543
- },
3544
- kind: { const: "vercel-oidc" },
3545
- name: {
3546
- type: "string",
3547
- minLength: 1,
3548
- maxLength: 200
3549
- },
3550
- config: {
3551
- type: "object",
3552
- additionalProperties: false,
3553
- required: ["team_id"],
3554
- properties: {
3555
- team_id: {
3556
- type: "string",
3557
- minLength: 1,
3558
- maxLength: 256
3559
- },
3560
- project_id: {
3561
- type: "string",
3562
- minLength: 1,
3563
- maxLength: 256
3564
- },
3565
- environment: { enum: [
3566
- "production",
3567
- "preview",
3568
- "development"
3569
- ] }
3570
- }
3571
- }
3572
- }
3573
- }
3574
- ]
3575
- });
3576
- //#endregion
3577
2986
  //#region src/testing/cloud-api/document.ts
2987
+ var import__2020 = require__2020();
3578
2988
  const ENV = "/v1/environments/{env}";
3579
2989
  const COMPACT_JWS = String.raw`^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+$`;
3580
2990
  const APPROVAL_REQUEST = "https://permdock.com/schemas/approval-request-v1.json";
@@ -4073,6 +3483,31 @@ const APPROVALS = {
4073
3483
  }) }
4074
3484
  };
4075
3485
  const RUNTIME = {
3486
+ "/v1/environment": { get: client({
3487
+ summary: "The environment the key belongs to; cloud() calls it when no environment is configured",
3488
+ responses: { "200": json("The key's environment", {
3489
+ type: "object",
3490
+ required: [
3491
+ "environment",
3492
+ "issuer",
3493
+ "jwks_uri"
3494
+ ],
3495
+ properties: {
3496
+ environment: {
3497
+ type: "string",
3498
+ minLength: 1
3499
+ },
3500
+ issuer: {
3501
+ type: "string",
3502
+ format: "uri"
3503
+ },
3504
+ jwks_uri: {
3505
+ type: "string",
3506
+ format: "uri"
3507
+ }
3508
+ }
3509
+ }) }
3510
+ }) },
4076
3511
  [`${ENV}/decisions`]: { post: client({
4077
3512
  summary: "sink.write and sink.flush",
4078
3513
  requestBody: body({
@@ -4783,9 +4218,10 @@ function testCloudApi(baseUrl, keys, options) {
4783
4218
  const fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
4784
4219
  const url = trimSlash(baseUrl);
4785
4220
  const prefix = trimSlash(new URL(url).pathname);
4221
+ const environment = options.environment ?? "production";
4786
4222
  const { issuer } = cloudEndpoints({
4787
4223
  url,
4788
- ...options.environment === void 0 ? {} : { environment: options.environment }
4224
+ environment
4789
4225
  });
4790
4226
  const check = cloudApiValidator();
4791
4227
  const problems = [];
@@ -4805,7 +4241,7 @@ function testCloudApi(baseUrl, keys, options) {
4805
4241
  key: keys.client,
4806
4242
  fetch: recording,
4807
4243
  approver: options.approver,
4808
- ...options.environment === void 0 ? {} : { environment: options.environment },
4244
+ environment,
4809
4245
  ...options.verifier === void 0 ? {} : { verifier: options.verifier }
4810
4246
  });
4811
4247
  const call = (path, key, init = {}) => {
@@ -4851,12 +4287,22 @@ function testCloudApi(baseUrl, keys, options) {
4851
4287
  origin: issuer,
4852
4288
  ...options.authzen.headers === void 0 ? {} : { headers: options.authzen.headers }
4853
4289
  });
4854
- if (options.platform !== void 0) testCloudPlatform(url, options.environment ?? "production", options.platform, recording);
4290
+ if (options.platform !== void 0) testCloudPlatform(url, environment, options.platform, recording);
4855
4291
  it("answers 401 Problem Details without a key", async () => {
4856
4292
  const response = await call("/approvals", null);
4857
4293
  expect(response.status).toBe(401);
4858
4294
  expect(response.headers.get("content-type")).toMatch(/^application\/problem\+json/u);
4859
4295
  });
4296
+ it("names the client key's environment at GET /v1/environment", async () => {
4297
+ const response = await recording(`${url}/v1/environment`, { headers: { authorization: `Bearer ${keys.client}` } });
4298
+ expect(response.status).toBe(200);
4299
+ expect(await response.json()).toMatchObject({
4300
+ environment,
4301
+ issuer,
4302
+ jwks_uri: `${issuer}/.well-known/jwks.json`
4303
+ });
4304
+ expect((await recording(`${url}/v1/environment`)).status).toBe(401);
4305
+ });
4860
4306
  it("answers 403 to a key of another kind", async () => {
4861
4307
  expect((await call("/hosted-grants", keys.client)).status).toBe(403);
4862
4308
  if (keys.export !== void 0) expect((await call("/approvals", keys.export)).status).toBe(403);
@@ -5280,6 +4726,70 @@ function testSetQueue(queue) {
5280
4726
  }]);
5281
4727
  });
5282
4728
  }
4729
+ function streamConfiguration(id, description) {
4730
+ return {
4731
+ stream_id: id,
4732
+ iss: "https://transmitter.example",
4733
+ aud: "receiver",
4734
+ events_requested: [],
4735
+ delivery: { method: "urn:ietf:rfc:8936" },
4736
+ ...description === void 0 ? {} : { description }
4737
+ };
4738
+ }
4739
+ function testSsfStreamStore(store) {
4740
+ const id = (suffix) => `stream-${suffix}-${crypto.randomUUID()}`;
4741
+ it("creates an enabled stream and reads it back by id and by owner", async () => {
4742
+ const first = id("a");
4743
+ const second = id("b");
4744
+ const owner = `owner-${crypto.randomUUID()}`;
4745
+ await store.create(owner, streamConfiguration(first));
4746
+ await store.create(owner, streamConfiguration(second));
4747
+ await store.create("someone-else", streamConfiguration(id("c")));
4748
+ expect(await store.get(first)).toEqual({
4749
+ owner,
4750
+ configuration: streamConfiguration(first)
4751
+ });
4752
+ expect(await store.status(first)).toEqual({
4753
+ stream_id: first,
4754
+ status: "enabled"
4755
+ });
4756
+ const listed = await store.list(owner);
4757
+ expect(listed.map((stream) => stream.configuration.stream_id)).toEqual([first, second]);
4758
+ const all = await store.list();
4759
+ expect(all.map((stream) => stream.configuration.stream_id)).toEqual(expect.arrayContaining([first, second]));
4760
+ });
4761
+ it("answers null for a stream that does not exist", async () => {
4762
+ expect(await store.get(id("missing"))).toBeNull();
4763
+ expect(await store.status(id("missing"))).toBeNull();
4764
+ });
4765
+ it("replaces the configuration and keeps the owner and status", async () => {
4766
+ const stream = id("update");
4767
+ await store.create("owner-update", streamConfiguration(stream));
4768
+ await store.setStatus({
4769
+ stream_id: stream,
4770
+ status: "paused",
4771
+ reason: "maintenance"
4772
+ });
4773
+ await store.update(streamConfiguration(stream, "renamed"));
4774
+ expect(await store.get(stream)).toEqual({
4775
+ owner: "owner-update",
4776
+ configuration: streamConfiguration(stream, "renamed")
4777
+ });
4778
+ expect(await store.status(stream)).toEqual({
4779
+ stream_id: stream,
4780
+ status: "paused",
4781
+ reason: "maintenance"
4782
+ });
4783
+ });
4784
+ it("forgets a deleted stream and its status", async () => {
4785
+ const stream = id("delete");
4786
+ await store.create("owner-delete", streamConfiguration(stream));
4787
+ await store.delete(stream);
4788
+ expect(await store.get(stream)).toBeNull();
4789
+ expect(await store.status(stream)).toBeNull();
4790
+ expect((await store.list("owner-delete")).some((entry) => entry.configuration.stream_id === stream)).toBe(false);
4791
+ });
4792
+ }
5283
4793
  function testRevocationFeed(feed) {
5284
4794
  it("delivers each event to every subscriber until it unsubscribes", async () => {
5285
4795
  const first = [];
@@ -6957,4 +6467,4 @@ const PROBLEM_EXAMPLES = Object.freeze({
6957
6467
  }
6958
6468
  });
6959
6469
  //#endregion
6960
- export { AGENT_THROWING_ROW, AGENT_THROWING_USER, PROBLEM_EXAMPLES, authzenTodoData, authzenTodoPermissions, authzenTodoPolicy, authzenTodoUsers, authzenTodoVectors, describePolicy, expectTypeOf, jwtFixtureAudience, jwtFixtureIssuer, jwtFixtureJwks, jwtFixtureTokens, snapshotFixture, supabaseClaimFixtures, supabaseClaimVectors, supabaseHookManifestFixture, supabaseMembershipsBudget, testAccessReviewStore, testAgentAdapter, testAgentRuntime, testApprovalDelegationSource, testApprovalPolicySource, testApprovalStore, testApprovalWaiter, testAuthzen, testAutomationSource, testClientParity, testClientStore, testCloudApi, testCredentialVerifier, testCustomRoleSource, testDecisionProvider, testDecisionSink, testDeliveryTransport, testDirectoryStore, testEntitlementSource, testHttpAdapter, testIdempotencyStore, testLegacyParity, testLimitStore, testMembershipSource, testOrmParity, testPolicySource, testPrincipalSource, testRelationSource, testReplayStore, testRevocationFeed, testRlsParity, testSetQueue, testSettingsSource, testSnapshotSource, testSnapshotStorage, testSubjectResolver, testSupportSessionSource, testTokenSigner, testTokenVerifier, testWhereCompiler };
6470
+ export { AGENT_THROWING_ROW, AGENT_THROWING_USER, PROBLEM_EXAMPLES, authzenTodoData, authzenTodoPermissions, authzenTodoPolicy, authzenTodoUsers, authzenTodoVectors, describePolicy, expectTypeOf, jwtFixtureAudience, jwtFixtureIssuer, jwtFixtureJwks, jwtFixtureTokens, policyMatrix, snapshotFixture, supabaseClaimFixtures, supabaseClaimVectors, supabaseHookManifestFixture, supabaseMembershipsBudget, testAccessReviewStore, testAgentAdapter, testAgentRuntime, testApprovalDelegationSource, testApprovalPolicySource, testApprovalStore, testApprovalWaiter, testAuthzen, testAutomationSource, testClientParity, testClientStore, testCloudApi, testCredentialVerifier, testCustomRoleSource, testDecisionProvider, testDecisionSink, testDeliveryTransport, testDirectoryStore, testEntitlementSource, testHttpAdapter, testIdempotencyStore, testLegacyParity, testLimitStore, testMembershipSource, testOrmParity, testPolicySource, testPrincipalSource, testRelationSource, testReplayStore, testRevocationFeed, testRlsParity, testSetQueue, testSettingsSource, testSnapshotSource, testSnapshotStorage, testSsfStreamStore, testSubjectResolver, testSupportSessionSource, testTokenSigner, testTokenVerifier, testWhereCompiler };