permdock 0.1.0 → 0.3.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 (350) hide show
  1. package/README.md +106 -47
  2. package/dist/a2a/index.d.ts +7 -16
  3. package/dist/a2a/index.js +59 -98
  4. package/dist/adapter-context-mlWsVGGg.js +23 -0
  5. package/dist/ai-sdk/index.d.ts +37 -16
  6. package/dist/ai-sdk/index.js +30 -13
  7. package/dist/approvals/index.d.ts +3 -3
  8. package/dist/approvals/index.js +5 -4
  9. package/dist/{approvals-DaxY-Bdg.js → approvals-DbYAuNkG.js} +17 -11
  10. package/dist/approvers-DT4AVyIg.js +52 -0
  11. package/dist/{arazzo-CTeVuXr5.js → arazzo-BAgw9ap6.js} +2 -2
  12. package/dist/{arazzo-aoTkqYsJ.js → arazzo-CKwwqFWz.js} +2 -2
  13. package/dist/authzen/index.d.ts +4 -13
  14. package/dist/authzen/index.js +16 -50
  15. package/dist/better-auth/index.d.ts +20 -3
  16. package/dist/better-auth/index.js +27 -7
  17. package/dist/better-supabase/index.d.ts +223 -0
  18. package/dist/better-supabase/index.js +648 -0
  19. package/dist/bind-C_ob3LKa.d.ts +25 -0
  20. package/dist/bind-CuzGytRf.js +97 -0
  21. package/dist/boundary-BM8a_P6E.js +13 -0
  22. package/dist/boundary-BmHxVH1J.d.ts +15 -0
  23. package/dist/canonical-json-DemiK4Vp.js +26 -0
  24. package/dist/{capability-BDG_nkxt.d.ts → capability-2kYTMWDv.d.ts} +2 -2
  25. package/dist/{capability-B68OFnZx.js → capability-4qPdO9gk.js} +7 -5
  26. package/dist/catalog/index.d.ts +1 -1
  27. package/dist/catalog/index.js +1 -1
  28. package/dist/catalog-CRW5Mx_B.js +2 -0
  29. package/dist/{catalog-H-vFGwWK.js → catalog-DWF5cYqB.js} +4 -4
  30. package/dist/{catalog-B0E6bggc.js → catalog-dFZdWCGN.js} +2 -2
  31. package/dist/{catalog-doc-BSo_Q_-6.js → catalog-doc-DdGm82XT.js} +20 -32
  32. package/dist/claude-agent/index.d.ts +5 -14
  33. package/dist/claude-agent/index.js +4 -10
  34. package/dist/clerk/index.d.ts +12 -3
  35. package/dist/clerk/index.js +26 -5
  36. package/dist/cli/bin.js +1 -1
  37. package/dist/cli/index.d.ts +3 -3
  38. package/dist/cli/index.js +2 -2
  39. package/dist/clients-C7zLFuWT.d.ts +12 -0
  40. package/dist/clients-DjU5ABMy.js +23 -0
  41. package/dist/cloud/index.d.ts +4 -5
  42. package/dist/cloud/index.js +20 -6
  43. package/dist/{cloud-BNQTrmrr.js → cloud-CB_ELYuX.js} +2 -2
  44. package/dist/{cloud-Cuxr6Czw.js → cloud-DWLXO2af.js} +7 -6
  45. package/dist/collect-DClJsheJ.js +83 -0
  46. package/dist/{collect-O-tOtbnk.js → collect-DSTE3ml9.js} +194 -42
  47. package/dist/collect-DSWOk19R.js +2 -0
  48. package/dist/{commands-BMh_Etm2.js → commands-DSxCqG9A.js} +16 -12
  49. package/dist/compile/index.d.ts +3 -0
  50. package/dist/compile/index.js +2 -0
  51. package/dist/{compile-D22iwvuV.js → compile-Ba4blROR.js} +85 -30
  52. package/dist/compile-BkRyBDBw.d.ts +94 -0
  53. package/dist/config-BJiM-xAm.js +157 -0
  54. package/dist/config-Dnszbv-6.js +36 -0
  55. package/dist/config-report-DMvWKUxL.js +44 -0
  56. package/dist/{connection-JvqwHODC.js → connection-CU8MQxRi.js} +1 -1
  57. package/dist/{context-CKEAabd7.js → context-Bcy85rGi.js} +36 -27
  58. package/dist/convex/index.d.ts +9 -4
  59. package/dist/convex/index.js +14 -4
  60. package/dist/create-B1d519XK.d.ts +245 -0
  61. package/dist/create-CMwIl-w2.js +253 -0
  62. package/dist/{credential-B_rkUNlY.js → credential-8P81ff4u.js} +26 -46
  63. package/dist/delegation-D8pUEuce.js +103 -0
  64. package/dist/{describe-Bt1YD5uS.js → describe-B_gVZEVi.js} +10 -15
  65. package/dist/{describe-DernyItf.d.ts → describe-DMYiCjJV.d.ts} +9 -10
  66. package/dist/{diff-x5Il8LVa.js → diff-2VaeChzX.js} +44 -11
  67. package/dist/{diff-BUzf5Poi.js → diff-DBIhz_f2.js} +2 -2
  68. package/dist/{doctor-Bqo6FwUa.js → doctor-BwCAMLx_.js} +2 -2
  69. package/dist/doctor-collect-CHk6XWOA.js +665 -0
  70. package/dist/doctor-igIiM_Hl.js +1194 -0
  71. package/dist/drizzle/index.d.ts +4 -3
  72. package/dist/drizzle/index.js +3 -3
  73. package/dist/elysia/index.d.ts +6 -28
  74. package/dist/elysia/index.js +16 -60
  75. package/dist/{errors-DSMnAVNa.js → errors-CWfoNg9N.js} +8 -4
  76. package/dist/{errors-Iy71s7Oj.js → errors-Cz5zn0mW.js} +17 -71
  77. package/dist/{errors-DbZ1YOnb.d.ts → errors-DPdqI50v.d.ts} +8 -21
  78. package/dist/{errors-m3u9TmDu.js → errors-DRnGZHzF.js} +4 -1
  79. package/dist/evaluation-items-CfCCejQd.js +40 -0
  80. package/dist/{evaluations-DsAU9ppl.js → evaluations-tz6D9A2G.js} +28 -46
  81. package/dist/eve/index.d.ts +6 -15
  82. package/dist/eve/index.js +7 -12
  83. package/dist/expiry-BoBJ8Tvc.js +7 -0
  84. package/dist/express/index.d.ts +6 -29
  85. package/dist/express/index.js +28 -58
  86. package/dist/fastify/index.d.ts +6 -29
  87. package/dist/fastify/index.js +16 -65
  88. package/dist/fields-BMl1RxoX.js +26 -0
  89. package/dist/{files-B_wAGYmt.js → files-DWUN9PzI.js} +5 -1
  90. package/dist/{fixtures-Cvaw0gDG.js → fixtures-ht28Cplr.js} +5 -2
  91. package/dist/{freeze-y1_jQL4v.js → freeze-CrU8nQeX.js} +31 -2
  92. package/dist/{from-snapshot-BMGnhmgv.js → from-snapshot-CTLijvdm.js} +66 -48
  93. package/dist/{grantee-Bv04_Vzf.js → grantee-Cv5Sogfv.js} +88 -7
  94. package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
  95. package/dist/{headers-B5RRv3Xm.js → headers-BZSDieNT.js} +1 -1
  96. package/dist/{headers-C8SHQccD.d.ts → headers-Cf-zWvsO.d.ts} +1 -1
  97. package/dist/helpers-H_KARDVC.js +421 -0
  98. package/dist/hono/index.d.ts +6 -28
  99. package/dist/hono/index.js +11 -43
  100. package/dist/{hosted-BwKQ1BTA.js → hosted-DJQw46hn.js} +6 -5
  101. package/dist/{http-GgVApX1k.js → http-BIhmLfCc.js} +4 -20
  102. package/dist/http-SO7qGttf.js +44 -0
  103. package/dist/ids-DC4V4CFu.js +18 -0
  104. package/dist/index-0nNqHspG.d.ts +6 -0
  105. package/dist/{index-xIxJLwOQ.d.ts → index-BNc7Wer_.d.ts} +75 -7
  106. package/dist/{index-CltcQ4Bf.d.ts → index-C7Tw7MaW.d.ts} +68 -5
  107. package/dist/{index-LF_hS-yn.d.ts → index-C8z4RjQV.d.ts} +1 -1
  108. package/dist/index.d.ts +14 -9
  109. package/dist/index.js +22 -17
  110. package/dist/instance-options-Dhhcnm3y.js +22 -0
  111. package/dist/instance-options-jARdwfPN.d.ts +11 -0
  112. package/dist/{parse-DPfIvFMU.js → json-schema-BsAflUGW.js} +28 -57
  113. package/dist/jwt/index.d.ts +10 -6
  114. package/dist/jwt/index.js +32 -13
  115. package/dist/kernel-_RRHmnMY.js +208 -0
  116. package/dist/kysely/index.d.ts +4 -3
  117. package/dist/kysely/index.js +3 -3
  118. package/dist/live-options-H2eG8dfJ.js +60 -0
  119. package/dist/{load-BZ24CpZP.js → load-DhWEB9P1.js} +16 -10
  120. package/dist/load-DwJUafYN.js +2 -0
  121. package/dist/manifest-iaoBXHKc.js +783 -0
  122. package/dist/manifest-uDS9y5de.d.ts +206 -0
  123. package/dist/{map-DowSO96j.js → map-AcxK9o_D.js} +4 -15
  124. package/dist/{map-claims-B_6I1Rn-.js → map-claims-Z4QZOiFF.js} +13 -4
  125. package/dist/map-error-pgUWNNtG.js +23 -0
  126. package/dist/may-use-DndQ5tQ-.js +77 -0
  127. package/dist/mcp/index.d.ts +54 -22
  128. package/dist/mcp/index.js +218 -178
  129. package/dist/nest/index.d.ts +26 -31
  130. package/dist/nest/index.js +75 -84
  131. package/dist/next/client.d.ts +7 -8
  132. package/dist/next/client.js +11 -9
  133. package/dist/next/index.d.ts +30 -47
  134. package/dist/next/index.js +45 -60
  135. package/dist/next/plugin.d.ts +1 -1
  136. package/dist/next/plugin.js +32 -1
  137. package/dist/node/index.d.ts +9 -28
  138. package/dist/node/index.js +11 -43
  139. package/dist/openai/index.d.ts +6 -15
  140. package/dist/openai/index.js +7 -20
  141. package/dist/openapi/index.d.ts +87 -4
  142. package/dist/openapi/index.js +3 -3
  143. package/dist/{openapi-DcqM8nU7.js → openapi-BqRBvAng.js} +237 -5
  144. package/dist/{openapi-DWD0Uc_4.js → openapi-CqqEbHsL.js} +5 -5
  145. package/dist/{openapi-import-BWRUNNeW.js → openapi-import-cmwetbzw.js} +1 -1
  146. package/dist/{openapi-CwePaF7C.js → openapi-l0xYHkcv.js} +3 -3
  147. package/dist/{openapi-schema-D8j_T9tO.js → openapi-schema--ARjyfQr.js} +2 -2
  148. package/dist/orpc/index.d.ts +15 -28
  149. package/dist/orpc/index.js +74 -117
  150. package/dist/otel/index.d.ts +2 -2
  151. package/dist/parse-BuyjxhZV.js +53 -0
  152. package/dist/parse-local-manifest-BrMozJCo.js +36 -0
  153. package/dist/parse-local-manifest-JLnaBH0S.d.ts +10 -0
  154. package/dist/pdp/index.d.ts +2 -2
  155. package/dist/pdp/index.js +14 -127
  156. package/dist/{permdock-yoZ7EjxX.js → permdock-CbgvLnuo.js} +672 -149
  157. package/dist/{permissions-B8vCg_bI.d.ts → permissions-CDgvKG5L.d.ts} +2 -2
  158. package/dist/{permissions-DC7GROPA.js → permissions-DVoF6dMt.js} +77 -15
  159. package/dist/{permissions-B4apnahQ.d.ts → permissions-DttnqqxC.d.ts} +34 -5
  160. package/dist/{permissions-CofRqesP.js → permissions-RJrovw98.js} +3 -3
  161. package/dist/{pins-CqE1jZuF.js → pins-8ILTftC9.js} +2 -2
  162. package/dist/{policy-Cq2fB8Q5.d.ts → policy-D2W7uv19.d.ts} +2 -2
  163. package/dist/{policy-CInmNGkM.d.ts → policy-IB6yxpC3.d.ts} +351 -42
  164. package/dist/{policy-ANp36PnI.js → policy-xyWg7QdR.js} +173 -22
  165. package/dist/powersync-BylawD_U.js +540 -0
  166. package/dist/powersync-DliZK_-y.js +62 -0
  167. package/dist/powersync-e_AZrKbg.js +2 -0
  168. package/dist/prisma/index.d.ts +3 -2
  169. package/dist/prisma/index.js +45 -20
  170. package/dist/{problem-Cgp9-KZA.js → problem-B43ztKIm.js} +74 -109
  171. package/dist/problem-details-DX075l9V.d.ts +7 -0
  172. package/dist/problem-details-_AMOYz-w.js +144 -0
  173. package/dist/{protected-BuPAycJT.d.ts → protected-BdnIEFkY.d.ts} +5 -4
  174. package/dist/protected-utU-SLuy.js +100 -0
  175. package/dist/protected-xAr24FEC.d.ts +40 -0
  176. package/dist/provider-CSQd7m92.js +52 -0
  177. package/dist/{provider-wTAUda2v.d.ts → provider-DZY281jO.d.ts} +1 -1
  178. package/dist/provider-store-Cfbvo4DE.js +43 -0
  179. package/dist/react/index.d.ts +7 -5
  180. package/dist/react/index.js +5 -4
  181. package/dist/react/provider-client.d.ts +1 -1
  182. package/dist/react/provider-client.js +1 -1
  183. package/dist/react-native/index.d.ts +166 -10
  184. package/dist/react-native/index.js +607 -85
  185. package/dist/{refs-ChLSxbST.js → refs-KYb4ntaz.js} +4 -3
  186. package/dist/{relations-r4soIFZB.js → relations-cjOL01hZ.js} +110 -31
  187. package/dist/replay-BsOyTrdV.js +28 -0
  188. package/dist/replay-CYyiLiwO.d.ts +5 -0
  189. package/dist/resource-ref-CaS9yVPi.js +20 -0
  190. package/dist/revocations-Bhr0aMIC.js +27 -0
  191. package/dist/{rls-BOFU3chG.js → rls-B4ur8nKQ.js} +8 -3
  192. package/dist/rls-DQtdgTHB.js +2521 -0
  193. package/dist/rls-fields-74oZPXWL.js +3582 -0
  194. package/dist/{rls-graph-DxQ39PJj.js → rls-graph-CHwx0V8q.js} +100 -36
  195. package/dist/{rls-import-CXV6LBlS.js → rls-import-BTFVk3jH.js} +7 -6
  196. package/dist/{rls-migrate-DrFPbf8p.js → rls-migrate-CN4TlJTO.js} +6 -5
  197. package/dist/rls-ownership-RuFqaqGz.js +843 -0
  198. package/dist/rls-shared-Cewd_-zI.js +495 -0
  199. package/dist/rls-verify-CVQTHTh5.js +746 -0
  200. package/dist/{row-check-BajTgQZ-.d.ts → row-check-Dt35czLy.d.ts} +12 -15
  201. package/dist/row-conditions-h2HythXQ.js +27 -0
  202. package/dist/rpc-DL9Sqvb1.js +89 -0
  203. package/dist/{run-CJ6UvS3a.js → run-DKDbM4Du.js} +31 -12
  204. package/dist/runtime-CB8gQFvS.js +11 -0
  205. package/dist/{saas-BRrZzJkM.js → saas-DhpJjnBA.js} +17 -7
  206. package/dist/{schema-P8yoma__.js → schema-D3MnDMxa.js} +8 -4
  207. package/dist/scim/index.d.ts +1 -1
  208. package/dist/scim/index.js +1 -1
  209. package/dist/{scim-9NFa0XVZ.js → scim-BFGBBAqR.js} +1 -1
  210. package/dist/{scopes-cKVp_WTw.js → scopes-CVdPrWN-.js} +35 -8
  211. package/dist/server/index.d.ts +22 -11
  212. package/dist/server/index.js +11 -8
  213. package/dist/{credentials-BgRX3WEg.js → server-DlZ28Oz5.js} +1 -1
  214. package/dist/shared-DRu8VFVM.js +123 -0
  215. package/dist/{sink-Cfr9-7YC.d.ts → sink-B1fZzIMf.d.ts} +1 -1
  216. package/dist/skills-Biq5uup3.js +192 -0
  217. package/dist/{skills-C_lpV4Jx.js → skills-Bx-U0irG.js} +10 -4
  218. package/dist/{snapshot-DE8dE_hz.js → snapshot-Enxd0n-s.js} +138 -214
  219. package/dist/snapshot-cache-B-LxUahj.d.ts +45 -0
  220. package/dist/snapshot-cache-D6jLelln.js +44 -0
  221. package/dist/solid/index.d.ts +39 -9
  222. package/dist/solid/index.js +76 -85
  223. package/dist/sources-4p0-4xQm.js +545 -0
  224. package/dist/sources-BdOYLw9j.d.ts +192 -0
  225. package/dist/{sql-Bll1d7y0.js → sql-xdg5f4Fi.js} +6 -1
  226. package/dist/{src-CTNT-PBW.js → src-BDwEZWrZ.js} +149 -11
  227. package/dist/ssf/index.d.ts +3 -2
  228. package/dist/ssf/index.js +3 -29
  229. package/dist/store-DMAWwAJV.js +371 -0
  230. package/dist/{store-Bq90395i.d.ts → store-jOBYpiXC.d.ts} +13 -4
  231. package/dist/store-options-ByhZq1jV.js +716 -0
  232. package/dist/{stores-CkG2HrSg.js → stores-BT2pSCub.js} +10 -63
  233. package/dist/{stores-CvOnu_2T.d.ts → stores-C0IMQrGI.d.ts} +20 -9
  234. package/dist/{stream-BhMfZOwr.d.ts → stream-D1RXubw2.d.ts} +2 -2
  235. package/dist/{stream-Q_xlB6Ko.js → stream-DDpvynSB.js} +16 -2
  236. package/dist/subject-settings-BwBmCdTR.js +128 -0
  237. package/dist/supabase/index.d.ts +133 -6
  238. package/dist/supabase/index.js +4 -3
  239. package/dist/supabase/middleware.d.ts +32 -27
  240. package/dist/supabase/middleware.js +56 -22
  241. package/dist/{supabase-D8UlBA7Z.js → supabase-Boqb9a_Y.js} +3 -3
  242. package/dist/{supabase-DTxGtYdi.js → supabase-C0qESOa-.js} +347 -367
  243. package/dist/supabase-config-BpPXt3x1.js +472 -0
  244. package/dist/supabase-hook-6sYLXg_u.js +2 -0
  245. package/dist/{supabase-hook-D_OqGb_V.js → supabase-hook-CSLQ4zJ3.js} +1037 -705
  246. package/dist/supautils-Cn4R4cJ4.js +91 -0
  247. package/dist/svelte/PermissionBoundary.svelte +37 -0
  248. package/dist/svelte/Protected.svelte +8 -2
  249. package/dist/svelte/index.d.ts +9 -6
  250. package/dist/svelte/index.js +61 -7
  251. package/dist/svelte/runtime.d.ts +4 -3
  252. package/dist/svelte/runtime.js +4 -3
  253. package/dist/svelte/source.d.ts +9 -6
  254. package/dist/svelte/source.js +7 -4
  255. package/dist/terminal/index.d.ts +6 -14
  256. package/dist/terminal/index.js +44 -32
  257. package/dist/testing/index.d.ts +105 -16
  258. package/dist/testing/index.js +504 -40
  259. package/dist/testing/saas/index.d.ts +4 -4
  260. package/dist/testing/saas/index.js +2 -2
  261. package/dist/testing/saas/permissions.d.ts +1 -1
  262. package/dist/testing/saas/permissions.js +1 -1
  263. package/dist/token-CIWxJOCh.js +50 -0
  264. package/dist/trpc/index.d.ts +7 -26
  265. package/dist/trpc/index.js +17 -100
  266. package/dist/types-BnIEz1sU.d.ts +48 -0
  267. package/dist/{types-CxquUByI.d.ts → types-Bvc4oWT6.d.ts} +1 -1
  268. package/dist/{sources-DOpW5Ila.d.ts → types-C97IskBw.d.ts} +86 -127
  269. package/dist/types-CKNSyIf_.d.ts +52 -0
  270. package/dist/types-Cq_H8N_X.d.ts +197 -0
  271. package/dist/{types-D6Z6-rKJ.d.ts → types-DbjRN55U.d.ts} +273 -22
  272. package/dist/{types-BBK-exvJ.d.ts → types-Dnemwd77.d.ts} +7 -1
  273. package/dist/{types-BvBk1wgn.d.ts → types-DxiCGmmd.d.ts} +5 -3
  274. package/dist/{types-B9dmiiab.d.ts → types-QCuYJh4q.d.ts} +1 -1
  275. package/dist/{types-B8w5PFtS.d.ts → types-aqOHTHcp.d.ts} +17 -1
  276. package/dist/unplugin/index.d.ts +1 -1
  277. package/dist/unplugin/index.js +10 -9
  278. package/dist/usage-DorAJiU_.js +2 -0
  279. package/dist/{usage-1ozMubLY.js → usage-GTixvDDU.js} +2 -2
  280. package/dist/{usage-CUnK6Ou9.js → usage-ItS7nLcl.js} +225 -62
  281. package/dist/validation-error-Ba264OaJ.d.ts +26 -0
  282. package/dist/validation-error-CnjZ4t92.js +33 -0
  283. package/dist/{validity-D0uRmJKJ.js → validity-uOp8UpYn.js} +57 -36
  284. package/dist/{verifier-B90agnhl.js → verifier-BxBo6I44.js} +10 -5
  285. package/dist/version-BvacVTZR.js +17 -0
  286. package/dist/views-Soe7bGSC.js +95 -0
  287. package/dist/{vocabulary-Dk0fs-Jk.d.ts → vocabulary-DA8a8zif.d.ts} +1 -1
  288. package/dist/vue/index.d.ts +35 -13
  289. package/dist/vue/index.js +86 -93
  290. package/dist/watch-BwxLTYMZ.js +2 -0
  291. package/dist/watch-DVBJ9cBq.js +128 -0
  292. package/dist/webmcp/index.d.ts +2 -2
  293. package/dist/webmcp/index.js +7 -13
  294. package/package.json +62 -36
  295. package/schemas/approval-request-v1.json +175 -0
  296. package/schemas/catalog-v1.json +29 -1
  297. package/schemas/supabase-claims-v1.json +6 -1
  298. package/schemas/supabase-manifest-v1.json +150 -6
  299. package/skills/permdock/SKILL.md +7 -7
  300. package/skills/permdock-agents/SKILL.md +5 -5
  301. package/skills/permdock-agents/references/runtimes.md +12 -10
  302. package/skills/permdock-approvals/SKILL.md +4 -4
  303. package/skills/permdock-approvals/references/stores-and-resume.md +15 -4
  304. package/skills/permdock-audit/SKILL.md +3 -3
  305. package/skills/permdock-credentials/SKILL.md +4 -4
  306. package/skills/permdock-credentials/references/tokens-keys-links.md +7 -2
  307. package/skills/permdock-data/SKILL.md +4 -4
  308. package/skills/permdock-data/references/queries-and-rls.md +14 -6
  309. package/skills/permdock-data/references/relationships.md +5 -3
  310. package/skills/permdock-tenancy/SKILL.md +9 -6
  311. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +14 -8
  312. package/skills/permdock-wire/SKILL.md +4 -4
  313. package/skills/permdock-wire/references/adapters.md +42 -30
  314. package/skills/permdock-wire/references/policy-options.md +5 -3
  315. package/dist/approvers-aH0PJkmf.js +0 -20
  316. package/dist/catalog-idsHc0vo.js +0 -2
  317. package/dist/collect-B7_TIfmg.js +0 -49
  318. package/dist/collect-fRPAQIWb.js +0 -2
  319. package/dist/compile-CQbvyIBr.d.ts +0 -30
  320. package/dist/config-BPYmjTOp.js +0 -26
  321. package/dist/context-gtAwAILx.js +0 -6
  322. package/dist/create-BKF3dgFk.d.ts +0 -162
  323. package/dist/create-CSkhDU9T.js +0 -222
  324. package/dist/doctor-BGle8Gqi.js +0 -1314
  325. package/dist/helpers-DnSOrhB9.js +0 -682
  326. package/dist/index-fG6NSXlc.d.ts +0 -9
  327. package/dist/kernel-YOGCWNLf.js +0 -211
  328. package/dist/load-QOOm1z70.js +0 -2
  329. package/dist/manifest-DDQbC6K0.d.ts +0 -118
  330. package/dist/map-error-RJ3ZsUyA.js +0 -16
  331. package/dist/may-use-CnFEjVEp.js +0 -37
  332. package/dist/pg-4GJWDUxG.js +0 -953
  333. package/dist/plugin-4gr7IxFJ.js +0 -65
  334. package/dist/protected-B4K3BKoX.js +0 -138
  335. package/dist/protected-wY7nXhY9.d.ts +0 -23
  336. package/dist/provider-_wx46HpB.js +0 -48
  337. package/dist/rls-CJVja9Ww.js +0 -2119
  338. package/dist/rls-helpers-BxRuif0l.js +0 -1346
  339. package/dist/runtime-DP9ttFh1.js +0 -27
  340. package/dist/skills-Dx3QLnMY.js +0 -110
  341. package/dist/source-DoBBYJi2.js +0 -6
  342. package/dist/sources-DVHM3Mwq.js +0 -284
  343. package/dist/store-C6hFW6ta.js +0 -508
  344. package/dist/subject-settings-xt7V845g.js +0 -82
  345. package/dist/supabase-hook-DW-xP4hU.js +0 -2
  346. package/dist/types-DbWdEfcm.d.ts +0 -87
  347. package/dist/types-bva3i4Gf.d.ts +0 -98
  348. package/dist/types-i4BAOvdb.d.ts +0 -97
  349. package/dist/usage-PyEor6GA.js +0 -2
  350. package/dist/version-CnSh33Fj.js +0 -16
@@ -1,35 +1,13 @@
1
- import { n as freezeDeep } from "./freeze-y1_jQL4v.js";
2
- import { C as ownGet, S as isForbiddenKey, d as isFieldRelation, w as ownKeys } from "./permissions-DC7GROPA.js";
3
- import { a as resolveScope, c as scopeChain, f as tenantOf, l as scopeIdOf, r as findScope, s as rootScope, t as activeFor } from "./scopes-cKVp_WTw.js";
4
- //#region src/core/fields.ts
5
- function sanitizeFields(fields) {
6
- if (fields === void 0) return;
7
- return fields.filter((field) => field.length > 0 && !isForbiddenKey(field));
8
- }
9
- function grantCoversField(fields, field, effect) {
10
- if (fields === void 0) return true;
11
- if (fields.length === 0) return false;
12
- if (field === void 0) return effect === "allow";
13
- return fields.includes(field);
14
- }
15
- function pickVisible(row, canField) {
16
- const out = {};
17
- for (const key of ownKeys(row)) if (canField(key)) out[key] = ownGet(row, key);
18
- return freezeDeep(out);
19
- }
20
- function sanitizeContext(value) {
21
- if (value === null || typeof value !== "object" || Array.isArray(value)) return {};
22
- const out = {};
23
- for (const key of ownKeys(value)) out[key] = ownGet(value, key);
24
- return out;
25
- }
26
- //#endregion
1
+ import { f as isFieldRelation } from "./permissions-DVoF6dMt.js";
2
+ import { t as expiredAt } from "./expiry-BoBJ8Tvc.js";
3
+ import { n as sameId } from "./ids-DC4V4CFu.js";
4
+ import { c as rootScope, l as scopeChain, m as tenantOf, o as resolveScope, r as findScope, t as activeFor, u as scopeIdOf } from "./scopes-CVdPrWN-.js";
27
5
  //#region src/core/tenancy.ts
28
6
  function nowSeconds(now) {
29
7
  return now ?? Date.now() / 1e3;
30
8
  }
31
9
  function isMembershipExpired(membership, now) {
32
- return membership.expiresAt !== void 0 && membership.expiresAt <= (now ?? nowSeconds());
10
+ return expiredAt(membership, now ?? nowSeconds());
33
11
  }
34
12
  /** The instances of the first scope the subject holds a live membership in. */
35
13
  function tenantsOf(principal, scopes, now) {
@@ -42,6 +20,11 @@ function tenantsOf(principal, scopes, now) {
42
20
  }
43
21
  return [...tenants];
44
22
  }
23
+ function heldRoleNamesIn(principal, scopes, tenant, now) {
24
+ const names = /* @__PURE__ */ new Set();
25
+ for (const membership of principal?.memberships ?? []) if (!isMembershipExpired(membership, now) && membership.keep === void 0 && tenantOf(membership, scopes) === tenant) for (const name of membership.roles) names.add(name);
26
+ return [...names];
27
+ }
45
28
  /** `requested` when a live membership sits in that instance of the first scope; never a default. */
46
29
  function resolveActiveTenant(principal, requested, scopes, now) {
47
30
  if (requested === void 0) return principal.tenant;
@@ -62,9 +45,30 @@ function relatesTo(resource, field, scope, scopes) {
62
45
  if (resource === void 0) return false;
63
46
  return Object.values(resource.relations).some((relation) => isFieldRelation(relation) && relation.field === field && relation.memberOf !== void 0 && resolveScope(scopes, relation.memberOf) === scope);
64
47
  }
65
- /** The scopes whose key partitions `resource`, from its `memberOf` relations. */
48
+ /** The fields of `resource`'s `memberOf` relations to `scope`. */
49
+ function memberOfFields(resource, scope, scopes) {
50
+ return [...new Set(Object.values(resource.relations).flatMap((relation) => isFieldRelation(relation) && relation.memberOf !== void 0 && resolveScope(scopes, relation.memberOf) === scope ? [relation.field] : []))];
51
+ }
52
+ /**
53
+ * The field of `resource` that holds `scope`'s instance id: the scope's
54
+ * `key` when one of the resource's `memberOf` relations names it, otherwise
55
+ * the field of its one `memberOf` relation to the scope. A table whose own
56
+ * id is the instance (`organizations.id`) declares
57
+ * `{ self: { field: 'id', memberOf: 'organization' } }`.
58
+ */
59
+ function scopeField(resource, scope, scopes) {
60
+ const key = findScope(scopes, scope)?.key;
61
+ if (resource === void 0) return key;
62
+ const fields = memberOfFields(resource, scope, scopes);
63
+ if (key !== void 0 && fields.includes(key)) return key;
64
+ return fields.length === 1 ? fields[0] : key;
65
+ }
66
+ /** The scopes that partition `resource`, from its `memberOf` relations. */
66
67
  function partitionsOf(resource, scopes) {
67
- return scopes.filter((scope) => scope.key !== void 0 && relatesTo(resource, scope.key, scope.name, scopes)).map((scope) => scope.name);
68
+ return scopes.filter((scope) => {
69
+ const field = scopeField(resource, scope.name, scopes);
70
+ return field !== void 0 && relatesTo(resource, field, scope.name, scopes);
71
+ }).map((scope) => scope.name);
68
72
  }
69
73
  /**
70
74
  * Whether `row` lies inside a named membership's instance: for the scope and
@@ -72,23 +76,36 @@ function partitionsOf(resource, scopes) {
72
76
  * resource declares it) must hold the membership's id for it. There is no
73
77
  * cascade: the membership's own scope is checked, never a scope below it.
74
78
  */
75
- function rowInScope(membership, scopes, row, partitioned) {
79
+ function rowInScope(membership, scopes, row, partitioned, fieldOf) {
76
80
  if (membership.scope === void 0 || row === null || typeof row !== "object") return { ok: true };
77
81
  const root = rootScope(scopes);
78
82
  const chain = scopeChain(scopes, membership.scope).toReversed();
79
83
  for (const name of chain) {
80
- const key = findScope(scopes, name)?.key;
84
+ const key = fieldOf?.(name) ?? findScope(scopes, name)?.key;
81
85
  if (key === void 0) continue;
82
86
  const value = Object.hasOwn(row, key) ? row[key] : void 0;
83
- if ((value !== void 0 || partitioned(name, key)) && value !== scopeIdOf(membership, name)) return {
87
+ if ((value !== void 0 || partitioned(name, key)) && !sameId(value, scopeIdOf(membership, name))) return {
84
88
  ok: false,
85
89
  reason: name === root ? "tenant-mismatch" : "scope"
86
90
  };
87
91
  }
88
92
  return { ok: true };
89
93
  }
90
- function matchScopedMembership(subject, scope, roleName, row, scopes, resource, resources, now, rolesOf = (membership) => membership.roles, team, walk) {
94
+ /**
95
+ * Whether a membership answers an instance check for `row`: any membership
96
+ * with a row object, otherwise only the first scope or the instance of the
97
+ * second scope that `team(id)` selected.
98
+ */
99
+ function nestedAppliesWithoutRow(membership, scopes, row, team) {
100
+ if (row !== null && typeof row === "object") return true;
101
+ return membership.scope === rootScope(scopes) || team !== void 0 && membership.scope === scopes[1]?.name;
102
+ }
103
+ function matchScopedMembership(subject, scope, roleName, row, scopes, resource, resources, now, rolesOf = (membership) => membership.roles, team, walk, instance = false, only) {
91
104
  if (scope === "global") return { ok: true };
105
+ if (only !== void 0 && scope !== only) return {
106
+ ok: false,
107
+ reason: "scope"
108
+ };
92
109
  const principal = subject.principal;
93
110
  if (principal === null) return {
94
111
  ok: false,
@@ -108,7 +125,11 @@ function matchScopedMembership(subject, scope, roleName, row, scopes, resource,
108
125
  }
109
126
  if (typeof scope === "string") {
110
127
  if (findScope(scopes, scope) === void 0 || membership.scope !== scope || !inTeam(membership, scopes, team) || !activeFor(membership, scopes, principal.tenant)) continue;
111
- const inside = rowInScope(membership, scopes, row, (name, key) => relatesTo(resource, key, name, scopes));
128
+ if (instance && !nestedAppliesWithoutRow(membership, scopes, row, team)) {
129
+ sawWrongScope = true;
130
+ continue;
131
+ }
132
+ const inside = rowInScope(membership, scopes, row, (name, key) => relatesTo(resource, key, name, scopes), (name) => scopeField(resource, name, scopes));
112
133
  if (!inside.ok) {
113
134
  if (inside.reason === "tenant-mismatch") sawTenantMismatch = true;
114
135
  else sawWrongScope = true;
@@ -165,7 +186,7 @@ function matchResourceMembership(membership, roleResource, row, resource, resour
165
186
  if (row === null || typeof row !== "object") return false;
166
187
  if (on.resource !== roleResource && membershipField(resources.get(roleResource), on.resource, resources) === void 0) return false;
167
188
  const field = membershipField(resource, on.resource, resources);
168
- return field !== void 0 && row[field] === on.id;
189
+ return field !== void 0 && sameId(row[field], on.id);
169
190
  }
170
191
  /**
171
192
  * The row field that holds the id of a `membershipResource` membership: the
@@ -221,4 +242,4 @@ function isActive(validity, now) {
221
242
  return validity.until === void 0 || now < validity.until;
222
243
  }
223
244
  //#endregion
224
- export { matchScopedMembership as a, partitionsOf as c, rowInScope as d, tenantsOf as f, sanitizeFields as g, sanitizeContext as h, isMembershipExpired as i, relatesTo as l, pickVisible as m, normalizeValidity as n, membershipField as o, grantCoversField as p, inTeam as r, nowSeconds as s, isActive as t, resolveActiveTenant as u };
245
+ export { isMembershipExpired as a, membershipField as c, partitionsOf as d, relatesTo as f, tenantsOf as g, scopeField as h, inTeam as i, nestedAppliesWithoutRow as l, rowInScope as m, normalizeValidity as n, matchScopedMembership as o, resolveActiveTenant as p, heldRoleNamesIn as r, memberOfFields as s, isActive as t, nowSeconds as u };
@@ -1,5 +1,5 @@
1
1
  import { n as isReadonlyArray, t as compact } from "./compact-y6vfu2_f.js";
2
- import { E as splitPath, S as isForbiddenKey } from "./permissions-DC7GROPA.js";
2
+ import { T as isForbiddenKey, k as splitPath } from "./permissions-DVoF6dMt.js";
3
3
  import { t as loadJose } from "./load-jose-BL6LH4bL.js";
4
4
  //#region src/jwt/header.ts
5
5
  function compactParts(token) {
@@ -173,7 +173,9 @@ function createKeyCache(options) {
173
173
  const jwksInFlight = /* @__PURE__ */ new Map();
174
174
  let discoveryInFlight;
175
175
  let discoveryCache;
176
+ /** Keyed by `jwks_uri`: keys cached for one URI never answer for another. */
176
177
  let jwksCache;
178
+ const cachedJwks = (href, now) => jwksCache?.href === href && jwksCache.expiresAt > now ? jwksCache.value : void 0;
177
179
  let cooldownUntil = 0;
178
180
  let discoveryCause;
179
181
  const readDiscovery = async (href, issuer, now) => {
@@ -251,9 +253,10 @@ function createKeyCache(options) {
251
253
  };
252
254
  };
253
255
  const loadJwks = (href, now, force) => {
254
- if (!force && jwksCache !== void 0 && jwksCache.expiresAt > now) return Promise.resolve({
256
+ const cached = force ? void 0 : cachedJwks(href, now);
257
+ if (cached !== void 0) return Promise.resolve({
255
258
  ok: true,
256
- jwks: jwksCache.value
259
+ jwks: cached
257
260
  });
258
261
  const pending = jwksInFlight.get(href);
259
262
  if (pending !== void 0) return pending;
@@ -273,6 +276,7 @@ function createKeyCache(options) {
273
276
  const body = await response.json();
274
277
  if (!Array.isArray(body.keys) || body.keys.length === 0) throw new Error("empty jwks");
275
278
  jwksCache = {
279
+ href,
276
280
  value: body,
277
281
  expiresAt: now + clampTtl(cacheControlMaxAge(response.headers.get("cache-control")) ?? maxTtl, minTtl, maxTtl)
278
282
  };
@@ -281,9 +285,10 @@ function createKeyCache(options) {
281
285
  jwks: body
282
286
  };
283
287
  } catch {
284
- if (jwksCache !== void 0 && jwksCache.expiresAt > now) return {
288
+ const stale = cachedJwks(href, now);
289
+ if (stale !== void 0) return {
285
290
  ok: true,
286
- jwks: jwksCache.value
291
+ jwks: stale
287
292
  };
288
293
  return {
289
294
  ok: false,
@@ -0,0 +1,17 @@
1
+ import { t as packageRoot } from "./package-root-zGkxO3oN.js";
2
+ import { readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ //#region src/cli/version.ts
5
+ function cliVersion() {
6
+ return JSON.parse(readFileSync(join(packageRoot(), "package.json"), "utf8")).version;
7
+ }
8
+ function generatorBanner() {
9
+ return `permdock@${cliVersion()}`;
10
+ }
11
+ const CATALOG_SCHEMA = "https://permdock.com/schemas/catalog-v1.json";
12
+ const SUPABASE_MANIFEST_SCHEMA = "https://permdock.com/schemas/supabase-manifest-v1.json";
13
+ const USAGE_REPORT_SCHEMA = "https://permdock.com/schemas/usage-report-v1.json";
14
+ const DOCTOR_REPORT_SCHEMA = "https://permdock.com/schemas/doctor-report-v1.json";
15
+ const CONFIG_REPORT_SCHEMA = "https://permdock.com/schemas/config-report-v1.json";
16
+ //#endregion
17
+ export { USAGE_REPORT_SCHEMA as a, SUPABASE_MANIFEST_SCHEMA as i, CONFIG_REPORT_SCHEMA as n, cliVersion as o, DOCTOR_REPORT_SCHEMA as r, generatorBanner as s, CATALOG_SCHEMA as t };
@@ -0,0 +1,95 @@
1
+ //#region src/client/views.ts
2
+ function permissionSet(store, permissions, data) {
3
+ const granted = [];
4
+ const byKey = {};
5
+ for (const permission of permissions) {
6
+ const state = store.permissionState(permission, data);
7
+ byKey[permission.key] = state;
8
+ if (state.allowed) granted.push(permission);
9
+ }
10
+ return new Proxy({
11
+ granted,
12
+ get(permission) {
13
+ return byKey[permission.key];
14
+ }
15
+ }, { get(target, prop, receiver) {
16
+ if (typeof prop === "string" && Object.hasOwn(byKey, prop)) return byKey[prop];
17
+ return Reflect.get(target, prop, receiver);
18
+ } });
19
+ }
20
+ function filterResult(permdock, permission, rows) {
21
+ const result = permdock.filter(permission, rows);
22
+ result.partial = permdock.where(permission).partial;
23
+ return result;
24
+ }
25
+ function tenantView(permdock) {
26
+ return {
27
+ tenant: permdock.subject.principal?.tenant ?? null,
28
+ tenants: permdock.tenants(),
29
+ switchTo: (id) => permdock.refresh({ tenant: id }),
30
+ status: permdock.status()
31
+ };
32
+ }
33
+ function rolesView(permdock, options) {
34
+ return { roles: (options.team === void 0 ? permdock : permdock.team(options.team)).heldRoles(options.tenant === void 0 ? void 0 : { tenant: options.tenant }) };
35
+ }
36
+ function subjectView(permdock) {
37
+ const snapshot = permdock.snapshot();
38
+ return {
39
+ principal: permdock.subject.principal,
40
+ actor: permdock.subject.actor,
41
+ delegation: permdock.subject.delegation,
42
+ expiresAt: permdock.subject.expiresAt,
43
+ simulated: typeof snapshot === "object" && snapshot !== null && "simulated" in snapshot && snapshot.simulated === true
44
+ };
45
+ }
46
+ /** The root's view of another tenant for a `Protected` with a `tenant` prop; `undefined` answers the active one. */
47
+ function scopedTenant(root, tenant) {
48
+ return tenant === void 0 ? void 0 : root.tenant(tenant);
49
+ }
50
+ /** An instance whose every read answers from `current()`, so a held reference follows the store. */
51
+ function livePermDock(current) {
52
+ return new Proxy({}, { get(_target, prop, _receiver) {
53
+ return Reflect.get(current(), prop);
54
+ } });
55
+ }
56
+ /**
57
+ * `local` answers the active tenant; `scoped`, the root's view of another
58
+ * tenant, is decided on the spot and shares the root's `pending` and `stale`.
59
+ */
60
+ function protectedView(local, root, permission, data, scoped) {
61
+ const state = scoped === void 0 ? local : decideIn(root, scoped, permission, data);
62
+ if (state.status === "pending") return {
63
+ ...state,
64
+ slot: "pending"
65
+ };
66
+ const decision = state.decision;
67
+ if (!state.allowed || decision.outcome !== "granted") return {
68
+ ...state,
69
+ slot: "fallback"
70
+ };
71
+ return {
72
+ allowed: true,
73
+ status: state.status,
74
+ decision,
75
+ slot: "default"
76
+ };
77
+ }
78
+ function decideIn(root, scoped, permission, data) {
79
+ const decision = scoped.decide(permission, data);
80
+ const status = root.status();
81
+ return {
82
+ allowed: decision.outcome === "granted",
83
+ status: status === "pending" || status === "stale" ? status : "ready",
84
+ decision
85
+ };
86
+ }
87
+ function approvalHandle(store, decision) {
88
+ return {
89
+ state: store.approvalState(decision),
90
+ token: decision.outcome === "approval-required" ? decision.token : void 0,
91
+ request: (note) => store.requestApproval(decision, note)
92
+ };
93
+ }
94
+ //#endregion
95
+ export { protectedView as a, subjectView as c, permissionSet as i, tenantView as l, filterResult as n, rolesView as o, livePermDock as r, scopedTenant as s, approvalHandle as t };
@@ -1,4 +1,4 @@
1
- import { n as ActionMeta } from "./permissions-B4apnahQ.js";
1
+ import { n as ActionMeta } from "./permissions-DttnqqxC.js";
2
2
  //#region src/core/vocabulary.d.ts
3
3
  declare const ROLE_KIND: "role";
4
4
  declare const PLAN_KIND: "plan";
@@ -1,9 +1,11 @@
1
- import { Et as TokenVerifier, Mn as Decision, gt as Snapshot, pr as Membership } from "../policy-CInmNGkM.js";
2
- import { d as Permission } from "../permissions-B4apnahQ.js";
3
- import { r as Role } from "../vocabulary-Dk0fs-Jk.js";
4
- import { a as requiredPlans, i as describe } from "../describe-DernyItf.js";
5
- import { t as approvalHeaders } from "../headers-C8SHQccD.js";
6
- import { a as FilterResult, c as PermissionState, d as TenantView, f as UseRolesOptions, i as ClientStatus, n as ApprovalState, r as ClientPermDock, s as PermissionSet, t as ApprovalHandle, u as SubjectView } from "../types-DbWdEfcm.js";
1
+ import { Ft as TokenVerifier, Mr as Membership, Tt as Snapshot, Yn as Decision } from "../policy-IB6yxpC3.js";
2
+ import { f as Permission } from "../permissions-DttnqqxC.js";
3
+ import { r as Role } from "../vocabulary-DA8a8zif.js";
4
+ import { n as requiredPlans } from "../problem-details-DX075l9V.js";
5
+ import { i as describe } from "../describe-DMYiCjJV.js";
6
+ import { t as PermissionBoundaryState } from "../boundary-BmHxVH1J.js";
7
+ import { t as approvalHeaders } from "../headers-Cf-zWvsO.js";
8
+ import { a as FilterResult, c as SubjectView, i as ClientStatus, l as TenantView, n as ApprovalState, o as PermissionSet, r as ClientPermDock, s as PermissionState, t as ApprovalHandle, u as UseRolesOptions } from "../types-CKNSyIf_.js";
7
9
  import { ComputedRef, DefineComponent, MaybeRefOrGetter, Plugin } from "vue";
8
10
  //#region src/vue/types.d.ts
9
11
  type PermDockPluginOptions = {
@@ -13,13 +15,22 @@ type PermDockPluginOptions = {
13
15
  * `setup` under `<Suspense>`).
14
16
  */
15
17
  readonly snapshot: MaybeRefOrGetter<Snapshot | string> | PromiseLike<Snapshot | string>;
16
- readonly endpoint?: string;
18
+ /**
19
+ * The AuthZEN evaluations endpoint for checks the snapshot cannot answer.
20
+ * `false` never calls one: such a check is denied with reason `server-only`.
21
+ */
22
+ readonly endpoint?: string | false;
23
+ /** Where `refresh()` fetches a fresh snapshot. Defaults to `endpoint`. */
24
+ readonly snapshotUrl?: string;
17
25
  readonly approvals?: string;
18
- readonly tenant?: string;
26
+ /** A ref or getter switches the active tenant (`refresh({ tenant })`) when it changes. */
27
+ readonly tenant?: MaybeRefOrGetter<string | undefined>;
19
28
  readonly fetch?: typeof fetch;
20
- readonly headers?: Readonly<Record<string, string>>;
29
+ /** Read on every request: a ref or getter carries a rotated token without rebuilding the store. */
30
+ readonly headers?: MaybeRefOrGetter<Readonly<Record<string, string>> | undefined>;
21
31
  readonly maxAge?: number;
22
- readonly verifier?: TokenVerifier;
32
+ /** Read on every verification; set it at install to verify signed snapshots. */
33
+ readonly verifier?: MaybeRefOrGetter<TokenVerifier | undefined>;
23
34
  };
24
35
  //#endregion
25
36
  //#region src/vue/composables.d.ts
@@ -37,12 +48,23 @@ export declare function useRoles(options?: MaybeRefOrGetter<UseRolesOptions>): C
37
48
  readonly roles: readonly Role[];
38
49
  }>;
39
50
  export declare function useAssignableRoles(): ComputedRef<readonly Role[]>;
40
- export declare function useAssignablePermissions(options?: {
51
+ export declare function useAssignablePermissions(options?: MaybeRefOrGetter<{
41
52
  readonly tenant?: string;
42
- }): ComputedRef<readonly Permission[]>;
53
+ }>): ComputedRef<readonly Permission[]>;
43
54
  export declare function useSubject(): ComputedRef<SubjectView>;
44
55
  export declare function useApproval(decision: MaybeRefOrGetter<Decision>): ComputedRef<ApprovalHandle>;
45
56
  //#endregion
57
+ //#region src/vue/boundary.d.ts
58
+ /**
59
+ * Catches `PermDockDeniedError` and `PermDockApprovalRequiredError` thrown
60
+ * by a descendant and renders the `denied` slot, or the `approval` slot for
61
+ * an approval request (default `denied`). The slots receive the refused
62
+ * permission and `retry()`. Any other error propagates.
63
+ */
64
+ export declare const PermissionBoundary: DefineComponent;
65
+ /** Inside a `PermissionBoundary`: what was refused and `retry()`, or `null` while the children render. */
66
+ export declare function usePermissionBoundary(): PermissionBoundaryState | null;
67
+ //#endregion
46
68
  //#region src/vue/plugin.d.ts
47
69
  export declare const permdockPlugin: Plugin<PermDockPluginOptions>;
48
70
  //#endregion
@@ -54,4 +76,4 @@ type ProtectedProps = {
54
76
  };
55
77
  export declare const Protected: DefineComponent<ProtectedProps>;
56
78
  //#endregion
57
- export { type ApprovalHandle, type ApprovalState, type ClientPermDock, type ClientStatus, type FilterResult, type PermDockPluginOptions, type PermissionSet, type PermissionState, type SubjectView, type TenantView, type UseRolesOptions, approvalHeaders, describe, requiredPlans };
79
+ export { type ApprovalHandle, type ApprovalState, type ClientPermDock, type ClientStatus, type FilterResult, type PermDockPluginOptions, type PermissionBoundaryState, type PermissionSet, type PermissionState, type ProtectedProps, type SubjectView, type TenantView, type UseRolesOptions, approvalHeaders, describe, requiredPlans };
package/dist/vue/index.js CHANGED
@@ -1,10 +1,11 @@
1
- import { t as compact } from "../compact-y6vfu2_f.js";
2
- import { n as requiredPlans, t as describe } from "../describe-Bt1YD5uS.js";
3
- import { t as emptySnapshot } from "../from-snapshot-BMGnhmgv.js";
4
- import { t as approvalHeaders } from "../headers-B5RRv3Xm.js";
5
- import { t as createClientStore } from "../store-C6hFW6ta.js";
6
- import { t as isPromiseLike } from "../source-DoBBYJi2.js";
7
- import { computed, defineComponent, effectScope, inject, isRef, onScopeDispose, shallowRef, toValue, watch } from "vue";
1
+ import { r as requiredPlans } from "../problem-details-_AMOYz-w.js";
2
+ import { t as describe } from "../describe-B_gVZEVi.js";
3
+ import { t as approvalHeaders } from "../headers-BZSDieNT.js";
4
+ import { i as isPromiseLike } from "../store-options-ByhZq1jV.js";
5
+ import { a as protectedView, c as subjectView, i as permissionSet, l as tenantView, n as filterResult, o as rolesView, r as livePermDock, s as scopedTenant, t as approvalHandle } from "../views-Soe7bGSC.js";
6
+ import { n as boundaryFallback, t as boundaryDigest } from "../boundary-BM8a_P6E.js";
7
+ import { n as switchTenant, t as providerStore } from "../provider-store-Cfbvo4DE.js";
8
+ import { computed, defineComponent, effectScope, getCurrentScope, inject, isRef, onErrorCaptured, onScopeDispose, provide, shallowRef, toValue, watch } from "vue";
8
9
  //#region src/vue/context.ts
9
10
  const permDockKey = Symbol("permdock");
10
11
  //#endregion
@@ -15,6 +16,7 @@ function useStore() {
15
16
  return store;
16
17
  }
17
18
  function useTick(store) {
19
+ if (getCurrentScope() === void 0) throw new Error("PermDock: call composables in setup() or an effectScope, which removes their store subscription.");
18
20
  const tick = shallowRef(0);
19
21
  onScopeDispose(store.subscribe(() => {
20
22
  tick.value += 1;
@@ -26,9 +28,7 @@ function useTick(store) {
26
28
  }
27
29
  function usePermDock() {
28
30
  const permdock = useTick(useStore());
29
- return new Proxy({}, { get(_target, prop, _receiver) {
30
- return Reflect.get(permdock.value, prop);
31
- } });
31
+ return livePermDock(() => permdock.value);
32
32
  }
33
33
  function usePermission(permission, data) {
34
34
  const store = useStore();
@@ -48,40 +48,16 @@ function usePermissions(permissions, data) {
48
48
  const permdock = useTick(store);
49
49
  return computed(() => {
50
50
  permdock.value;
51
- const granted = [];
52
- const byKey = {};
53
- for (const permission of toValue(permissions)) {
54
- const next = store.permissionState(permission, toValue(data));
55
- byKey[permission.key] = next;
56
- if (next.allowed) granted.push(permission);
57
- }
58
- return new Proxy({
59
- granted,
60
- get(permission) {
61
- return byKey[permission.key];
62
- }
63
- }, { get(target, prop, receiver) {
64
- if (typeof prop === "string" && Object.hasOwn(byKey, prop)) return byKey[prop];
65
- return Reflect.get(target, prop, receiver);
66
- } });
51
+ return permissionSet(store, toValue(permissions), toValue(data));
67
52
  });
68
53
  }
69
54
  function useFilter(permission, rows) {
70
55
  const permdock = useTick(useStore());
71
- return computed(() => {
72
- const result = [...permdock.value.filter(permission, toValue(rows))];
73
- result.partial = permdock.value.where(permission).partial;
74
- return result;
75
- });
56
+ return computed(() => filterResult(permdock.value, permission, toValue(rows)));
76
57
  }
77
58
  function useTenant() {
78
59
  const permdock = useTick(useStore());
79
- return computed(() => ({
80
- tenant: permdock.value.subject.principal?.tenant ?? null,
81
- tenants: permdock.value.tenants(),
82
- switchTo: (id) => permdock.value.refresh({ tenant: id }),
83
- status: permdock.value.status()
84
- }));
60
+ return computed(() => tenantView(permdock.value));
85
61
  }
86
62
  function useMemberships() {
87
63
  const permdock = useTick(useStore());
@@ -89,10 +65,7 @@ function useMemberships() {
89
65
  }
90
66
  function useRoles(options = {}) {
91
67
  const permdock = useTick(useStore());
92
- return computed(() => {
93
- const next = toValue(options);
94
- return { roles: (next.team === void 0 ? permdock.value : permdock.value.team(next.team)).heldRoles(next.tenant === void 0 ? void 0 : { tenant: next.tenant }) };
95
- });
68
+ return computed(() => rolesView(permdock.value, toValue(options)));
96
69
  }
97
70
  function useAssignableRoles() {
98
71
  const permdock = useTick(useStore());
@@ -100,62 +73,86 @@ function useAssignableRoles() {
100
73
  }
101
74
  function useAssignablePermissions(options = {}) {
102
75
  const permdock = useTick(useStore());
103
- return computed(() => permdock.value.assignablePermissions(options));
76
+ return computed(() => permdock.value.assignablePermissions(toValue(options)));
104
77
  }
105
78
  function useSubject() {
106
79
  const permdock = useTick(useStore());
107
- return computed(() => {
108
- const snapshot = permdock.value.snapshot();
109
- const simulated = typeof snapshot === "object" && snapshot !== null && "simulated" in snapshot && snapshot.simulated === true;
110
- return {
111
- principal: permdock.value.subject.principal,
112
- actor: permdock.value.subject.actor,
113
- delegation: permdock.value.subject.delegation,
114
- expiresAt: permdock.value.subject.expiresAt,
115
- simulated
116
- };
117
- });
80
+ return computed(() => subjectView(permdock.value));
118
81
  }
119
82
  function useApproval(decision) {
120
83
  const store = useStore();
121
84
  const permdock = useTick(store);
122
85
  return computed(() => {
123
86
  permdock.value;
124
- const next = toValue(decision);
125
- return {
126
- state: store.approvalState(next),
127
- token: next.outcome === "approval-required" ? next.token : void 0,
128
- request: (note) => store.requestApproval(next, note)
129
- };
87
+ return approvalHandle(store, toValue(decision));
130
88
  });
131
89
  }
132
90
  //#endregion
91
+ //#region src/vue/boundary.ts
92
+ const boundaryKey = Symbol("permdock-boundary");
93
+ /**
94
+ * Catches `PermDockDeniedError` and `PermDockApprovalRequiredError` thrown
95
+ * by a descendant and renders the `denied` slot, or the `approval` slot for
96
+ * an approval request (default `denied`). The slots receive the refused
97
+ * permission and `retry()`. Any other error propagates.
98
+ */
99
+ const PermissionBoundary = defineComponent({
100
+ name: "PermissionBoundary",
101
+ setup(_props, { slots }) {
102
+ const state = shallowRef(null);
103
+ provide(boundaryKey, state);
104
+ onErrorCaptured((error) => {
105
+ const digest = boundaryDigest(error);
106
+ if (digest === null) return;
107
+ state.value = {
108
+ ...digest,
109
+ retry: () => {
110
+ state.value = null;
111
+ }
112
+ };
113
+ return false;
114
+ });
115
+ return () => {
116
+ const current = state.value;
117
+ if (current === null) return slots["default"]?.() ?? null;
118
+ return boundaryFallback(current, {
119
+ denied: slots["denied"],
120
+ approval: slots["approval"]
121
+ })?.(current) ?? null;
122
+ };
123
+ }
124
+ });
125
+ /** Inside a `PermissionBoundary`: what was refused and `retry()`, or `null` while the children render. */
126
+ function usePermissionBoundary() {
127
+ return inject(boundaryKey, null)?.value ?? null;
128
+ }
129
+ //#endregion
133
130
  //#region src/vue/plugin.ts
134
131
  const permdockPlugin = { install(app, options) {
135
132
  const source = options.snapshot;
136
133
  const promised = isPromiseLike(source);
137
- const store = createClientStore(compact({
138
- snapshot: promised ? emptySnapshot() : toValue(source),
139
- endpoint: options.endpoint,
140
- approvals: options.approvals,
141
- tenant: options.tenant,
134
+ const store = providerStore({
135
+ ...options,
136
+ tenant: toValue(options.tenant)
137
+ }, () => ({
138
+ headers: toValue(options.headers),
142
139
  fetch: options.fetch,
143
- headers: options.headers,
144
- maxAge: options.maxAge,
145
- verifier: options.verifier
146
- }));
147
- if (promised) store.follow(source);
148
- else if (isRef(source) || typeof source === "function") {
149
- const scope = effectScope(true);
150
- scope.run(() => {
151
- watch(() => toValue(source), (next) => {
152
- store.replace(next);
153
- });
140
+ verifier: toValue(options.verifier)
141
+ }), promised ? source : toValue(source));
142
+ const scope = effectScope(true);
143
+ scope.run(() => {
144
+ if (!promised && (isRef(source) || typeof source === "function")) watch(() => toValue(source), (next) => {
145
+ store.replace(next);
154
146
  });
155
- app.onUnmount(() => {
156
- scope.stop();
147
+ const tenant = options.tenant;
148
+ if (isRef(tenant) || typeof tenant === "function") watch(() => toValue(tenant), (next) => {
149
+ switchTenant(store, next);
157
150
  });
158
- }
151
+ });
152
+ app.onUnmount(() => {
153
+ scope.stop();
154
+ store.dispose();
155
+ });
159
156
  app.provide(permDockKey, store);
160
157
  } };
161
158
  //#endregion
@@ -168,7 +165,7 @@ const Protected = defineComponent({
168
165
  required: true
169
166
  },
170
167
  data: {
171
- type: Object,
168
+ type: null,
172
169
  required: false
173
170
  },
174
171
  tenant: {
@@ -179,25 +176,21 @@ const Protected = defineComponent({
179
176
  setup(props, { slots }) {
180
177
  const local = usePermission(() => props.permission, () => props.data);
181
178
  const root = usePermDock();
179
+ const scoped = computed(() => scopedTenant(root, props.tenant));
182
180
  return () => {
183
- const scoped = props.tenant === void 0 ? {
181
+ const view = protectedView({
184
182
  allowed: local.allowed.value,
185
183
  status: local.status.value,
186
184
  decision: local.decision.value
187
- } : tenantView(root.tenant(props.tenant), props.permission, props.data);
188
- if (scoped.status === "pending") return slots["pending"]?.() ?? null;
189
- if (!scoped.allowed || scoped.decision.outcome !== "granted") return slots["fallback"]?.({ decision: scoped.decision }) ?? null;
190
- return slots["default"]?.({ decision: scoped.decision }) ?? null;
185
+ }, root, props.permission, props.data, scoped.value);
186
+ switch (view.slot) {
187
+ case "pending": return slots["pending"]?.() ?? null;
188
+ case "fallback": return slots["fallback"]?.({ decision: view.decision }) ?? null;
189
+ case "default": return slots["default"]?.({ decision: view.decision }) ?? null;
190
+ default: return view;
191
+ }
191
192
  };
192
193
  }
193
194
  });
194
- function tenantView(permdock, permission, data) {
195
- const decision = permdock.decide(permission, data);
196
- return {
197
- allowed: decision.outcome === "granted",
198
- status: "ready",
199
- decision
200
- };
201
- }
202
195
  //#endregion
203
- export { Protected, approvalHeaders, describe, permdockPlugin, requiredPlans, useApproval, useAssignablePermissions, useAssignableRoles, useFilter, useMemberships, usePermDock, usePermission, usePermissions, useRoles, useSubject, useTenant };
196
+ export { PermissionBoundary, Protected, approvalHeaders, describe, permdockPlugin, requiredPlans, useApproval, useAssignablePermissions, useAssignableRoles, useFilter, useMemberships, usePermDock, usePermission, usePermissionBoundary, usePermissions, useRoles, useSubject, useTenant };