permdock 0.0.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 (344) hide show
  1. package/README.md +327 -1
  2. package/dist/a2a/index.d.ts +169 -0
  3. package/dist/a2a/index.js +232 -0
  4. package/dist/adapter-context-mlWsVGGg.js +23 -0
  5. package/dist/ai-sdk/index.d.ts +95 -0
  6. package/dist/ai-sdk/index.js +154 -0
  7. package/dist/approval-required-TzNB9oQA.js +6 -0
  8. package/dist/approvals/index.d.ts +3 -0
  9. package/dist/approvals/index.js +5 -0
  10. package/dist/approvals-DbYAuNkG.js +224 -0
  11. package/dist/approvers-DT4AVyIg.js +52 -0
  12. package/dist/arazzo-BAgw9ap6.js +70 -0
  13. package/dist/arazzo-cmvX2jDe.js +54 -0
  14. package/dist/authzen/index.d.ts +39 -0
  15. package/dist/authzen/index.js +302 -0
  16. package/dist/better-auth/index.d.ts +109 -0
  17. package/dist/better-auth/index.js +344 -0
  18. package/dist/better-supabase/index.d.ts +206 -0
  19. package/dist/better-supabase/index.js +620 -0
  20. package/dist/bind-CVy3Espv.d.ts +25 -0
  21. package/dist/bind-VnYn2HKq.js +97 -0
  22. package/dist/boundary-BM8a_P6E.js +13 -0
  23. package/dist/boundary-BmHxVH1J.d.ts +15 -0
  24. package/dist/budget-JqcRqyhK.d.ts +11 -0
  25. package/dist/budget-NbEtbJC_.js +11 -0
  26. package/dist/canonical-json-DemiK4Vp.js +26 -0
  27. package/dist/capability-4qPdO9gk.js +173 -0
  28. package/dist/capability-Dq43tT1u.d.ts +99 -0
  29. package/dist/catalog/index.d.ts +12 -0
  30. package/dist/catalog/index.js +2 -0
  31. package/dist/catalog-BjZSovXQ.js +2 -0
  32. package/dist/catalog-doc-Dsc9y7sd.js +309 -0
  33. package/dist/catalog-h2tlKFkq.js +48 -0
  34. package/dist/catalog-path-CnI0XTFK.js +12 -0
  35. package/dist/catalog-z8q6bi_r.js +55 -0
  36. package/dist/claude-agent/index.d.ts +72 -0
  37. package/dist/claude-agent/index.js +77 -0
  38. package/dist/clerk/index.d.ts +65 -0
  39. package/dist/clerk/index.js +301 -0
  40. package/dist/cli/bin.d.ts +1 -0
  41. package/dist/cli/bin.js +20 -0
  42. package/dist/cli/index.d.ts +46 -0
  43. package/dist/cli/index.js +5 -0
  44. package/dist/clients-C7zLFuWT.d.ts +12 -0
  45. package/dist/clients-DjU5ABMy.js +23 -0
  46. package/dist/cloud/index.d.ts +90 -0
  47. package/dist/cloud/index.js +404 -0
  48. package/dist/cloud-BGhHS-lY.js +50 -0
  49. package/dist/cloud-Bo3e9Ak3.js +118 -0
  50. package/dist/collect-DDDv_ESs.js +502 -0
  51. package/dist/collect-DLlujdHC.js +83 -0
  52. package/dist/collect-rG2IQ3t0.js +2 -0
  53. package/dist/commands-DWOrSQic.js +97 -0
  54. package/dist/compact-y6vfu2_f.js +19 -0
  55. package/dist/compare-pfyVnBjE.js +12 -0
  56. package/dist/compile/index.d.ts +3 -0
  57. package/dist/compile/index.js +2 -0
  58. package/dist/compile-Ba4blROR.js +613 -0
  59. package/dist/compile-CNnl6uIt.d.ts +94 -0
  60. package/dist/config-BJiM-xAm.js +157 -0
  61. package/dist/config-Bn00Z3ks.js +36 -0
  62. package/dist/config-report-Dw_JcUqT.js +44 -0
  63. package/dist/connection-CU8MQxRi.js +194 -0
  64. package/dist/context-Ttp0ekMT.js +82 -0
  65. package/dist/convex/index.d.ts +45 -0
  66. package/dist/convex/index.js +65 -0
  67. package/dist/create-BWyx3jua.d.ts +245 -0
  68. package/dist/create-CPhDL6qx.js +253 -0
  69. package/dist/credential-8P81ff4u.js +306 -0
  70. package/dist/delegation-D8pUEuce.js +103 -0
  71. package/dist/describe-B_gVZEVi.js +94 -0
  72. package/dist/describe-PdoqESvg.d.ts +36 -0
  73. package/dist/diff-B8Tunc3o.js +451 -0
  74. package/dist/diff-CzqLxZ77.js +48 -0
  75. package/dist/digest-B3kc_PgQ.d.ts +19 -0
  76. package/dist/digest-BI-6aa6d.js +27 -0
  77. package/dist/doctor-WpvG6p4k.js +1194 -0
  78. package/dist/doctor-collect-ByfYlNv1.js +664 -0
  79. package/dist/doctor-rOr-4ZfS.js +53 -0
  80. package/dist/drizzle/index.d.ts +73 -0
  81. package/dist/drizzle/index.js +160 -0
  82. package/dist/duration-xK2jGFVc.js +25 -0
  83. package/dist/elysia/index.d.ts +49 -0
  84. package/dist/elysia/index.js +59 -0
  85. package/dist/errors-CWfoNg9N.js +47 -0
  86. package/dist/errors-Cz5zn0mW.js +123 -0
  87. package/dist/errors-DAqevpNk.d.ts +125 -0
  88. package/dist/errors-DRnGZHzF.js +30 -0
  89. package/dist/evaluation-items-CfCCejQd.js +40 -0
  90. package/dist/evaluations-tz6D9A2G.js +461 -0
  91. package/dist/eve/index.d.ts +86 -0
  92. package/dist/eve/index.js +176 -0
  93. package/dist/expiry-BoBJ8Tvc.js +7 -0
  94. package/dist/express/index.d.ts +23 -0
  95. package/dist/express/index.js +78 -0
  96. package/dist/fastify/index.d.ts +33 -0
  97. package/dist/fastify/index.js +92 -0
  98. package/dist/fields-BMl1RxoX.js +26 -0
  99. package/dist/files-DWUN9PzI.js +125 -0
  100. package/dist/fixtures-ht28Cplr.js +67 -0
  101. package/dist/freeze-CrU8nQeX.js +60 -0
  102. package/dist/from-snapshot-C3sHpZNS.js +569 -0
  103. package/dist/generate-CH7ThJ14.js +173 -0
  104. package/dist/grantee-Cv5Sogfv.js +602 -0
  105. package/dist/graph-sql-B-dsAT6j.d.ts +29 -0
  106. package/dist/headers-BZSDieNT.js +6 -0
  107. package/dist/headers-Cf-zWvsO.d.ts +6 -0
  108. package/dist/helpers-H_KARDVC.js +421 -0
  109. package/dist/hono/index.d.ts +48 -0
  110. package/dist/hono/index.js +99 -0
  111. package/dist/hosted-DJQw46hn.js +266 -0
  112. package/dist/http-BIhmLfCc.js +95 -0
  113. package/dist/http-DPuDaChb.d.ts +13 -0
  114. package/dist/http-SO7qGttf.js +44 -0
  115. package/dist/ids-DC4V4CFu.js +18 -0
  116. package/dist/index-A0YNL8jZ.d.ts +177 -0
  117. package/dist/index-CtE07CBF.d.ts +6 -0
  118. package/dist/index-D3vbkoSI.d.ts +483 -0
  119. package/dist/index-D6_cSa1z.d.ts +201 -0
  120. package/dist/index.d.ts +16 -0
  121. package/dist/index.js +26 -0
  122. package/dist/instance-options-BK_rNOSC.d.ts +11 -0
  123. package/dist/instance-options-Dhhcnm3y.js +22 -0
  124. package/dist/json-schema-BsAflUGW.js +106 -0
  125. package/dist/jwt/index.d.ts +91 -0
  126. package/dist/jwt/index.js +590 -0
  127. package/dist/kernel-GSQnMz3O.js +208 -0
  128. package/dist/kysely/index.d.ts +78 -0
  129. package/dist/kysely/index.js +129 -0
  130. package/dist/live-options-H2eG8dfJ.js +60 -0
  131. package/dist/load-DhWEB9P1.js +75 -0
  132. package/dist/load-DwJUafYN.js +2 -0
  133. package/dist/load-jose-BL6LH4bL.js +11 -0
  134. package/dist/lru-8q4WZjBV.js +28 -0
  135. package/dist/manifest-iaoBXHKc.js +783 -0
  136. package/dist/manifest-uDS9y5de.d.ts +206 -0
  137. package/dist/map-AcxK9o_D.js +147 -0
  138. package/dist/map-claims-Z4QZOiFF.js +369 -0
  139. package/dist/map-error-pgUWNNtG.js +23 -0
  140. package/dist/markers-B0hYLvMD.js +60 -0
  141. package/dist/may-use-DndQ5tQ-.js +77 -0
  142. package/dist/mcp/index.d.ts +159 -0
  143. package/dist/mcp/index.js +603 -0
  144. package/dist/nest/index.d.ts +75 -0
  145. package/dist/nest/index.js +261 -0
  146. package/dist/next/client.d.ts +23 -0
  147. package/dist/next/client.js +33 -0
  148. package/dist/next/index.d.ts +93 -0
  149. package/dist/next/index.js +180 -0
  150. package/dist/next/plugin.d.ts +14 -0
  151. package/dist/next/plugin.js +33 -0
  152. package/dist/node/index.d.ts +24 -0
  153. package/dist/node/index.js +34 -0
  154. package/dist/openai/index.d.ts +62 -0
  155. package/dist/openai/index.js +92 -0
  156. package/dist/openapi/index.d.ts +176 -0
  157. package/dist/openapi/index.js +3 -0
  158. package/dist/openapi-Bbg4wGVL.js +164 -0
  159. package/dist/openapi-BqRBvAng.js +538 -0
  160. package/dist/openapi-CqqEbHsL.js +250 -0
  161. package/dist/openapi-import-cmwetbzw.js +5959 -0
  162. package/dist/openapi-schema--ARjyfQr.js +6902 -0
  163. package/dist/orpc/index.d.ts +51 -0
  164. package/dist/orpc/index.js +145 -0
  165. package/dist/otel/index.d.ts +13 -0
  166. package/dist/otel/index.js +202 -0
  167. package/dist/package-root-zGkxO3oN.js +30 -0
  168. package/dist/parse-BuyjxhZV.js +53 -0
  169. package/dist/parse-local-manifest-BkGQNzAh.d.ts +10 -0
  170. package/dist/parse-local-manifest-BrMozJCo.js +36 -0
  171. package/dist/pdp/index.d.ts +22 -0
  172. package/dist/pdp/index.js +682 -0
  173. package/dist/peer-BOr_kJE1.js +31 -0
  174. package/dist/permdock-CzqXjCpU.js +3471 -0
  175. package/dist/permissions-CDgvKG5L.d.ts +52 -0
  176. package/dist/permissions-CpZrivYv.js +142 -0
  177. package/dist/permissions-DVoF6dMt.js +662 -0
  178. package/dist/permissions-DttnqqxC.d.ts +214 -0
  179. package/dist/pins-8ILTftC9.js +12 -0
  180. package/dist/policy-CFZAr_Al.d.ts +2252 -0
  181. package/dist/policy-D8UFyERw.d.ts +20 -0
  182. package/dist/policy-xyWg7QdR.js +1122 -0
  183. package/dist/powersync-A8x_Yyvh.js +2 -0
  184. package/dist/powersync-C7kLglqX.js +540 -0
  185. package/dist/powersync-yW1UUFzp.js +62 -0
  186. package/dist/prisma/index.d.ts +136 -0
  187. package/dist/prisma/index.js +455 -0
  188. package/dist/problem-B43ztKIm.js +191 -0
  189. package/dist/problem-details-CkL50EEf.d.ts +7 -0
  190. package/dist/problem-details-_AMOYz-w.js +144 -0
  191. package/dist/prompt-CXYhLfsS.js +32 -0
  192. package/dist/protected-CNsMzrVd.d.ts +27 -0
  193. package/dist/protected-Cs6kTaHo.js +100 -0
  194. package/dist/protected-bZs6rbT1.d.ts +40 -0
  195. package/dist/provider-Cjr62YMV.d.ts +6 -0
  196. package/dist/provider-DLzpb2Xz.js +52 -0
  197. package/dist/provider-store-DNyC1y48.js +43 -0
  198. package/dist/react/index.d.ts +8 -0
  199. package/dist/react/index.js +7 -0
  200. package/dist/react/provider-client.d.ts +2 -0
  201. package/dist/react/provider-client.js +3 -0
  202. package/dist/react-native/index.d.ts +198 -0
  203. package/dist/react-native/index.js +696 -0
  204. package/dist/refs-KYb4ntaz.js +91 -0
  205. package/dist/relations-cjOL01hZ.js +505 -0
  206. package/dist/replay-BsOyTrdV.js +28 -0
  207. package/dist/replay-sqBGMnNs.d.ts +5 -0
  208. package/dist/resource-ref-CaS9yVPi.js +20 -0
  209. package/dist/revocations-Bhr0aMIC.js +27 -0
  210. package/dist/revocations-Cy06JNx2.d.ts +21 -0
  211. package/dist/rls-BMNydpHk.js +2521 -0
  212. package/dist/rls-CEvs64Kj.js +238 -0
  213. package/dist/rls-fields-BMasREhR.js +3502 -0
  214. package/dist/rls-graph-pc9fuXYm.js +435 -0
  215. package/dist/rls-import-D8F7j35Q.js +943 -0
  216. package/dist/rls-migrate-7wikfrVI.js +367 -0
  217. package/dist/rls-ownership-B5Lkq62W.js +843 -0
  218. package/dist/rls-shared-aOQ4hGTO.js +493 -0
  219. package/dist/rls-verify-D8B7dOTh.js +745 -0
  220. package/dist/row-check-Dt35czLy.d.ts +40 -0
  221. package/dist/rpc-DOK54_CS.js +89 -0
  222. package/dist/run-YXCJDNYk.js +174 -0
  223. package/dist/runtime-CB8gQFvS.js +11 -0
  224. package/dist/saas-Bj_FFkjN.js +1203 -0
  225. package/dist/schema-D3MnDMxa.js +300 -0
  226. package/dist/scim/index.d.ts +2 -0
  227. package/dist/scim/index.js +2 -0
  228. package/dist/scim-BFGBBAqR.js +1445 -0
  229. package/dist/scopes-CVdPrWN-.js +239 -0
  230. package/dist/server/index.d.ts +134 -0
  231. package/dist/server/index.js +11 -0
  232. package/dist/server-DlZ28Oz5.js +268 -0
  233. package/dist/sha256-BO0swRXL.js +150 -0
  234. package/dist/shared-DRu8VFVM.js +123 -0
  235. package/dist/sink-Bd9PSyfq.js +141 -0
  236. package/dist/sink-Gs6TTVa-.d.ts +104 -0
  237. package/dist/skills-Biq5uup3.js +192 -0
  238. package/dist/skills-JaymNCdK.js +56 -0
  239. package/dist/snapshot-Enxd0n-s.js +975 -0
  240. package/dist/snapshot-cache-D6jLelln.js +44 -0
  241. package/dist/snapshot-cache-DwQH8ufx.d.ts +45 -0
  242. package/dist/solid/index.d.ts +93 -0
  243. package/dist/solid/index.js +188 -0
  244. package/dist/sources-B0UvrJ21.js +534 -0
  245. package/dist/sources-BcJgw0lt.d.ts +192 -0
  246. package/dist/sql-xdg5f4Fi.js +27 -0
  247. package/dist/src-CSbUiozF.js +568 -0
  248. package/dist/ssf/index.d.ts +4 -0
  249. package/dist/ssf/index.js +596 -0
  250. package/dist/store-DMAWwAJV.js +371 -0
  251. package/dist/store-D_pjn91-.d.ts +36 -0
  252. package/dist/store-options-yO0V6gRn.js +716 -0
  253. package/dist/stores-4_sqiOA1.js +87 -0
  254. package/dist/stores-DVR5NHLE.d.ts +52 -0
  255. package/dist/stream-DDpvynSB.js +66 -0
  256. package/dist/stream-DlvG2hs-.d.ts +12 -0
  257. package/dist/style-CTm1AXDT.js +22 -0
  258. package/dist/subject-C6dLxqHU.js +24 -0
  259. package/dist/subject-settings-BwBmCdTR.js +128 -0
  260. package/dist/supabase/index.d.ts +183 -0
  261. package/dist/supabase/index.js +5 -0
  262. package/dist/supabase/middleware.d.ts +82 -0
  263. package/dist/supabase/middleware.js +102 -0
  264. package/dist/supabase-CwafwxxF.js +83 -0
  265. package/dist/supabase-DTBaC20O.js +774 -0
  266. package/dist/supabase-config-Bs44dare.js +472 -0
  267. package/dist/supabase-hook-BuxLQLpU.js +1814 -0
  268. package/dist/supabase-hook-D5qVd_D8.js +2 -0
  269. package/dist/supautils-DYZnzRWV.js +91 -0
  270. package/dist/svelte/PermissionBoundary.svelte +37 -0
  271. package/dist/svelte/Protected.svelte +40 -0
  272. package/dist/svelte/index.d.ts +13 -0
  273. package/dist/svelte/index.js +107 -0
  274. package/dist/svelte/runtime.d.ts +7 -0
  275. package/dist/svelte/runtime.js +4 -0
  276. package/dist/svelte/source.d.ts +13 -0
  277. package/dist/svelte/source.js +11 -0
  278. package/dist/terminal/index.d.ts +163 -0
  279. package/dist/terminal/index.js +833 -0
  280. package/dist/testing/index.d.ts +745 -0
  281. package/dist/testing/index.js +3672 -0
  282. package/dist/testing/saas/index.d.ts +194 -0
  283. package/dist/testing/saas/index.js +3 -0
  284. package/dist/testing/saas/permissions.d.ts +2 -0
  285. package/dist/testing/saas/permissions.js +2 -0
  286. package/dist/text-diff-BdkkYSbi.js +15 -0
  287. package/dist/thenable-okc2xDsj.js +10 -0
  288. package/dist/timeout-D51niuQP.js +8 -0
  289. package/dist/token-CIWxJOCh.js +50 -0
  290. package/dist/trpc/index.d.ts +61 -0
  291. package/dist/trpc/index.js +122 -0
  292. package/dist/types-9AWO9EGt.d.ts +197 -0
  293. package/dist/types-BPxgszlT.d.ts +550 -0
  294. package/dist/types-BVyImy5I.d.ts +120 -0
  295. package/dist/types-Bvc4oWT6.d.ts +9 -0
  296. package/dist/types-C3s9xVJG.d.ts +48 -0
  297. package/dist/types-Dnemwd77.d.ts +183 -0
  298. package/dist/types-kxznc7cn.d.ts +52 -0
  299. package/dist/types-vKyAMtcX.d.ts +157 -0
  300. package/dist/types-vNSDF7Dq.d.ts +66 -0
  301. package/dist/types-yF5LmQVD.d.ts +306 -0
  302. package/dist/unplugin/index.d.ts +7 -0
  303. package/dist/unplugin/index.js +31 -0
  304. package/dist/usage-D07N9QJ3.js +42 -0
  305. package/dist/usage-D82l1CwK.js +2 -0
  306. package/dist/usage-DG1oeCca.js +693 -0
  307. package/dist/validation-error-CnjZ4t92.js +33 -0
  308. package/dist/validation-error-CtF23SrC.d.ts +26 -0
  309. package/dist/validity-uOp8UpYn.js +245 -0
  310. package/dist/verifier-BxBo6I44.js +466 -0
  311. package/dist/version-BvacVTZR.js +17 -0
  312. package/dist/views-Soe7bGSC.js +95 -0
  313. package/dist/vocabulary-DA8a8zif.d.ts +56 -0
  314. package/dist/vue/index.d.ts +79 -0
  315. package/dist/vue/index.js +196 -0
  316. package/dist/watch-Etoa_Mvr.js +2 -0
  317. package/dist/watch-UihESpsJ.js +128 -0
  318. package/dist/webmcp/index.d.ts +75 -0
  319. package/dist/webmcp/index.js +307 -0
  320. package/package.json +450 -5
  321. package/rulesets/permdock.yaml +29 -0
  322. package/schemas/approval-request-v1.json +175 -0
  323. package/schemas/catalog-v1.json +535 -0
  324. package/schemas/openapi/oas-3.1.json +1298 -0
  325. package/schemas/openapi/oas-3.2.json +1516 -0
  326. package/schemas/openapi/overlay-1.1.json +79 -0
  327. package/schemas/supabase-claims-v1.json +144 -0
  328. package/schemas/supabase-manifest-v1.json +361 -0
  329. package/skills/permdock/SKILL.md +66 -0
  330. package/skills/permdock-agents/SKILL.md +77 -0
  331. package/skills/permdock-agents/references/runtimes.md +213 -0
  332. package/skills/permdock-approvals/SKILL.md +80 -0
  333. package/skills/permdock-approvals/references/stores-and-resume.md +94 -0
  334. package/skills/permdock-audit/SKILL.md +67 -0
  335. package/skills/permdock-credentials/SKILL.md +55 -0
  336. package/skills/permdock-credentials/references/tokens-keys-links.md +132 -0
  337. package/skills/permdock-data/SKILL.md +57 -0
  338. package/skills/permdock-data/references/queries-and-rls.md +62 -0
  339. package/skills/permdock-data/references/relationships.md +67 -0
  340. package/skills/permdock-tenancy/SKILL.md +80 -0
  341. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +89 -0
  342. package/skills/permdock-wire/SKILL.md +116 -0
  343. package/skills/permdock-wire/references/adapters.md +492 -0
  344. package/skills/permdock-wire/references/policy-options.md +45 -0
@@ -0,0 +1,620 @@
1
+ import { n as freezeDeep } from "../freeze-CrU8nQeX.js";
2
+ import { _ as listPermissions, p as isPermission } from "../permissions-DVoF6dMt.js";
3
+ import { t as anonymousSubject } from "../subject-C6dLxqHU.js";
4
+ import { t as mayUse } from "../may-use-DndQ5tQ-.js";
5
+ import { o as parseCredential, r as credentialSubject } from "../credential-8P81ff4u.js";
6
+ import { i as quoteSqlLiteral, o as sqlIdent } from "../sql-xdg5f4Fi.js";
7
+ import { o as subjectFromSupabaseSession, t as parseSupabaseManifest } from "../manifest-iaoBXHKc.js";
8
+ import { t as parseCatalog } from "../parse-BuyjxhZV.js";
9
+ import { AsyncResult, dbError } from "better-supabase";
10
+ //#region src/better-supabase/provider.ts
11
+ /**
12
+ * The helper each template calls (with `{scope}` unfilled), its default
13
+ * argument types and the role that calls it: `postgres` for the templates
14
+ * better-supabase runs inside its own `security definer` functions.
15
+ */
16
+ const TEMPLATES = {
17
+ idsWith: {
18
+ helper: "permitted_{scope}_ids_by_permission",
19
+ listedAs: "permitted_{scope}_ids",
20
+ args: "text",
21
+ role: "authenticated",
22
+ sql: "permitted_{scope}_ids_by_permission({permission})"
23
+ },
24
+ isPlatform: {
25
+ helper: "permdock_has_permission",
26
+ listedAs: "permdock_has",
27
+ args: "text",
28
+ role: "authenticated",
29
+ sql: "permdock_has_permission({permission})"
30
+ },
31
+ idsWithFor: {
32
+ helper: "permitted_{scope}_ids_by_permission_for",
33
+ listedAs: "permitted_{scope}_ids_for",
34
+ args: "uuid, text",
35
+ role: "postgres",
36
+ sql: "permitted_{scope}_ids_by_permission_for({user}, {permission})"
37
+ },
38
+ isPlatformFor: {
39
+ helper: "permdock_has_permission_for",
40
+ listedAs: "permdock_has_for",
41
+ args: "uuid, text",
42
+ role: "postgres",
43
+ sql: "permdock_has_permission_for({user}, {permission})"
44
+ },
45
+ memberIds: {
46
+ helper: "member_{scope}_ids",
47
+ args: "",
48
+ role: "authenticated",
49
+ sql: "member_{scope}_ids()"
50
+ },
51
+ memberIdsFor: {
52
+ helper: "member_{scope}_ids_for",
53
+ args: "uuid",
54
+ role: "supabase_auth_admin",
55
+ sql: "member_{scope}_ids_for({user})"
56
+ },
57
+ canAssign: {
58
+ helper: "permdock_can_assign",
59
+ args: "text, text",
60
+ role: "authenticated",
61
+ sql: "permdock_can_assign({role}, {tenant}::text)"
62
+ },
63
+ canAssignFor: {
64
+ helper: "permdock_can_assign_for",
65
+ args: "uuid, text, text",
66
+ role: "postgres",
67
+ sql: "permdock_can_assign_for({user}, {role}, {tenant}::text)"
68
+ },
69
+ permissionsFor: {
70
+ helper: "permitted_{scope}_permission_keys_for",
71
+ args: "uuid, uuid",
72
+ role: "postgres",
73
+ sql: "array(select {schema}.permitted_{scope}_permission_keys_for({user}, {tenant}))"
74
+ }
75
+ };
76
+ const ASSIGN_ANY = {
77
+ canAssign: {
78
+ helper: "permdock_can_assign_any",
79
+ args: "text, uuid, text, text",
80
+ role: "authenticated",
81
+ sql: "permdock_can_assign_any({role}, {tenant}, '{scope}', {tenant}::text)"
82
+ },
83
+ canAssignFor: {
84
+ helper: "permdock_can_assign_any_for",
85
+ args: "uuid, text, uuid, text, text",
86
+ role: "postgres",
87
+ sql: "permdock_can_assign_any_for({user}, {role}, {tenant}, '{scope}', {tenant}::text)"
88
+ }
89
+ };
90
+ const listedName = (entry) => entry.listedAs ?? entry.helper;
91
+ const OPTIONAL = [
92
+ "idsWithFor",
93
+ "isPlatformFor",
94
+ "memberIds",
95
+ "memberIdsFor",
96
+ "canAssign",
97
+ "canAssignFor",
98
+ "permissionsFor"
99
+ ];
100
+ /** Postgres aliases of the id types better-supabase reads (`uuid`, `text`, `bigint`, `integer`). */
101
+ const ID_TYPES = {
102
+ uuid: "uuid",
103
+ text: "text",
104
+ bigint: "bigint",
105
+ int8: "bigint",
106
+ integer: "integer",
107
+ int: "integer",
108
+ int4: "integer"
109
+ };
110
+ const withSchema = (schema, sql) => sql.includes("{schema}") ? sql.replaceAll("{schema}", schema) : `${schema}.${sql}`;
111
+ /** `p_user uuid, p_grant text` as `uuid, text`. */
112
+ const argTypes = (args) => args.split(",").map((arg) => arg.trim().split(/\s+/u).slice(1).join(" ")).filter((type) => type !== "").join(", ");
113
+ function tenantScopeOf(manifest, explicit) {
114
+ const names = manifest.rls.scopes.map((scope) => scope.name);
115
+ if (explicit !== void 0) {
116
+ if (!names.includes(explicit)) throw new TypeError(`PermDock: scope "${explicit}" is not in the manifest's rls.scopes (${names.join(", ")}).`);
117
+ return explicit;
118
+ }
119
+ const roots = manifest.rls.scopes.filter((scope) => scope.within === void 0);
120
+ const [root] = roots;
121
+ if (root === void 0 || roots.length > 1) throw new TypeError(`PermDock: the manifest has ${roots.length} root scopes (${roots.map((scope) => scope.name).join(", ") || "none"}), so it can't tell which scope tenants are. Pass { scope } with one of ${names.join(", ")}.`);
122
+ return root.name;
123
+ }
124
+ function covers(membership, scope) {
125
+ return !("value" in membership.scope) || membership.scope.value === scope;
126
+ }
127
+ /** `source` as better-supabase reads it, for a source that covers `scope`. */
128
+ function membershipOf(source, scope, problems) {
129
+ if ("through" in source.user) {
130
+ problems.push(`${source.table} reads its user id through ${source.user.through.table}, which better-supabase's membership reads don't follow.`);
131
+ return;
132
+ }
133
+ return {
134
+ table: source.table,
135
+ userColumn: source.user.column,
136
+ scope: "column" in source.scope ? { column: source.scope.column } : { value: scope },
137
+ idColumn: source.id.column
138
+ };
139
+ }
140
+ function roleSourceOf(source) {
141
+ const role = source.role;
142
+ if (Array.isArray(role) || !("column" in role) || !("through" in role)) return;
143
+ return {
144
+ table: source.table,
145
+ role: {
146
+ column: role.column,
147
+ through: {
148
+ table: role.through.table,
149
+ id: role.through.id,
150
+ column: role.through.column
151
+ }
152
+ }
153
+ };
154
+ }
155
+ function disabledRow(row) {
156
+ return {
157
+ table: row.table,
158
+ id: row.id,
159
+ ...row.disabledAt === void 0 ? {} : { disabledAt: row.disabledAt },
160
+ ...row.status === void 0 || row.active === void 0 ? {} : {
161
+ status: row.status,
162
+ active: row.active
163
+ }
164
+ };
165
+ }
166
+ function permissionsOf(catalog, scopes) {
167
+ return catalog.permissions.map((permission) => {
168
+ const granted = /* @__PURE__ */ new Set();
169
+ for (const grant of catalog.grants ?? []) if (grant.permission === permission.key && typeof grant.scope === "string" && scopes.has(grant.scope)) granted.add(grant.scope);
170
+ return {
171
+ key: permission.key,
172
+ sqlComplete: !permission.rowConditions,
173
+ ...granted.size > 0 ? { scopes: [...granted].toSorted() } : {}
174
+ };
175
+ });
176
+ }
177
+ function tokenHookOf(manifest) {
178
+ const owned = manifest.claims.filter((claim) => claim.source === "permdock");
179
+ const registered = manifest.claims.filter((claim) => claim.source !== "permdock");
180
+ const budgeted = manifest.claims.filter((claim) => claim.budget);
181
+ return {
182
+ function: `${manifest.hook.schema}.${manifest.hook.function}`,
183
+ tenantClaim: manifest.tenantClaim,
184
+ ownedClaims: owned.map((claim) => claim.name),
185
+ ...registered.length > 0 ? { registeredClaims: registered.map((claim) => ({
186
+ name: claim.name,
187
+ function: claim.source
188
+ })) } : {},
189
+ budget: {
190
+ claims: budgeted.map((claim) => claim.name),
191
+ bytes: manifest.budget.bytes,
192
+ ...owned.some((claim) => claim.name === "memberships_truncated") ? { truncatedClaim: "memberships_truncated" } : {}
193
+ },
194
+ markers: {
195
+ hook: `-- permdock:hook ${manifest.markers.hook}`,
196
+ grants: `-- permdock:grants ${manifest.markers.grants}`
197
+ },
198
+ grantsCommand: `permdock supabase hook generate --grants-out supabase/migrations/<timestamp>_permdock_hook_grants.sql`
199
+ };
200
+ }
201
+ /**
202
+ * better-supabase's `authorization` config value, built from PermDock's
203
+ * manifest and catalog: the scopes, the `rls generate` helpers as SQL
204
+ * templates, the membership tables, suspension rows, the token hook and
205
+ * every catalog key with `sqlComplete` set from its `rowConditions`. A
206
+ * `_for` template and `permissionsFor` are set only when the manifest lists
207
+ * their helper, which `rls.mode: 'database'` writes; `canApprove` only with
208
+ * `approver`. Throws when the manifest or catalog is invalid, or when the
209
+ * tenant scope is ambiguous.
210
+ */
211
+ function authorizationProvider(options) {
212
+ const manifest = parseSupabaseManifest(options.manifest);
213
+ const catalog = options.catalog === void 0 ? void 0 : parseCatalog(options.catalog);
214
+ const rls = manifest.rls;
215
+ const problems = [];
216
+ if (catalog === void 0) problems.push("No catalog: better-supabase cannot check that the permission keys its SQL modules use (ai_chat, workflow, inbox and the rest) exist. Pass `catalog`.");
217
+ const tenantScope = tenantScopeOf(manifest, options.scope);
218
+ const scopeNames = rls.scopes.map((scope) => scope.name);
219
+ const helpers = new Map(rls.helpers.map((helper) => [helper.name, helper]));
220
+ const schema = sqlIdent(rls.schema);
221
+ const rootTenant = rls.scopes.find((scope) => scope.name === tenantScope)?.within === void 0;
222
+ const assignAny = rls.customRoles === true && rootTenant;
223
+ const entryOf = (template) => assignAny && (template === "canAssign" || template === "canAssignFor") ? ASSIGN_ANY[template] : TEMPLATES[template];
224
+ const listed = (template, scope) => helpers.has(listedName(entryOf(template)).replaceAll("{scope}", scope));
225
+ const templates = [
226
+ "idsWith",
227
+ "isPlatform",
228
+ ...OPTIONAL.filter((template) => listed(template, tenantScope))
229
+ ];
230
+ for (const template of ["idsWith", "isPlatform"]) if (!listed(template, tenantScope)) problems.push(`The manifest's rls.helpers has no ${rls.schema}.${listedName(TEMPLATES[template]).replaceAll("{scope}", tenantScope)}. Run \`permdock rls generate\`, then \`permdock supabase inspect --out\`.`);
231
+ if (rls.customRoles === true && !rootTenant && templates.includes("canAssign")) problems.push(`The tenant scope "${tenantScope}" is not a root scope, so canAssign checks declared roles only: ${rls.schema}.${ASSIGN_ANY.canAssign.helper}, which also answers for custom roles, takes the root tenant id.`);
232
+ const optional = {};
233
+ const requires = [];
234
+ const required = /* @__PURE__ */ new Set();
235
+ for (const template of templates) {
236
+ const entry = entryOf(template);
237
+ optional[template] = withSchema(schema, entry.sql);
238
+ for (const scope of entry.helper.includes("{scope}") ? scopeNames : [tenantScope]) {
239
+ const name = entry.helper.replaceAll("{scope}", scope);
240
+ const fn = `${schema}.${sqlIdent(name)}`;
241
+ if (required.has(fn)) continue;
242
+ required.add(fn);
243
+ const helper = helpers.get(name);
244
+ const args = helper === void 0 ? entry.args : argTypes(helper.args);
245
+ requires.push({
246
+ function: fn,
247
+ ...args === "" ? {} : { args },
248
+ role: entry.role
249
+ });
250
+ }
251
+ }
252
+ const memberships = [];
253
+ const roleSources = [];
254
+ for (const source of rls.memberships) {
255
+ if (!covers(source, tenantScope)) continue;
256
+ const membership = membershipOf(source, tenantScope, problems);
257
+ if (membership) memberships.push(membership);
258
+ const roleSource = roleSourceOf(source);
259
+ if (roleSource) roleSources.push(roleSource);
260
+ }
261
+ const users = rls.suspension?.users;
262
+ const tenants = rls.suspension?.scopes?.[tenantScope];
263
+ const approver = options.approver;
264
+ let canApprove;
265
+ if (approver !== void 0) {
266
+ if (catalog !== void 0 && !catalog.permissions.some((permission) => permission.key === approver.key)) problems.push(`The approver permission ${approver.key} is not in the catalog. Run \`permdock catalog\` after adding it to the policy.`);
267
+ const name = `permitted_${tenantScope}_ids_by_permission`;
268
+ canApprove = `{tenant} in (select ${schema}.${sqlIdent(name)}(${quoteSqlLiteral(approver.key)}))`;
269
+ requires.push({
270
+ function: `${schema}.${sqlIdent(name)}`,
271
+ args: "text",
272
+ role: "postgres"
273
+ });
274
+ }
275
+ const functions = {
276
+ ...optional,
277
+ idsWith: `${schema}.${TEMPLATES.idsWith.sql}`,
278
+ isPlatform: `${schema}.${TEMPLATES.isPlatform.sql}`,
279
+ ...canApprove === void 0 ? {} : { canApprove }
280
+ };
281
+ const scopes = rls.scopes.map((scope) => {
282
+ const idType = ID_TYPES[scope.type.trim().toLowerCase()];
283
+ if (idType === void 0) problems.push(`Scope "${scope.name}" has ids of type ${scope.type}; better-supabase reads uuid, text, bigint and integer ids.`);
284
+ return scope.within === void 0 ? {
285
+ name: scope.name,
286
+ idType: idType ?? scope.type
287
+ } : {
288
+ name: scope.name,
289
+ idType: idType ?? scope.type,
290
+ parent: scope.within
291
+ };
292
+ });
293
+ return freezeDeep({
294
+ apiVersion: 1,
295
+ name: "PermDock",
296
+ scopes,
297
+ tenantScope,
298
+ functions,
299
+ requires,
300
+ ...catalog ? { permissions: permissionsOf(catalog, new Set(scopeNames)) } : {},
301
+ ...memberships.length > 0 ? { memberships } : {},
302
+ ...users || tenants ? { suspension: {
303
+ ...users ? { user: disabledRow(users) } : {},
304
+ ...tenants ? { tenant: disabledRow(tenants) } : {}
305
+ } } : {},
306
+ ...roleSources.length > 0 ? { roleSources } : {},
307
+ ...canApprove === void 0 ? {} : { approvals: { distinctApprover: true } },
308
+ decidingColumns: manifest.decidingColumns,
309
+ tokenHook: tokenHookOf(manifest),
310
+ ...problems.length > 0 ? { problems } : {}
311
+ });
312
+ }
313
+ //#endregion
314
+ //#region src/better-supabase/policies.ts
315
+ /** PermDock splits a key with row conditions into `key#1`, `key#2`, ... in the policies it generates. */
316
+ const SPLIT_KEY = /#\d+$/u;
317
+ function checkedKey(where, permission, catalog, scope) {
318
+ const key = permission.key;
319
+ if (SPLIT_KEY.test(key)) throw new TypeError(`PermDock: ${where} "${key}" is one part of a permission split by row condition. Use the policies \`permdock rls generate\` writes for it.`);
320
+ const entry = catalog.permissions.find((candidate) => candidate.key === key);
321
+ if (!entry) throw new TypeError(`PermDock: ${where} "${key}" is not in permissions.catalog.json. Run \`permdock catalog\`.`);
322
+ if (entry.rowConditions) throw new TypeError(`PermDock: ${where} "${key}" has row conditions (rowConditions: true), which the SQL helpers don't check, so the policy would grant every object in the scope. Use the policies \`permdock rls generate\` writes for it.`);
323
+ const grantScope = scope === "platform" ? "global" : scope;
324
+ const scopes = (catalog.grants ?? []).flatMap((grant) => grant.permission === key && typeof grant.scope === "string" ? [grant.scope] : []);
325
+ if (scopes.length > 0 && !scopes.includes(grantScope)) throw new TypeError(`PermDock: ${where} "${key}" is granted at ${[...new Set(scopes)].join(", ")}, not at ${grantScope}. Check it at one of those scopes.`);
326
+ return key;
327
+ }
328
+ function target(options) {
329
+ const manifest = parseSupabaseManifest(options.manifest);
330
+ const catalog = parseCatalog(options.catalog);
331
+ const names = manifest.rls.scopes.map((scope) => scope.name);
332
+ if (options.scope !== "platform" && !names.includes(options.scope)) throw new TypeError(`PermDock: scope "${options.scope}" is not in the manifest's rls.scopes (${names.join(", ")}) and is not "platform".`);
333
+ const schema = sqlIdent(manifest.rls.schema);
334
+ return {
335
+ catalog,
336
+ sql: {
337
+ idsWith: `${schema}.permitted_{scope}_ids_by_permission({permission})`,
338
+ isPlatform: `${schema}.permdock_has_permission({permission})`
339
+ }
340
+ };
341
+ }
342
+ /**
343
+ * A better-supabase bucket `policy` that checks PermDock permissions with
344
+ * the `rls generate` helpers at `scope`. The helpers check role and scope
345
+ * only, so a permission the catalog doesn't mark `rowConditions: false`, or
346
+ * doesn't grant at `scope`, throws.
347
+ */
348
+ function bucketPolicy(access, options) {
349
+ const { catalog, sql } = target(options);
350
+ const key = (name, permission) => checkedKey(`bucket access.${name}`, permission, catalog, options.scope);
351
+ return freezeDeep({
352
+ access: {
353
+ read: key("read", access.read),
354
+ ...access.list ? { list: key("list", access.list) } : {},
355
+ write: key("write", access.write),
356
+ ...access.delete ? { delete: key("delete", access.delete) } : {}
357
+ },
358
+ scope: options.scope,
359
+ ...options.segment === void 0 ? {} : { segment: options.segment },
360
+ sql
361
+ });
362
+ }
363
+ /** As {@link bucketPolicy}, for a better-supabase Realtime topic. */
364
+ function topicPolicy(access, options) {
365
+ const { catalog, sql } = target(options);
366
+ const key = (name, permission) => checkedKey(`topic ${name}`, permission, catalog, options.scope);
367
+ return freezeDeep({
368
+ receive: key("receive", access.receive),
369
+ ...access.send ? { send: key("send", access.send) } : {},
370
+ scope: options.scope,
371
+ ...options.segment === void 0 ? {} : { segment: options.segment },
372
+ sql
373
+ });
374
+ }
375
+ //#endregion
376
+ //#region src/better-supabase/api-keys.ts
377
+ const seconds = (instant) => Math.floor(instant.epochMilliseconds / 1e3);
378
+ /** When a key stops verifying: its expiry, or the end of a rotated key's grace period. */
379
+ function endOf(key) {
380
+ const { expiresAt, revokedAt } = key;
381
+ if (revokedAt === void 0) return expiresAt;
382
+ if (expiresAt === void 0) return revokedAt;
383
+ return revokedAt.epochMilliseconds < expiresAt.epochMilliseconds ? revokedAt : expiresAt;
384
+ }
385
+ /** `rls.apiKeys.serviceRoles` from the manifest, when it has `rls.apiKeys`. */
386
+ function manifestServiceRoles(manifest) {
387
+ return manifest === void 0 ? void 0 : parseSupabaseManifest(manifest).rls.apiKeys?.serviceRoles;
388
+ }
389
+ /**
390
+ * A personal key as a `user` credential acting as its user, a tenant key as
391
+ * a `service` credential holding `roles` in its tenant; `null` when `*`
392
+ * has no expansion, a tenant key has no roles, or the record is invalid.
393
+ */
394
+ function keyCredential(key, roles, allPermissions) {
395
+ const scopes = key.scopes.includes("*") ? allPermissions?.map((permission) => permission.key) : key.scopes;
396
+ if (scopes === void 0) return null;
397
+ const owner = key.userId;
398
+ const base = {
399
+ v: 1,
400
+ id: key.id,
401
+ permissions: scopes.map((permission) => ({ permission })),
402
+ createdBy: key.createdBy ?? owner ?? key.id,
403
+ createdAt: key.createdAt ?? 0,
404
+ ...key.expiresAt === void 0 ? {} : { expiresAt: key.expiresAt },
405
+ name: key.name
406
+ };
407
+ if (owner !== void 0) return parseCredential({
408
+ ...base,
409
+ kind: "user",
410
+ principal: owner,
411
+ ...key.organizationId === void 0 ? {} : { tenant: key.organizationId }
412
+ }) ?? null;
413
+ if (roles === void 0 || key.organizationId === void 0) return null;
414
+ return parseCredential({
415
+ ...base,
416
+ kind: "service",
417
+ principal: key.id,
418
+ tenant: key.organizationId,
419
+ roles
420
+ }) ?? null;
421
+ }
422
+ /**
423
+ * better-supabase's API keys as a `CredentialVerifier`, for
424
+ * `subjectFromApiKey` from `permdock/server`, which reads PermDock's
425
+ * `pdk_<id>_<secret>` format: create the keys with `prefix: "pdk"`. The
426
+ * credential id is the key's `publicId`, the id in the token. A personal key
427
+ * is a `user` credential acting as its user (inside its tenant when the key
428
+ * is limited to one), a tenant key a `service` credential holding
429
+ * `serviceRoles` in its tenant, and the key's scopes are the credential's
430
+ * permissions. better-supabase records the use when it verifies, so there is
431
+ * no `touch`. A rotated key in its grace period verifies, and its credential
432
+ * expires when the grace period ends. An invalid, revoked, expired or
433
+ * rate-limited key, and a failed lookup, are `null`. `permdock/server` exports a different
434
+ * `apiKeyVerifier`, over the application's own key records.
435
+ */
436
+ function apiKeyVerifier(options) {
437
+ const fallback = manifestServiceRoles(options.manifest);
438
+ return freezeDeep({ async verify(secret) {
439
+ try {
440
+ const checked = await options.keys.verify(secret);
441
+ if (!checked.ok || checked.data.status !== "ok") return null;
442
+ const { key } = checked.data;
443
+ if (key.state !== "active" && key.state !== "grace") return null;
444
+ const end = endOf(key);
445
+ const roles = typeof options.serviceRoles === "function" ? options.serviceRoles(key) : options.serviceRoles ?? fallback;
446
+ return keyCredential({
447
+ id: key.publicId,
448
+ name: key.name,
449
+ scopes: key.scopes,
450
+ createdAt: seconds(key.createdAt),
451
+ ...key.organizationId === void 0 ? {} : { organizationId: key.organizationId },
452
+ ...key.userId === void 0 ? {} : { userId: key.userId },
453
+ ...key.createdBy === void 0 ? {} : { createdBy: key.createdBy },
454
+ ...end === void 0 ? {} : { expiresAt: seconds(end) }
455
+ }, roles, options.allPermissions);
456
+ } catch {
457
+ return null;
458
+ }
459
+ } });
460
+ }
461
+ /**
462
+ * The `claim` and `tenantClaim` options of better-supabase's
463
+ * `apiKeyClaims()`, from the manifest's `rls.apiKeys`, so a key's token
464
+ * carries the scopes ceiling, tenant and roles the `rls generate` helpers
465
+ * read. Throws when the manifest has no `rls.apiKeys`.
466
+ */
467
+ function apiKeyClaimOptions(manifest) {
468
+ const rls = parseSupabaseManifest(manifest).rls;
469
+ const apiKeys = rls.apiKeys;
470
+ if (!apiKeys) throw new TypeError("PermDock: the manifest has no rls.apiKeys. Set rls.apiKeys in permdock.config.ts, then run `permdock rls generate` and `permdock supabase inspect --out`.");
471
+ return freezeDeep({
472
+ claim: {
473
+ name: apiKeys.claim,
474
+ scopes: apiKeys.scopes,
475
+ tenant: apiKeys.tenant,
476
+ roles: apiKeys.roles,
477
+ serviceRoles: apiKeys.serviceRoles
478
+ },
479
+ tenantClaim: rls.tenantClaim
480
+ });
481
+ }
482
+ //#endregion
483
+ //#region src/better-supabase/credentials.ts
484
+ /**
485
+ * `provider` with every `getToken`, `startAuthorization`,
486
+ * `completeAuthorization` and `revoke` decided by PermDock first, on the
487
+ * `CredentialRef` as the row. Anything but `granted` is a `forbidden`
488
+ * error with hint `PERMDOCK_DENIED`, and a failed check is one too.
489
+ * `capabilities` and `verifyInbound` (a third party's request, with no
490
+ * user) pass through. Build it per request, with that request's PermDock.
491
+ */
492
+ function credentialGuard(provider, options) {
493
+ const allowed = async (permission, ref) => {
494
+ try {
495
+ return (await options.permdock()).can(permission, ref);
496
+ } catch {
497
+ return false;
498
+ }
499
+ };
500
+ const guarded = (permission, ref, run) => AsyncResult.from(async () => await allowed(permission, ref) ? run() : AsyncResult.err(dbError("forbidden", `PermDock denied ${permission.key}`, { hint: "PERMDOCK_DENIED" })));
501
+ const revoke = options.revoke ?? options.use;
502
+ const start = provider.startAuthorization?.bind(provider);
503
+ const complete = provider.completeAuthorization?.bind(provider);
504
+ const inbound = provider.verifyInbound?.bind(provider);
505
+ return Object.freeze({
506
+ apiVersion: 1,
507
+ name: provider.name,
508
+ getToken: (ref, getOptions) => guarded(options.use, ref, () => provider.getToken(ref, getOptions)),
509
+ capabilities: (ref) => provider.capabilities(ref),
510
+ ...start === void 0 ? {} : { startAuthorization: (ref, startOptions) => guarded(options.use, ref, () => start(ref, startOptions)) },
511
+ ...complete === void 0 ? {} : { completeAuthorization: (ref, completeOptions) => guarded(options.use, ref, () => complete(ref, completeOptions)) },
512
+ revoke: (ref, revokeOptions) => guarded(revoke, ref, () => provider.revoke(ref, revokeOptions)),
513
+ ...inbound === void 0 ? {} : { verifyInbound: inbound }
514
+ });
515
+ }
516
+ //#endregion
517
+ //#region src/better-supabase/mcp.ts
518
+ const refused = (reason) => ({
519
+ allowed: false,
520
+ reason
521
+ });
522
+ /**
523
+ * The `authorize` and `visible` hooks of better-supabase's `createMcp`, for
524
+ * tools whose `meta` is a PermDock permission. A tool without a permission
525
+ * is hidden and refused. `authorize` grants only a `granted` decision: an
526
+ * approval-required call is refused, because `createMcp`
527
+ * has no approval flow. A throw anywhere refuses.
528
+ */
529
+ function toolPolicy(options) {
530
+ return Object.freeze({
531
+ async authorize(ctx, tool, args) {
532
+ const permission = tool.meta;
533
+ if (!isPermission(permission)) return refused("This tool has no PermDock permission.");
534
+ try {
535
+ const permdock = await options.permdock(ctx);
536
+ const data = await options.data?.(ctx, tool, args);
537
+ const decision = permdock.decide(permission, data);
538
+ switch (decision.outcome) {
539
+ case "granted": return { allowed: true };
540
+ case "approval-required": return refused(`${permission.key} needs approval, which this server does not collect.`);
541
+ case "denied": return refused(`PermDock denied ${permission.key}.`);
542
+ default: return decision;
543
+ }
544
+ } catch {
545
+ return refused("The permission check failed.");
546
+ }
547
+ },
548
+ async visible(ctx, tool) {
549
+ const permission = tool.meta;
550
+ if (!isPermission(permission)) return false;
551
+ try {
552
+ return mayUse(await options.permdock(ctx), permission);
553
+ } catch {
554
+ return false;
555
+ }
556
+ }
557
+ });
558
+ }
559
+ //#endregion
560
+ //#region src/better-supabase/subject.ts
561
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
562
+ /** `session` with the short codes in `claim` turned back into feature keys. */
563
+ function decodedFeatures(session, claim, keys) {
564
+ const claims = session?.claims;
565
+ if (session === null || session === void 0 || !isRecord(claims)) return session;
566
+ const coded = claims[claim];
567
+ if (!isRecord(coded)) return session;
568
+ const byCode = new Map(Object.entries(keys).map(([key, code]) => [code, key]));
569
+ const decoded = Object.fromEntries(Object.entries(coded).map(([tenant, codes]) => [tenant, Array.isArray(codes) ? codes.flatMap((code) => {
570
+ const key = typeof code === "string" ? byCode.get(code) : void 0;
571
+ return key === void 0 ? [] : [key];
572
+ }) : codes]));
573
+ return {
574
+ ...session,
575
+ claims: {
576
+ ...claims,
577
+ [claim]: decoded
578
+ }
579
+ };
580
+ }
581
+ function isApiKeySession(session) {
582
+ if (typeof session !== "object" || session === null) return false;
583
+ const record = Object.fromEntries(Object.entries(session));
584
+ return record["kind"] === "apiKey" && typeof record["keyId"] === "string" && typeof record["name"] === "string" && Array.isArray(record["scopes"]) && record["scopes"].every((scope) => typeof scope === "string");
585
+ }
586
+ function apiKeySubject(session, options) {
587
+ const roles = typeof options.serviceRoles === "function" ? options.serviceRoles(session) : options.serviceRoles ?? manifestServiceRoles(options.manifest);
588
+ const credential = keyCredential({
589
+ id: session.keyId,
590
+ name: session.name,
591
+ scopes: session.scopes,
592
+ ...session.organizationId === void 0 ? {} : { organizationId: session.organizationId },
593
+ ...session.userId === void 0 ? {} : { userId: session.userId },
594
+ ...session.createdBy === void 0 ? {} : { createdBy: session.createdBy },
595
+ ...session.createdAt === void 0 ? {} : { createdAt: session.createdAt }
596
+ }, roles, listPermissions(options.permissions));
597
+ return credential === null ? anonymousSubject() : credentialSubject(credential, { permissions: options.permissions });
598
+ }
599
+ /**
600
+ * `subjectFromSupabaseSession` for better-supabase's `AuthSession`, reading
601
+ * `memberships` for the memberships and the entitlements module's `features`
602
+ * claim for `principal.plans` (`plans` names another claim). With `apiKeys`,
603
+ * a verified `apiKey` session is the key's credential subject: a personal key
604
+ * acts as its user within the key's scopes, a tenant key as a `service`
605
+ * principal holding `serviceRoles`. Without `apiKeys`, and for `anon`,
606
+ * `service` and `invalid` sessions, the subject is anonymous.
607
+ */
608
+ function subjectFromBetterSupabase(session, options = {}) {
609
+ const { apiKeys, plans = "features", ...rest } = options;
610
+ if (isApiKeySession(session)) return apiKeys === void 0 ? anonymousSubject() : apiKeySubject(session, apiKeys);
611
+ const claim = typeof plans === "string" ? plans : plans.claim ?? "features";
612
+ const keys = typeof plans === "string" ? void 0 : plans.keys;
613
+ return subjectFromSupabaseSession(keys === void 0 ? session : decodedFeatures(session, claim, keys), {
614
+ memberships: "memberships",
615
+ ...rest,
616
+ plans: claim
617
+ });
618
+ }
619
+ //#endregion
620
+ export { apiKeyClaimOptions, apiKeyVerifier, authorizationProvider, bucketPolicy, credentialGuard, subjectFromBetterSupabase, toolPolicy, topicPolicy };
@@ -0,0 +1,25 @@
1
+ import { f as ApprovalStore } from "./types-vKyAMtcX.js";
2
+ import { t as InstanceOptions } from "./instance-options-BK_rNOSC.js";
3
+ import { r as PdpFactory } from "./types-BVyImy5I.js";
4
+ import { o as OtelWrap } from "./types-vNSDF7Dq.js";
5
+ import { T as TenantOption, b as WebBotAuthVerifier } from "./create-BWyx3jua.js";
6
+ //#region src/server/bind.d.ts
7
+ /** The options of every framework adapter; `TContext` is what its callbacks receive. */
8
+ type ServerAdapterOptions<TContext, TUser = unknown> = InstanceOptions & ServerAdapterServices & {
9
+ readonly subject: (context: TContext) => TUser | Promise<TUser>;
10
+ /** The agent or service acting for the subject; anything but an `Actor` is ignored. */
11
+ readonly actor?: (context: TContext) => unknown;
12
+ readonly tenant?: TenantOption<TContext>;
13
+ };
14
+ /** The services an adapter hands to its kernel unchanged. */
15
+ type ServerAdapterServices = {
16
+ readonly store?: ApprovalStore;
17
+ /** `createPermDock` from `permdock/pdp`; `protect` then decides delegated permissions remotely. */
18
+ readonly pdp?: PdpFactory;
19
+ /** `(permdock) => withOtel(permdock, options)` from `permdock/otel`. */
20
+ readonly otel?: OtelWrap;
21
+ /** `(request) => verifyWebBotAuth(request, options)`; a verified bot becomes the actor. */
22
+ readonly webBotAuth?: WebBotAuthVerifier;
23
+ };
24
+ //#endregion
25
+ export { ServerAdapterServices as n, ServerAdapterOptions as t };