permdock 0.1.0 → 0.2.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 (349) 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-cmvX2jDe.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 +206 -0
  18. package/dist/better-supabase/index.js +620 -0
  19. package/dist/bind-CVy3Espv.d.ts +25 -0
  20. package/dist/bind-VnYn2HKq.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-B68OFnZx.js → capability-4qPdO9gk.js} +7 -5
  25. package/dist/{capability-BDG_nkxt.d.ts → capability-Dq43tT1u.d.ts} +2 -2
  26. package/dist/catalog/index.d.ts +1 -1
  27. package/dist/catalog/index.js +1 -1
  28. package/dist/catalog-BjZSovXQ.js +2 -0
  29. package/dist/{catalog-doc-BSo_Q_-6.js → catalog-doc-Dsc9y7sd.js} +23 -12
  30. package/dist/{catalog-B0E6bggc.js → catalog-h2tlKFkq.js} +2 -2
  31. package/dist/{catalog-H-vFGwWK.js → catalog-z8q6bi_r.js} +4 -4
  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-BGhHS-lY.js} +2 -2
  44. package/dist/{cloud-Cuxr6Czw.js → cloud-Bo3e9Ak3.js} +7 -6
  45. package/dist/{collect-O-tOtbnk.js → collect-DDDv_ESs.js} +194 -42
  46. package/dist/collect-DLlujdHC.js +83 -0
  47. package/dist/collect-rG2IQ3t0.js +2 -0
  48. package/dist/{commands-BMh_Etm2.js → commands-DWOrSQic.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-CNnl6uIt.d.ts +94 -0
  53. package/dist/config-BJiM-xAm.js +157 -0
  54. package/dist/config-Bn00Z3ks.js +36 -0
  55. package/dist/config-report-Dw_JcUqT.js +44 -0
  56. package/dist/{connection-JvqwHODC.js → connection-CU8MQxRi.js} +1 -1
  57. package/dist/{context-CKEAabd7.js → context-Ttp0ekMT.js} +36 -27
  58. package/dist/convex/index.d.ts +9 -4
  59. package/dist/convex/index.js +14 -4
  60. package/dist/create-BWyx3jua.d.ts +245 -0
  61. package/dist/create-CPhDL6qx.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-PdoqESvg.d.ts} +9 -10
  66. package/dist/{diff-x5Il8LVa.js → diff-B8Tunc3o.js} +44 -11
  67. package/dist/{diff-BUzf5Poi.js → diff-CzqLxZ77.js} +2 -2
  68. package/dist/doctor-WpvG6p4k.js +1194 -0
  69. package/dist/doctor-collect-ByfYlNv1.js +664 -0
  70. package/dist/{doctor-Bqo6FwUa.js → doctor-rOr-4ZfS.js} +2 -2
  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-DAqevpNk.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-C3sHpZNS.js} +65 -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-LF_hS-yn.d.ts → index-A0YNL8jZ.d.ts} +1 -1
  105. package/dist/index-CtE07CBF.d.ts +6 -0
  106. package/dist/{index-xIxJLwOQ.d.ts → index-D3vbkoSI.d.ts} +75 -7
  107. package/dist/{index-CltcQ4Bf.d.ts → index-D6_cSa1z.d.ts} +68 -5
  108. package/dist/index.d.ts +14 -9
  109. package/dist/index.js +22 -17
  110. package/dist/instance-options-BK_rNOSC.d.ts +11 -0
  111. package/dist/instance-options-Dhhcnm3y.js +22 -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-GSQnMz3O.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-CwePaF7C.js → openapi-Bbg4wGVL.js} +3 -3
  144. package/dist/{openapi-DcqM8nU7.js → openapi-BqRBvAng.js} +237 -5
  145. package/dist/{openapi-DWD0Uc_4.js → openapi-CqqEbHsL.js} +5 -5
  146. package/dist/{openapi-import-BWRUNNeW.js → openapi-import-cmwetbzw.js} +1 -1
  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-BkGQNzAh.d.ts +10 -0
  153. package/dist/parse-local-manifest-BrMozJCo.js +36 -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-CzqXjCpU.js} +641 -126
  157. package/dist/{permissions-B8vCg_bI.d.ts → permissions-CDgvKG5L.d.ts} +2 -2
  158. package/dist/{permissions-CofRqesP.js → permissions-CpZrivYv.js} +3 -3
  159. package/dist/{permissions-DC7GROPA.js → permissions-DVoF6dMt.js} +77 -15
  160. package/dist/{permissions-B4apnahQ.d.ts → permissions-DttnqqxC.d.ts} +34 -5
  161. package/dist/{pins-CqE1jZuF.js → pins-8ILTftC9.js} +2 -2
  162. package/dist/{policy-CInmNGkM.d.ts → policy-CFZAr_Al.d.ts} +330 -37
  163. package/dist/{policy-Cq2fB8Q5.d.ts → policy-D8UFyERw.d.ts} +2 -2
  164. package/dist/{policy-ANp36PnI.js → policy-xyWg7QdR.js} +173 -22
  165. package/dist/powersync-A8x_Yyvh.js +2 -0
  166. package/dist/powersync-C7kLglqX.js +540 -0
  167. package/dist/powersync-yW1UUFzp.js +62 -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-CkL50EEf.d.ts +7 -0
  172. package/dist/problem-details-_AMOYz-w.js +144 -0
  173. package/dist/{protected-BuPAycJT.d.ts → protected-CNsMzrVd.d.ts} +5 -4
  174. package/dist/protected-Cs6kTaHo.js +100 -0
  175. package/dist/protected-bZs6rbT1.d.ts +40 -0
  176. package/dist/{provider-wTAUda2v.d.ts → provider-Cjr62YMV.d.ts} +1 -1
  177. package/dist/provider-DLzpb2Xz.js +52 -0
  178. package/dist/provider-store-DNyC1y48.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-sqBGMnNs.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-BMNydpHk.js +2521 -0
  192. package/dist/{rls-BOFU3chG.js → rls-CEvs64Kj.js} +8 -3
  193. package/dist/rls-fields-BMasREhR.js +3502 -0
  194. package/dist/{rls-graph-DxQ39PJj.js → rls-graph-pc9fuXYm.js} +100 -36
  195. package/dist/{rls-import-CXV6LBlS.js → rls-import-D8F7j35Q.js} +7 -6
  196. package/dist/{rls-migrate-DrFPbf8p.js → rls-migrate-7wikfrVI.js} +6 -5
  197. package/dist/rls-ownership-B5Lkq62W.js +843 -0
  198. package/dist/rls-shared-aOQ4hGTO.js +493 -0
  199. package/dist/rls-verify-D8B7dOTh.js +745 -0
  200. package/dist/{row-check-BajTgQZ-.d.ts → row-check-Dt35czLy.d.ts} +12 -15
  201. package/dist/rpc-DOK54_CS.js +89 -0
  202. package/dist/{run-CJ6UvS3a.js → run-YXCJDNYk.js} +31 -12
  203. package/dist/runtime-CB8gQFvS.js +11 -0
  204. package/dist/{saas-BRrZzJkM.js → saas-Bj_FFkjN.js} +17 -7
  205. package/dist/{schema-P8yoma__.js → schema-D3MnDMxa.js} +8 -4
  206. package/dist/scim/index.d.ts +1 -1
  207. package/dist/scim/index.js +1 -1
  208. package/dist/{scim-9NFa0XVZ.js → scim-BFGBBAqR.js} +1 -1
  209. package/dist/{scopes-cKVp_WTw.js → scopes-CVdPrWN-.js} +35 -8
  210. package/dist/server/index.d.ts +22 -11
  211. package/dist/server/index.js +11 -8
  212. package/dist/{credentials-BgRX3WEg.js → server-DlZ28Oz5.js} +1 -1
  213. package/dist/shared-DRu8VFVM.js +123 -0
  214. package/dist/{sink-Cfr9-7YC.d.ts → sink-Gs6TTVa-.d.ts} +1 -1
  215. package/dist/skills-Biq5uup3.js +192 -0
  216. package/dist/{skills-C_lpV4Jx.js → skills-JaymNCdK.js} +10 -4
  217. package/dist/{snapshot-DE8dE_hz.js → snapshot-Enxd0n-s.js} +138 -214
  218. package/dist/snapshot-cache-D6jLelln.js +44 -0
  219. package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
  220. package/dist/solid/index.d.ts +39 -9
  221. package/dist/solid/index.js +76 -85
  222. package/dist/sources-B0UvrJ21.js +534 -0
  223. package/dist/sources-BcJgw0lt.d.ts +192 -0
  224. package/dist/{sql-Bll1d7y0.js → sql-xdg5f4Fi.js} +6 -1
  225. package/dist/{src-CTNT-PBW.js → src-CSbUiozF.js} +149 -11
  226. package/dist/ssf/index.d.ts +3 -2
  227. package/dist/ssf/index.js +3 -29
  228. package/dist/store-DMAWwAJV.js +371 -0
  229. package/dist/{store-Bq90395i.d.ts → store-D_pjn91-.d.ts} +13 -4
  230. package/dist/store-options-yO0V6gRn.js +716 -0
  231. package/dist/{stores-CkG2HrSg.js → stores-4_sqiOA1.js} +10 -63
  232. package/dist/{stores-CvOnu_2T.d.ts → stores-DVR5NHLE.d.ts} +20 -9
  233. package/dist/{stream-Q_xlB6Ko.js → stream-DDpvynSB.js} +16 -2
  234. package/dist/{stream-BhMfZOwr.d.ts → stream-DlvG2hs-.d.ts} +2 -2
  235. package/dist/subject-settings-BwBmCdTR.js +128 -0
  236. package/dist/supabase/index.d.ts +122 -6
  237. package/dist/supabase/index.js +4 -3
  238. package/dist/supabase/middleware.d.ts +32 -27
  239. package/dist/supabase/middleware.js +56 -22
  240. package/dist/{supabase-D8UlBA7Z.js → supabase-CwafwxxF.js} +3 -3
  241. package/dist/{supabase-DTxGtYdi.js → supabase-DTBaC20O.js} +345 -367
  242. package/dist/supabase-config-Bs44dare.js +472 -0
  243. package/dist/{supabase-hook-D_OqGb_V.js → supabase-hook-BuxLQLpU.js} +994 -708
  244. package/dist/supabase-hook-D5qVd_D8.js +2 -0
  245. package/dist/supautils-DYZnzRWV.js +91 -0
  246. package/dist/svelte/PermissionBoundary.svelte +37 -0
  247. package/dist/svelte/Protected.svelte +8 -2
  248. package/dist/svelte/index.d.ts +9 -6
  249. package/dist/svelte/index.js +61 -7
  250. package/dist/svelte/runtime.d.ts +4 -3
  251. package/dist/svelte/runtime.js +4 -3
  252. package/dist/svelte/source.d.ts +9 -6
  253. package/dist/svelte/source.js +7 -4
  254. package/dist/terminal/index.d.ts +6 -14
  255. package/dist/terminal/index.js +44 -32
  256. package/dist/testing/index.d.ts +105 -16
  257. package/dist/testing/index.js +504 -40
  258. package/dist/testing/saas/index.d.ts +4 -4
  259. package/dist/testing/saas/index.js +2 -2
  260. package/dist/testing/saas/permissions.d.ts +1 -1
  261. package/dist/testing/saas/permissions.js +1 -1
  262. package/dist/token-CIWxJOCh.js +50 -0
  263. package/dist/trpc/index.d.ts +7 -26
  264. package/dist/trpc/index.js +17 -100
  265. package/dist/types-9AWO9EGt.d.ts +197 -0
  266. package/dist/{types-D6Z6-rKJ.d.ts → types-BPxgszlT.d.ts} +260 -22
  267. package/dist/{types-BvBk1wgn.d.ts → types-BVyImy5I.d.ts} +5 -3
  268. package/dist/{types-CxquUByI.d.ts → types-Bvc4oWT6.d.ts} +1 -1
  269. package/dist/types-C3s9xVJG.d.ts +48 -0
  270. package/dist/{types-BBK-exvJ.d.ts → types-Dnemwd77.d.ts} +7 -1
  271. package/dist/types-kxznc7cn.d.ts +52 -0
  272. package/dist/{types-B8w5PFtS.d.ts → types-vKyAMtcX.d.ts} +17 -1
  273. package/dist/{types-B9dmiiab.d.ts → types-vNSDF7Dq.d.ts} +1 -1
  274. package/dist/{sources-DOpW5Ila.d.ts → types-yF5LmQVD.d.ts} +86 -127
  275. package/dist/unplugin/index.d.ts +1 -1
  276. package/dist/unplugin/index.js +10 -9
  277. package/dist/{usage-1ozMubLY.js → usage-D07N9QJ3.js} +2 -2
  278. package/dist/usage-D82l1CwK.js +2 -0
  279. package/dist/{usage-CUnK6Ou9.js → usage-DG1oeCca.js} +225 -62
  280. package/dist/validation-error-CnjZ4t92.js +33 -0
  281. package/dist/validation-error-CtF23SrC.d.ts +26 -0
  282. package/dist/{validity-D0uRmJKJ.js → validity-uOp8UpYn.js} +57 -36
  283. package/dist/{verifier-B90agnhl.js → verifier-BxBo6I44.js} +10 -5
  284. package/dist/version-BvacVTZR.js +17 -0
  285. package/dist/views-Soe7bGSC.js +95 -0
  286. package/dist/{vocabulary-Dk0fs-Jk.d.ts → vocabulary-DA8a8zif.d.ts} +1 -1
  287. package/dist/vue/index.d.ts +35 -13
  288. package/dist/vue/index.js +86 -93
  289. package/dist/watch-Etoa_Mvr.js +2 -0
  290. package/dist/watch-UihESpsJ.js +128 -0
  291. package/dist/webmcp/index.d.ts +2 -2
  292. package/dist/webmcp/index.js +7 -13
  293. package/package.json +62 -36
  294. package/schemas/approval-request-v1.json +175 -0
  295. package/schemas/catalog-v1.json +29 -1
  296. package/schemas/supabase-claims-v1.json +6 -1
  297. package/schemas/supabase-manifest-v1.json +150 -6
  298. package/skills/permdock/SKILL.md +7 -7
  299. package/skills/permdock-agents/SKILL.md +5 -5
  300. package/skills/permdock-agents/references/runtimes.md +12 -10
  301. package/skills/permdock-approvals/SKILL.md +4 -4
  302. package/skills/permdock-approvals/references/stores-and-resume.md +15 -4
  303. package/skills/permdock-audit/SKILL.md +3 -3
  304. package/skills/permdock-credentials/SKILL.md +4 -4
  305. package/skills/permdock-credentials/references/tokens-keys-links.md +7 -2
  306. package/skills/permdock-data/SKILL.md +4 -4
  307. package/skills/permdock-data/references/queries-and-rls.md +14 -6
  308. package/skills/permdock-data/references/relationships.md +5 -3
  309. package/skills/permdock-tenancy/SKILL.md +9 -6
  310. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +14 -8
  311. package/skills/permdock-wire/SKILL.md +4 -4
  312. package/skills/permdock-wire/references/adapters.md +42 -30
  313. package/skills/permdock-wire/references/policy-options.md +5 -3
  314. package/dist/approvers-aH0PJkmf.js +0 -20
  315. package/dist/catalog-idsHc0vo.js +0 -2
  316. package/dist/collect-B7_TIfmg.js +0 -49
  317. package/dist/collect-fRPAQIWb.js +0 -2
  318. package/dist/compile-CQbvyIBr.d.ts +0 -30
  319. package/dist/config-BPYmjTOp.js +0 -26
  320. package/dist/context-gtAwAILx.js +0 -6
  321. package/dist/create-BKF3dgFk.d.ts +0 -162
  322. package/dist/create-CSkhDU9T.js +0 -222
  323. package/dist/doctor-BGle8Gqi.js +0 -1314
  324. package/dist/helpers-DnSOrhB9.js +0 -682
  325. package/dist/index-fG6NSXlc.d.ts +0 -9
  326. package/dist/kernel-YOGCWNLf.js +0 -211
  327. package/dist/load-QOOm1z70.js +0 -2
  328. package/dist/manifest-DDQbC6K0.d.ts +0 -118
  329. package/dist/map-error-RJ3ZsUyA.js +0 -16
  330. package/dist/may-use-CnFEjVEp.js +0 -37
  331. package/dist/pg-4GJWDUxG.js +0 -953
  332. package/dist/plugin-4gr7IxFJ.js +0 -65
  333. package/dist/protected-B4K3BKoX.js +0 -138
  334. package/dist/protected-wY7nXhY9.d.ts +0 -23
  335. package/dist/provider-_wx46HpB.js +0 -48
  336. package/dist/rls-CJVja9Ww.js +0 -2119
  337. package/dist/rls-helpers-BxRuif0l.js +0 -1346
  338. package/dist/runtime-DP9ttFh1.js +0 -27
  339. package/dist/skills-Dx3QLnMY.js +0 -110
  340. package/dist/source-DoBBYJi2.js +0 -6
  341. package/dist/sources-DVHM3Mwq.js +0 -284
  342. package/dist/store-C6hFW6ta.js +0 -508
  343. package/dist/subject-settings-xt7V845g.js +0 -82
  344. package/dist/supabase-hook-DW-xP4hU.js +0 -2
  345. package/dist/types-DbWdEfcm.d.ts +0 -87
  346. package/dist/types-bva3i4Gf.d.ts +0 -98
  347. package/dist/types-i4BAOvdb.d.ts +0 -97
  348. package/dist/usage-PyEor6GA.js +0 -2
  349. package/dist/version-CnSh33Fj.js +0 -16
@@ -1,40 +1,77 @@
1
- import { c as getResource } from "./permissions-DC7GROPA.js";
2
- import { i as USAGE_REPORT_SCHEMA } from "./version-CnSh33Fj.js";
3
- import { o as jsonSchemaOf } from "./catalog-doc-BSo_Q_-6.js";
4
- import { n as listSourceFiles, r as rel } from "./files-B_wAGYmt.js";
5
- import { a as loadModule, n as asPolicy, o as pickNamed } from "./load-BZ24CpZP.js";
6
- import { t as runCollect } from "./collect-O-tOtbnk.js";
7
- import { a as usageResult } from "./errors-DSMnAVNa.js";
8
- import { existsSync, readFileSync } from "node:fs";
9
- import { resolve } from "node:path";
10
- import { parseSync } from "oxc-parser";
1
+ import { c as getResource } from "./permissions-DVoF6dMt.js";
2
+ import { o as usageResult } from "./errors-CWfoNg9N.js";
3
+ import { a as USAGE_REPORT_SCHEMA } from "./version-BvacVTZR.js";
4
+ import { o as jsonSchemaOf } from "./catalog-doc-Dsc9y7sd.js";
5
+ import { i as rel, r as listSourceFiles } from "./files-DWUN9PzI.js";
6
+ import { a as loadModule, n as asPolicy, o as pickNamed } from "./load-DhWEB9P1.js";
7
+ import { r as runCollect } from "./collect-DDDv_ESs.js";
8
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
9
+ import { dirname, resolve } from "node:path";
10
+ import { fileURLToPath, pathToFileURL } from "node:url";
11
+ import { createJiti } from "jiti";
12
+ import { Visitor, parseSync } from "oxc-parser";
13
+ import { isBuiltin } from "node:module";
11
14
  //#region src/cli/doctor-source.ts
15
+ /** Entries a client file must not import; `tests/cli/doctor-entries.test.ts` keeps it in step with `exports`. */
12
16
  const SERVER_SPECIFIERS = [
13
- "permdock/server",
14
- "permdock/next",
15
- "permdock/hono",
16
- "permdock/mcp",
17
+ "permdock/a2a",
18
+ "permdock/ai-sdk",
17
19
  "permdock/approvals",
18
- "permdock/jwt",
19
- "permdock/supabase",
20
- "permdock/ssf",
20
+ "permdock/authzen",
21
21
  "permdock/better-auth",
22
+ "permdock/better-supabase",
23
+ "permdock/claude-agent",
22
24
  "permdock/clerk",
25
+ "permdock/cloud",
23
26
  "permdock/convex",
24
- "permdock/pdp",
25
- "permdock/ai-sdk",
26
- "permdock/claude-agent",
27
+ "permdock/drizzle",
28
+ "permdock/elysia",
27
29
  "permdock/eve",
28
- "permdock/openai"
29
- ];
30
- const ADAPTER_SPECIFIERS = [
30
+ "permdock/express",
31
+ "permdock/fastify",
31
32
  "permdock/hono",
32
- "permdock/next",
33
+ "permdock/jwt",
34
+ "permdock/kysely",
33
35
  "permdock/mcp",
36
+ "permdock/nest",
37
+ "permdock/next",
38
+ "permdock/node",
39
+ "permdock/openai",
40
+ "permdock/openapi",
41
+ "permdock/orpc",
42
+ "permdock/otel",
43
+ "permdock/pdp",
44
+ "permdock/prisma",
45
+ "permdock/scim",
46
+ "permdock/server",
47
+ "permdock/ssf",
48
+ "permdock/supabase",
49
+ "permdock/supabase/middleware",
50
+ "permdock/terminal",
51
+ "permdock/trpc"
52
+ ];
53
+ /** Entries that feed request, tool or model data into a check. */
54
+ const ADAPTER_SPECIFIERS = [
55
+ "permdock/a2a",
34
56
  "permdock/ai-sdk",
57
+ "permdock/authzen",
35
58
  "permdock/claude-agent",
59
+ "permdock/elysia",
60
+ "permdock/eve",
36
61
  "permdock/express",
37
- "permdock/fastify"
62
+ "permdock/fastify",
63
+ "permdock/hono",
64
+ "permdock/mcp",
65
+ "permdock/nest",
66
+ "permdock/next",
67
+ "permdock/node",
68
+ "permdock/openai",
69
+ "permdock/orpc",
70
+ "permdock/server",
71
+ "permdock/supabase/middleware",
72
+ "permdock/terminal",
73
+ "permdock/trpc",
74
+ "permdock/webmcp"
38
75
  ];
39
76
  const UNTRUSTED_CLAIMS = [
40
77
  "user_metadata",
@@ -43,7 +80,6 @@ const UNTRUSTED_CLAIMS = [
43
80
  "clientMetadata",
44
81
  "preferred_username"
45
82
  ];
46
- const JWKS_OPTION = /(?<!\b(?:const|let|var)\s+)\bjwks\s*:/u;
47
83
  function withoutComments(source) {
48
84
  const { comments } = parseSync(source.file, source.text);
49
85
  let text = source.text;
@@ -53,10 +89,62 @@ function withoutComments(source) {
53
89
  function isClientSource(source, clientEntries) {
54
90
  return clientEntries.has(source.file) || source.text.includes("'use client'") || source.text.includes("\"use client\"") || source.file.includes(".client.");
55
91
  }
56
- function pd001(sources, clientEntries = /* @__PURE__ */ new Set()) {
92
+ /** Specifiers a module loads at runtime: value imports, re-exports and literal dynamic imports. */
93
+ function runtimeSpecifiers(source) {
94
+ const { module } = parseSync(source.file, source.text);
95
+ const out = /* @__PURE__ */ new Set();
96
+ for (const item of module.staticImports) if (item.entries.length === 0 || item.entries.some((entry) => !entry.isType)) out.add(item.moduleRequest.value);
97
+ for (const item of module.staticExports) for (const entry of item.entries) if (entry.moduleRequest !== null && !entry.isType) out.add(entry.moduleRequest.value);
98
+ for (const item of module.dynamicImports) {
99
+ const literal = /^\s*(['"`])([^'"`$]+)\1\s*$/u.exec(source.text.slice(item.moduleRequest.start, item.moduleRequest.end));
100
+ if (literal?.[2] !== void 0) out.add(literal[2]);
101
+ }
102
+ return [...out];
103
+ }
104
+ function realFile(path) {
105
+ try {
106
+ return realpathSync(path);
107
+ } catch {
108
+ return path;
109
+ }
110
+ }
111
+ /**
112
+ * A resolver for imports of `file`, the way the bundler resolves them:
113
+ * relative paths with or without an extension, the `paths` of the nearest
114
+ * `tsconfig.json`, and package names through `node_modules` and each
115
+ * package's `exports`. An unresolvable specifier gives `undefined`.
116
+ */
117
+ function resolverFor(file) {
118
+ const jiti = createJiti(file, { tsconfigPaths: dirname(file) });
119
+ const parentURL = pathToFileURL(file);
120
+ return (specifier) => {
121
+ if (specifier === "" || isBuiltin(specifier)) return;
122
+ try {
123
+ const url = jiti.esmResolve(specifier, {
124
+ parentURL,
125
+ try: true
126
+ });
127
+ const path = url?.startsWith("file:") === true ? fileURLToPath(url) : void 0;
128
+ return path !== void 0 && existsSync(path) ? realFile(path) : void 0;
129
+ } catch {
130
+ return;
131
+ }
132
+ };
133
+ }
134
+ function pd001(sources, clientEntries = /* @__PURE__ */ new Set(), policy) {
57
135
  const findings = [];
136
+ const policyFile = policy === void 0 ? void 0 : realFile(resolve(policy.cwd, policy.path));
58
137
  for (const source of sources) {
59
138
  if (!isClientSource(source, clientEntries)) continue;
139
+ if (policy !== void 0 && policyFile !== void 0) {
140
+ const resolveImport = resolverFor(resolve(policy.cwd, source.file));
141
+ for (const specifier of runtimeSpecifiers(source)) if (specifier !== "permdock" && !specifier.startsWith("permdock/") && resolveImport(specifier) === policyFile) findings.push({
142
+ code: "PD001",
143
+ severity: "error",
144
+ message: `${source.file} imports the policy module through ${specifier}`,
145
+ fix: "decide on the server and pass a snapshot to the client ('permdock/react'); never import the policy into a client entry"
146
+ });
147
+ }
60
148
  for (const spec of SERVER_SPECIFIERS) if (source.text.includes(`'${spec}'`) || source.text.includes(`"${spec}"`)) findings.push({
61
149
  code: "PD001",
62
150
  severity: "error",
@@ -137,29 +225,92 @@ function pd013(sources) {
137
225
  }
138
226
  return findings;
139
227
  }
228
+ function unwrapped(node) {
229
+ let current = node ?? void 0;
230
+ while (current?.type === "TSAsExpression" || current?.type === "TSSatisfiesExpression" || current?.type === "ParenthesizedExpression") current = current.expression;
231
+ return current;
232
+ }
233
+ function propertyName(property) {
234
+ if (property.computed) return;
235
+ const key = property.key;
236
+ if (key.type === "Identifier") return key.name;
237
+ return key.type === "Literal" && typeof key.value === "string" ? key.value : void 0;
238
+ }
239
+ function stringValue(node) {
240
+ const value = unwrapped(node);
241
+ if (value?.type === "Literal") return typeof value.value === "string" ? value.value : void 0;
242
+ return value?.type === "TemplateLiteral" ? value.quasis[0]?.value.cooked ?? void 0 : void 0;
243
+ }
244
+ function isPermDockSpecifier(value) {
245
+ return value === "permdock" || value.startsWith("permdock/");
246
+ }
247
+ function permdockOptionObjects(source) {
248
+ const { program } = parseSync(source.file, source.text);
249
+ const functions = /* @__PURE__ */ new Set();
250
+ const namespaces = /* @__PURE__ */ new Set();
251
+ const constants = /* @__PURE__ */ new Map();
252
+ const calls = [];
253
+ new Visitor({
254
+ ImportDeclaration(node) {
255
+ if (node.importKind === "type" || !isPermDockSpecifier(node.source.value)) return;
256
+ for (const specifier of node.specifiers) if (specifier.type === "ImportNamespaceSpecifier") namespaces.add(specifier.local.name);
257
+ else if (specifier.type === "ImportDefaultSpecifier" || specifier.importKind !== "type") functions.add(specifier.local.name);
258
+ },
259
+ VariableDeclarator(node) {
260
+ const init = unwrapped(node.init);
261
+ if (node.id.type === "Identifier" && init?.type === "ObjectExpression") constants.set(node.id.name, init);
262
+ },
263
+ CallExpression(node) {
264
+ calls.push(node);
265
+ }
266
+ }).visit(program);
267
+ const objects = [];
268
+ const collect = (node) => {
269
+ const value = unwrapped(node);
270
+ const target = value?.type === "Identifier" ? constants.get(value.name) : value;
271
+ if (target?.type !== "ObjectExpression" || objects.includes(target)) return;
272
+ objects.push(target);
273
+ for (const property of target.properties) if (property.type === "Property") collect(property.value);
274
+ };
275
+ for (const call of calls) {
276
+ const callee = call.callee;
277
+ if (callee.type === "Identifier" && functions.has(callee.name) || callee.type === "MemberExpression" && callee.object.type === "Identifier" && namespaces.has(callee.object.name)) for (const argument of call.arguments) collect(argument);
278
+ }
279
+ return objects;
280
+ }
140
281
  function pd014(sources) {
141
282
  const findings = [];
142
283
  for (const source of sources) {
143
- const text = withoutComments(source);
144
- if (/discovery:\s*['"]http:/u.test(text)) findings.push({
145
- code: "PD014",
146
- severity: "error",
147
- message: `${source.file} uses a plain-HTTP discovery URL`,
148
- fix: "use an https: issuer"
149
- });
150
- const setsJwks = JWKS_OPTION.test(text);
151
- if (/discovery\s*:/u.test(text) && setsJwks) findings.push({
152
- code: "PD014",
153
- severity: "error",
154
- message: `${source.file} sets discovery together with jwks or issuer`,
155
- fix: "use discovery alone, or jwks plus issuer"
156
- });
157
- if (setsJwks && !/\bissuer\s*[:,}]/u.test(text) && !/discovery\s*:/u.test(text)) findings.push({
158
- code: "PD014",
159
- severity: "error",
160
- message: `${source.file} sets jwks without issuer`,
161
- fix: "set issuer with jwks, or switch to discovery"
162
- });
284
+ if (!source.text.includes("permdock")) continue;
285
+ for (const object of permdockOptionObjects(source)) {
286
+ const keys = /* @__PURE__ */ new Map();
287
+ for (const property of object.properties) {
288
+ if (property.type !== "Property") continue;
289
+ const name = propertyName(property);
290
+ if (name !== void 0) keys.set(name, property.value);
291
+ }
292
+ const discovery = keys.get("discovery");
293
+ const setsDiscovery = keys.has("discovery");
294
+ const setsJwks = keys.has("jwks");
295
+ if (stringValue(discovery)?.startsWith("http:") === true) findings.push({
296
+ code: "PD014",
297
+ severity: "error",
298
+ message: `${source.file} uses a plain-HTTP discovery URL`,
299
+ fix: "use an https: issuer"
300
+ });
301
+ if (setsDiscovery && (setsJwks || keys.has("issuer"))) findings.push({
302
+ code: "PD014",
303
+ severity: "error",
304
+ message: `${source.file} sets discovery together with jwks or issuer`,
305
+ fix: "use discovery alone, or jwks plus issuer"
306
+ });
307
+ if (setsJwks && !setsDiscovery && !keys.has("issuer")) findings.push({
308
+ code: "PD014",
309
+ severity: "error",
310
+ message: `${source.file} sets jwks without issuer`,
311
+ fix: "set issuer with jwks, or switch to discovery"
312
+ });
313
+ }
163
314
  }
164
315
  return findings;
165
316
  }
@@ -288,7 +439,7 @@ function pd036(sources) {
288
439
  for (const match of source.text.matchAll(PROTECT_CALL)) {
289
440
  const open = match.index + match[0].length - 1;
290
441
  const args = callArguments(source.text, open);
291
- if (args?.length !== 1) continue;
442
+ if (args?.length !== 1 || args[0]?.trim() === "null") continue;
292
443
  const route = idRouteOf(source, match.index);
293
444
  if (route === void 0) continue;
294
445
  const line = source.text.slice(0, match.index).split("\n").length;
@@ -305,14 +456,14 @@ function pd036(sources) {
305
456
  //#endregion
306
457
  //#region src/cli/usage.ts
307
458
  async function runUsage(input) {
308
- const collected = await runCollect({
459
+ const collected = input.collected === void 0 ? await runCollect({
309
460
  cwd: input.cwd,
310
461
  config: input.config,
311
462
  collect: input.config.collect ?? {},
312
463
  check: true,
313
464
  now: input.now,
314
465
  io: input.io
315
- });
466
+ }) : await input.collected();
316
467
  if (collected.document === void 0 || collected.scan === void 0) return {
317
468
  code: 2,
318
469
  output: collected.message
@@ -322,17 +473,8 @@ async function runUsage(input) {
322
473
  code: 2,
323
474
  output: "usage: set policy in permdock.config.ts"
324
475
  };
325
- const policyAbs = resolve(input.cwd, policyRel);
326
- if (!existsSync(policyAbs)) return {
327
- code: 2,
328
- output: `PermDock CLI: policy module not found: ${policyRel}`
329
- };
330
- let policy;
331
- try {
332
- policy = asPolicy(pickNamed(await loadModule(policyAbs), ["policy"]));
333
- } catch (error) {
334
- return usageResult(error);
335
- }
476
+ const policy = await usagePolicy(input.cwd, policyRel, input.policy);
477
+ if (!("roles" in policy)) return policy;
336
478
  const granted = /* @__PURE__ */ new Set();
337
479
  const mergedRoles = /* @__PURE__ */ new Set();
338
480
  for (const role of policy.roles) {
@@ -395,6 +537,22 @@ async function runUsage(input) {
395
537
  output: input.json ? `${JSON.stringify(report, null, 2)}\n` : formatUsage(report)
396
538
  };
397
539
  }
540
+ async function usagePolicy(cwd, policyRel, loaded) {
541
+ if (loaded !== void 0) return await loaded() ?? {
542
+ code: 2,
543
+ output: `PermDock CLI: policy module failed to load: ${policyRel}`
544
+ };
545
+ const policyAbs = resolve(cwd, policyRel);
546
+ if (!existsSync(policyAbs)) return {
547
+ code: 2,
548
+ output: `PermDock CLI: policy module not found: ${policyRel}`
549
+ };
550
+ try {
551
+ return asPolicy(pickNamed(await loadModule(policyAbs), ["policy"]));
552
+ } catch (error) {
553
+ return usageResult(error);
554
+ }
555
+ }
398
556
  const CLIENT_CALLS = /* @__PURE__ */ new Set([
399
557
  "usePermission",
400
558
  "can",
@@ -462,8 +620,13 @@ function conditionFields(condition, out) {
462
620
  case "related":
463
621
  add(condition.field);
464
622
  if (condition.restricted !== void 0) add(condition.restricted);
623
+ if (condition.restrictedAncestors !== void 0) {
624
+ add(condition.restrictedAncestors.id);
625
+ add(condition.restrictedAncestors.parent);
626
+ }
465
627
  break;
466
- case "opaque": break;
628
+ case "opaque":
629
+ case "liveSession": break;
467
630
  default: throw new Error(`unknown condition ${String(condition)}`);
468
631
  }
469
632
  }
@@ -0,0 +1,33 @@
1
+ import { t as compact } from "./compact-y6vfu2_f.js";
2
+ //#region src/core/validation-error.ts
3
+ /** The base of every Problem Details `type` URI; defined here so a validation error does not pull in the Problem Details builders. */
4
+ const PROBLEM_BASE = "https://permdock.com/problems";
5
+ var PermDockValidationError = class extends Error {
6
+ name = "PermDockValidationError";
7
+ code;
8
+ permission;
9
+ resource;
10
+ issues;
11
+ boundary;
12
+ constructor(input) {
13
+ super(input.message);
14
+ this.code = input.code;
15
+ this.permission = input.permission;
16
+ this.resource = input.resource;
17
+ this.issues = input.issues ?? [];
18
+ this.boundary = input.boundary;
19
+ }
20
+ toProblemDetails(options) {
21
+ return compact({
22
+ type: `${PROBLEM_BASE}/validation`,
23
+ title: "Invalid resource data",
24
+ status: 400,
25
+ detail: this.message,
26
+ instance: options?.instance,
27
+ permission: this.permission,
28
+ issues: this.issues
29
+ });
30
+ }
31
+ };
32
+ //#endregion
33
+ export { PermDockValidationError as n, PROBLEM_BASE as t };
@@ -0,0 +1,26 @@
1
+ import { a as ProblemDetails } from "./errors-DAqevpNk.js";
2
+ import { StandardSchemaV1 } from "@standard-schema/spec";
3
+ //#region src/core/validation-error.d.ts
4
+ /** The base of every Problem Details `type` URI; defined here so a validation error does not pull in the Problem Details builders. */
5
+ declare const PROBLEM_BASE = "https://permdock.com/problems";
6
+ declare class PermDockValidationError extends Error {
7
+ override readonly name: "PermDockValidationError";
8
+ readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
9
+ readonly permission: string;
10
+ readonly resource: string;
11
+ readonly issues: readonly StandardSchemaV1.Issue[];
12
+ readonly boundary: string;
13
+ constructor(input: {
14
+ readonly code: "invalid-data" | "async-schema" | "no-schema" | "non-portable-condition";
15
+ readonly permission: string;
16
+ readonly resource: string;
17
+ readonly issues?: readonly StandardSchemaV1.Issue[];
18
+ readonly boundary: string;
19
+ readonly message: string;
20
+ });
21
+ toProblemDetails(options?: {
22
+ readonly instance?: string;
23
+ }): ProblemDetails;
24
+ }
25
+ //#endregion
26
+ export { PermDockValidationError as n, PROBLEM_BASE as t };
@@ -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 };