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,534 @@
1
+ import { t as compact } from "./compact-y6vfu2_f.js";
2
+ import { a as quoteSqlTable, i as quoteSqlLiteral, r as quoteSqlIdent } from "./sql-xdg5f4Fi.js";
3
+ //#region src/supabase/keep.ts
4
+ /** The permission keys of a suspended scope's `keep`, references read by `key`, sorted and unique. */
5
+ function keptKeys(row) {
6
+ const keep = row?.keep;
7
+ if (keep === void 0) return [];
8
+ const keys = Array.isArray(keep) ? keep.map((item) => typeof item === "string" ? item : item !== null && typeof item === "object" && "key" in item ? item.key : void 0) : [void 0];
9
+ const valid = keys.filter((key) => typeof key === "string" && key !== "");
10
+ if (valid.length !== keys.length) throw new TypeError("PermDock: a suspension keep is a list of permissions or permission keys");
11
+ return [...new Set(valid)].toSorted();
12
+ }
13
+ //#endregion
14
+ //#region src/supabase/roles.ts
15
+ function isRoleList(role) {
16
+ return Array.isArray(role);
17
+ }
18
+ /**
19
+ * Resolves the role sources of `table` (`schema.table`, or `public`). An
20
+ * unqualified `through` table is in `table`'s schema. `label` names the
21
+ * option in the error for an `on` that is not exactly one column; `prefix`
22
+ * starts every error. A row with several sources holds the union of their
23
+ * non-null keys.
24
+ */
25
+ function roleColumn(role, table, alias, options) {
26
+ if (!isRoleList(role)) return singleRole(role, table, alias, options);
27
+ const prefix = options.prefix ?? "PermDock";
28
+ const parts = role.map((part, index) => singleRole(part, table, alias, {
29
+ ...options,
30
+ label: `${options.label}[${String(index)}]`
31
+ }));
32
+ const [first] = parts;
33
+ if (first === void 0) throw new TypeError(`${prefix}: ${options.label} needs at least one role source`);
34
+ if (parts.length === 1) return first;
35
+ const rows = quoteSqlIdent(`${alias}r`, prefix);
36
+ const values = quoteSqlIdent(`${alias}v`, prefix);
37
+ const sql = `${rows}.permdock_role`;
38
+ return {
39
+ column: first.column,
40
+ sql,
41
+ join: `${options.indent === void 0 ? " " : `\n${options.indent}`}cross join lateral (select ${values}.role from (values ${parts.map((part) => `(${part.lookup})`).join(", ")}) ${values}(role) where ${values}.role is not null) ${rows}(permdock_role)`,
42
+ lookup: sql,
43
+ columns: [...new Set(parts.map((part) => part.column))],
44
+ throughs: parts.flatMap((part) => part.throughs),
45
+ lateral: true
46
+ };
47
+ }
48
+ function singleRole(role, table, alias, options) {
49
+ const prefix = options.prefix ?? "PermDock";
50
+ const q = (name) => quoteSqlIdent(name, prefix);
51
+ if (typeof role === "string") return {
52
+ column: role,
53
+ sql: `${alias}.${q(role)}::text`,
54
+ join: "",
55
+ lookup: `${alias}.${q(role)}::text`,
56
+ columns: [role],
57
+ throughs: [],
58
+ lateral: false
59
+ };
60
+ const pairs = Object.entries(role.on);
61
+ const [pair] = pairs;
62
+ if (pair === void 0 || pairs.length !== 1) throw new TypeError(`${prefix}: ${options.label}.on must map exactly one column of ${table} to ${role.through}, for example ${options.example ?? "{ role_id: 'id' }"}`);
63
+ const [ref, id] = pair;
64
+ const schema = table.includes(".") ? table.split(".")[0] ?? "public" : "public";
65
+ const through = role.through.includes(".") ? role.through : `${schema}.${role.through}`;
66
+ const keys = options.joined ?? `${alias}k`;
67
+ const target = quoteSqlTable(through, prefix);
68
+ const keyed = {
69
+ table: through,
70
+ id,
71
+ key: role.column,
72
+ ref
73
+ };
74
+ return {
75
+ column: ref,
76
+ sql: `${keys}.${q(role.column)}::text`,
77
+ join: `${options.indent === void 0 ? " " : `\n${options.indent}`}join ${target} ${keys} on ${keys}.${q(id)} = ${alias}.${q(ref)}`,
78
+ lookup: `(select ${keys}.${q(role.column)}::text from ${target} ${keys} where ${keys}.${q(id)} = ${alias}.${q(ref)})`,
79
+ through: keyed,
80
+ columns: [ref],
81
+ throughs: [keyed],
82
+ lateral: false
83
+ };
84
+ }
85
+ /** The manifest entry of one role source: the column, and the roles table it references. */
86
+ function sourceManifest(column, through) {
87
+ return through === void 0 ? { column } : {
88
+ column,
89
+ through: {
90
+ table: through.table,
91
+ id: through.id,
92
+ column: through.key
93
+ }
94
+ };
95
+ }
96
+ /** The manifest entry of a single-source column, such as a membership's user. */
97
+ function columnManifest(role) {
98
+ return sourceManifest(role.column, role.through);
99
+ }
100
+ /** The manifest entry of a role column, or one entry per source of a row with several. */
101
+ function roleManifest(role) {
102
+ if (!role.lateral) return sourceManifest(role.column, role.through);
103
+ return role.columns.map((column) => sourceManifest(column, role.throughs.find((through) => through.ref === column)));
104
+ }
105
+ //#endregion
106
+ //#region src/supabase/sources.ts
107
+ const ident = (name) => quoteSqlIdent(name);
108
+ const literal = quoteSqlLiteral;
109
+ function qualifiedName(name) {
110
+ return name.includes(".") ? name : `public.${name}`;
111
+ }
112
+ function qualified(name) {
113
+ return quoteSqlTable(qualifiedName(name));
114
+ }
115
+ function col(name) {
116
+ return `m.${ident(name)}`;
117
+ }
118
+ function activeRow(row, id) {
119
+ const parts = [`s.${ident(row.id)}::text = (${id})::text`];
120
+ if (row.disabledAt !== void 0) parts.push(`s.${ident(row.disabledAt)} is null`);
121
+ if (row.status !== void 0) {
122
+ const values = row.active ?? [];
123
+ if (values.length === 0) throw new TypeError("PermDock: a suspension status column needs its active values");
124
+ parts.push(`s.${ident(row.status)}::text = any(array[${values.map(literal).join(", ")}]::text[])`);
125
+ }
126
+ if (row.disabledAt === void 0 && row.status === void 0) throw new TypeError("PermDock: a suspension table needs disabledAt or status");
127
+ return `exists (select 1 from ${qualified(row.table)} s where ${parts.join(" and ")})`;
128
+ }
129
+ function textArray(values) {
130
+ return `array[${values.map(literal).join(", ")}]::text[]`;
131
+ }
132
+ /**
133
+ * The suspendable instances on the row's chain whose scope keeps
134
+ * permissions: each one's active check and its kept keys.
135
+ */
136
+ function keeping(shape) {
137
+ const scopes = Object.entries(shape.suspension?.scopes ?? {}).flatMap(([name, row]) => {
138
+ const id = shape.idOf(name);
139
+ const keep = keptKeys(row);
140
+ return id === void 0 || keep.length === 0 ? [] : [{
141
+ active: `(${id} is null or ${activeRow(row, id)})`,
142
+ keep
143
+ }];
144
+ });
145
+ const keep = keptKeys(shape.suspension?.memberships);
146
+ return shape.disabledAt === void 0 || keep.length === 0 ? scopes : [...scopes, {
147
+ active: enabled(shape.disabledAt),
148
+ keep
149
+ }];
150
+ }
151
+ function enabled(disabledAt) {
152
+ return `${col(disabledAt)} is null`;
153
+ }
154
+ function keepsDisabled(shape) {
155
+ return shape.disabledAt !== void 0 && keptKeys(shape.suspension?.memberships).length > 0;
156
+ }
157
+ /**
158
+ * The keys a row on a suspended chain still grants, as a sorted `jsonb`
159
+ * array: the keys every suspended instance on it keeps. `null` when nothing
160
+ * is kept.
161
+ */
162
+ function keptSql(shape) {
163
+ const list = keeping(shape);
164
+ if (list.length === 0) return;
165
+ const keys = [...new Set(list.flatMap((item) => item.keep))].toSorted();
166
+ const each = list.map((item) => `(${item.active} or k = any(${textArray(item.keep)}))`).join(" and ");
167
+ return `(select jsonb_agg(k order by k) from unnest(${textArray(keys)}) k where ${each})`;
168
+ }
169
+ function allActive(shape) {
170
+ return keeping(shape).map((item) => item.active).join(" and ");
171
+ }
172
+ function filters(shape, owner) {
173
+ const lines = [owner];
174
+ if (shape.expiresAt !== void 0) {
175
+ const expires = col(shape.expiresAt);
176
+ lines.push(`(${expires} is null or ${expires} > now())`);
177
+ }
178
+ if (shape.disabledAt !== void 0 && !keepsDisabled(shape)) lines.push(enabled(shape.disabledAt));
179
+ const users = shape.suspension?.users;
180
+ if (users !== void 0) lines.push(activeRow(users, shape.userSql));
181
+ for (const [name, row] of Object.entries(shape.suspension?.scopes ?? {})) {
182
+ const id = shape.idOf(name);
183
+ if (id !== void 0 && keptKeys(row).length === 0) lines.push(`(${id} is null or ${activeRow(row, id)})`);
184
+ }
185
+ const kept = keptSql(shape);
186
+ if (kept !== void 0) lines.push(`(${allActive(shape)} or ${kept} is not null)`);
187
+ return lines;
188
+ }
189
+ function keepColumn(shape) {
190
+ const kept = keptSql(shape);
191
+ return kept === void 0 ? "null::jsonb" : `(array_agg(case when ${allActive(shape)} then null else ${kept} end))[1]`;
192
+ }
193
+ function selectOf(shape, where, user, keep) {
194
+ const fields = [
195
+ ...user ? [`${shape.userSql}::text as user_id`] : [],
196
+ `${shape.scope} as scope`,
197
+ `${shape.id} as id`,
198
+ `${shape.within} as within`,
199
+ `${shape.roles} as roles`,
200
+ `${shape.via} as via`,
201
+ `${shape.expiresAt === void 0 ? "null::bigint" : `floor(extract(epoch from ${col(shape.expiresAt)}))::bigint`} as expires_at`,
202
+ `${shape.grantedBy} as granted_by`,
203
+ `${shape.reason} as reason`,
204
+ `${shape.memberGroup} as member_group`,
205
+ `${shape.managed} as managed_by`,
206
+ `${shape.seats} as seats`,
207
+ ...keep ? [`${keepColumn(shape)} as keep`] : []
208
+ ];
209
+ const group = [
210
+ ...user ? [shape.userSql] : [],
211
+ ...shape.groupBy,
212
+ ...keepsDisabled(shape) && shape.disabledAt !== void 0 ? [`(${enabled(shape.disabledAt)})`] : []
213
+ ];
214
+ return `select ${fields.join(", ")}
215
+ from ${qualified(shape.table)} m${shape.join}
216
+ where ${where.join("\n and ")}
217
+ group by ${group.join(", ")}`;
218
+ }
219
+ function holdersOf(shape) {
220
+ const id = ident(shape.idColumn);
221
+ return {
222
+ idType: `${qualified(shape.table)}.${id}%type`,
223
+ id: (scope, row) => {
224
+ const filter = shape.holds(scope, row);
225
+ return filter === void 0 ? "null::text" : filter === "true" ? `${row}.${id}::text` : `case when ${filter} then ${row}.${id}::text end`;
226
+ },
227
+ rows: (scope, options = {}) => {
228
+ const where = [shape.holds(scope, "m") ?? "false"];
229
+ if (options.id !== void 0) where.push(`m.${id} = ${options.id}`);
230
+ const conditions = [...shape.expiresAt === void 0 ? [] : [`(${col(shape.expiresAt)} is null or ${col(shape.expiresAt)} > now())`], ...shape.disabledAt === void 0 ? [] : [enabled(shape.disabledAt)]];
231
+ const live = conditions.length === 0 ? "true" : conditions.length === 1 ? conditions.join("") : `(${conditions.join(" and ")})`;
232
+ const kept = where.filter((part) => part !== "true");
233
+ return `select m.${id}::text as id, ${shape.userSql}::text as user_id, ${shape.roleKey} as role, ${shape.via} as via, ${live} as live
234
+ from ${options.from ?? qualified(shape.table)} m${shape.join}${shape.roleJoin}${kept.length === 0 ? "" : `\nwhere ${kept.join(" and ")}`}`;
235
+ }
236
+ };
237
+ }
238
+ function sqlOf(shape) {
239
+ const suspension = shape.suspension;
240
+ return compact({
241
+ holders: holdersOf(shape),
242
+ table: shape.table,
243
+ user: shape.user,
244
+ userThrough: shape.userThrough,
245
+ userType: shape.userThrough === void 0 ? `${qualified(shape.table)}.${ident(shape.user)}%type` : `${quoteSqlTable(shape.userThrough.table)}.${ident(shape.userThrough.key)}%type`,
246
+ reads: [...new Set([suspension?.users, ...Object.values(suspension?.scopes ?? {})].flatMap((row) => row === void 0 ? [] : [row.table]))],
247
+ managed: shape.managedColumn,
248
+ through: shape.through,
249
+ throughs: shape.throughs,
250
+ columns: [...new Set(shape.columns)],
251
+ manifest: {
252
+ table: qualifiedName(shape.table),
253
+ ...shape.manifest,
254
+ columns: [...new Set(shape.columns)]
255
+ },
256
+ keeps: keptSql(shape) !== void 0,
257
+ select: (user, keep = keptSql(shape) !== void 0) => selectOf(shape, filters(shape, `${shape.userSql} = ${user}`), false, keep),
258
+ list: (keep = keptSql(shape) !== void 0) => selectOf(shape, filters(shape, `${shape.scope} = $1::text and ${shape.id} = $2::text`), true, keep)
259
+ });
260
+ }
261
+ function isFixed(roles) {
262
+ return Array.isArray(roles);
263
+ }
264
+ /** A role column of the membership table, aliased `m`; a `through` column joins its roles table as `mk`. */
265
+ function memberRole(role, table, label) {
266
+ return roleColumn(role, qualifiedName(table), "m", {
267
+ label,
268
+ indent: ""
269
+ });
270
+ }
271
+ /** The user of the membership table, aliased `m`; a `through` user joins its table as `mu`. */
272
+ function memberUser(user, table, label) {
273
+ const column = roleColumn(user, qualifiedName(table), "m", {
274
+ label,
275
+ indent: "",
276
+ joined: "mu",
277
+ example: "{ contact_profile_id: 'id' }"
278
+ });
279
+ return {
280
+ column,
281
+ sql: column.through === void 0 ? col(column.column) : `mu.${ident(column.through.key)}`
282
+ };
283
+ }
284
+ function roleAgg(role) {
285
+ return `jsonb_agg(distinct ${role.sql} order by ${role.sql})`;
286
+ }
287
+ function rowsOf(result) {
288
+ return Array.isArray(result) ? result : result.rows;
289
+ }
290
+ function strings(value) {
291
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
292
+ }
293
+ function membershipOf(row) {
294
+ const roles = strings(row["roles"]);
295
+ if (typeof row["scope"] !== "string" || typeof row["id"] !== "string") return;
296
+ if (roles.length === 0) return;
297
+ const within = row["within"] !== null && typeof row["within"] === "object" && !Array.isArray(row["within"]) ? Object.fromEntries(Object.entries(row["within"]).filter((entry) => typeof entry[1] === "string")) : void 0;
298
+ const expires = typeof row["expires_at"] === "number" ? row["expires_at"] : typeof row["expires_at"] === "string" && row["expires_at"] !== "" ? Number(row["expires_at"]) : void 0;
299
+ const seats = strings(row["seats"]);
300
+ const keep = row["keep"];
301
+ if (keep !== null && keep !== void 0 && (!Array.isArray(keep) || !keep.every((key) => typeof key === "string" && key !== ""))) return;
302
+ return compact({
303
+ scope: row["scope"],
304
+ id: row["id"],
305
+ within: within === void 0 || Object.keys(within).length === 0 ? void 0 : within,
306
+ roles: [...roles].toSorted(),
307
+ via: typeof row["via"] === "string" ? row["via"] : void 0,
308
+ expiresAt: Number.isFinite(expires) ? expires : void 0,
309
+ grantedBy: typeof row["granted_by"] === "string" && row["granted_by"] !== "" ? row["granted_by"] : void 0,
310
+ reason: typeof row["reason"] === "string" && row["reason"] !== "" ? row["reason"] : void 0,
311
+ member: typeof row["member_group"] === "string" && row["member_group"] !== "" ? { group: row["member_group"] } : void 0,
312
+ managedBy: row["managed_by"] === "idp" ? "idp" : void 0,
313
+ entitlements: seats.length === 0 ? void 0 : seats,
314
+ keep: keep === null || keep === void 0 ? void 0 : strings(keep)
315
+ });
316
+ }
317
+ function sourceOf(sql, query) {
318
+ const run = async (text, values) => {
319
+ if (query === void 0) throw new TypeError(`PermDock: the ${sql.table} membership source needs query to resolve memberships`);
320
+ return rowsOf(await query(text, values));
321
+ };
322
+ return {
323
+ sql,
324
+ async membershipsFor(principal) {
325
+ return (await run(sql.select("$1"), [principal.id])).flatMap((row) => {
326
+ const membership = membershipOf(row);
327
+ return membership === void 0 ? [] : [membership];
328
+ });
329
+ },
330
+ async list(scope) {
331
+ return (await run(sql.list(), [scope.scope, scope.id])).flatMap((row) => {
332
+ const membership = membershipOf(row);
333
+ return membership === void 0 || typeof row["user_id"] !== "string" ? [] : [{
334
+ principal: { id: row["user_id"] },
335
+ membership
336
+ }];
337
+ });
338
+ }
339
+ };
340
+ }
341
+ /**
342
+ * `ctx.postgres` (from `withPostgresClient`) or `ctx.postgresAdmin` as a
343
+ * `SqlQuery` for `fromTable`, `fromJunction` and `supabaseApprovalStore`.
344
+ * `ctx.postgres` runs as the caller under RLS, so the membership tables must
345
+ * be readable by `authenticated`; `ctx.postgresAdmin` bypasses RLS.
346
+ */
347
+ function fromSupabasePostgres(postgres) {
348
+ return (text, values) => postgres.queryRaw(text, [...values]);
349
+ }
350
+ /**
351
+ * Memberships from one table holding every scope: a row per user, scope,
352
+ * instance and role (`user_id, scope, scope_id, role`), with optional
353
+ * `within`, `via`, expiry, owner and seat columns. Rows of the same instance
354
+ * merge into one membership.
355
+ */
356
+ function fromTable(options) {
357
+ const c = options.columns ?? {};
358
+ const scope = `${col(c.scope ?? "scope")}::text`;
359
+ const id = `${col(c.id ?? "scope_id")}::text`;
360
+ const within = c.within === void 0 ? "null::jsonb" : col(c.within);
361
+ const optional = (name, cast) => name === void 0 ? `null::${cast}` : `${col(name)}::${cast}`;
362
+ const user = memberUser(c.user ?? "user_id", options.table, "fromTable columns.user");
363
+ const role = memberRole(c.role ?? "role", options.table, "fromTable columns.role");
364
+ return sourceOf(sqlOf({
365
+ table: options.table,
366
+ join: `${user.column.join}${role.join}`,
367
+ through: role.through,
368
+ throughs: role.throughs,
369
+ user: user.column.column,
370
+ userSql: user.sql,
371
+ userThrough: user.column.through,
372
+ scope,
373
+ id,
374
+ within,
375
+ roles: roleAgg(role),
376
+ via: optional(c.via, "text"),
377
+ expiresAt: c.expiresAt,
378
+ disabledAt: c.disabledAt,
379
+ grantedBy: optional(c.grantedBy, "text"),
380
+ reason: optional(c.reason, "text"),
381
+ memberGroup: optional(c.group, "text"),
382
+ managed: optional(c.managedBy, "text"),
383
+ managedColumn: c.managedBy,
384
+ seats: c.seats === void 0 ? "null::jsonb" : `to_jsonb(${col(c.seats)})`,
385
+ idOf: (name) => `coalesce(case when ${scope} = ${literal(name)} then ${id} end${c.within === void 0 ? "" : `, ${within} ->> ${literal(name)}`})`,
386
+ idColumn: c.id ?? "scope_id",
387
+ holds: (name, alias) => `${alias}.${ident(c.scope ?? "scope")}::text = ${literal(name)}`,
388
+ roleKey: role.sql,
389
+ roleJoin: "",
390
+ groupBy: [
391
+ scope,
392
+ id,
393
+ ...c.within === void 0 ? [] : [within],
394
+ ...[
395
+ c.via,
396
+ c.expiresAt,
397
+ c.grantedBy,
398
+ c.reason,
399
+ c.group,
400
+ c.managedBy,
401
+ c.seats
402
+ ].filter((name) => name !== void 0).map(col)
403
+ ],
404
+ suspension: options.suspension,
405
+ columns: [
406
+ user.column.column,
407
+ c.scope ?? "scope",
408
+ c.id ?? "scope_id",
409
+ ...role.columns,
410
+ ...[
411
+ c.within,
412
+ c.via,
413
+ c.expiresAt,
414
+ c.disabledAt
415
+ ].filter((name) => name !== void 0)
416
+ ],
417
+ manifest: compact({
418
+ user: columnManifest(user.column),
419
+ scope: { column: c.scope ?? "scope" },
420
+ id: { column: c.id ?? "scope_id" },
421
+ role: roleManifest(role),
422
+ within: c.within === void 0 ? void 0 : { column: c.within },
423
+ via: c.via === void 0 ? void 0 : { column: c.via },
424
+ expiresAt: c.expiresAt === void 0 ? void 0 : { column: c.expiresAt },
425
+ disabledAt: c.disabledAt === void 0 ? void 0 : { column: c.disabledAt }
426
+ })
427
+ }), options.query);
428
+ }
429
+ /**
430
+ * Memberships from a table of one scope (`customer_contacts`): every row is a
431
+ * membership of `scope`, with roles from a column or fixed (`['contact']`), a
432
+ * fixed `via`, and ancestor ids from `within` columns.
433
+ */
434
+ function fromJunction(options) {
435
+ if (!/^[a-z][a-z0-9_]*$/u.test(options.scope)) throw new TypeError(`PermDock: unsafe scope name '${options.scope}'`);
436
+ const idColumn = options.id ?? `${options.scope}_id`;
437
+ const withinEntries = Object.entries(options.within ?? {});
438
+ const roles = options.roles;
439
+ const fixed = isFixed(roles) ? roles : void 0;
440
+ if (fixed?.length === 0) throw new TypeError("PermDock: fromJunction needs at least one role");
441
+ const role = isFixed(roles) ? void 0 : memberRole(typeof roles === "object" && "sources" in roles ? roles.sources : roles, options.table, "fromJunction roles");
442
+ const user = memberUser(options.user ?? "user_id", options.table, "fromJunction user");
443
+ const managedColumn = options.managedBy === void 0 ? void 0 : options.managedBy === "idp" ? "" : options.managedBy.column;
444
+ const groupColumn = options.group === void 0 || typeof options.group === "string" ? void 0 : options.group.column;
445
+ const shape = {
446
+ table: options.table,
447
+ join: `${user.column.join}${role?.join ?? ""}`,
448
+ through: role?.through,
449
+ throughs: role?.throughs ?? [],
450
+ user: user.column.column,
451
+ userSql: user.sql,
452
+ userThrough: user.column.through,
453
+ scope: `${literal(options.scope)}::text`,
454
+ id: `${col(idColumn)}::text`,
455
+ within: withinEntries.length === 0 ? "null::jsonb" : `jsonb_build_object(${withinEntries.map(([name, column]) => `${literal(name)}, ${col(column)}::text`).join(", ")})`,
456
+ roles: role === void 0 ? `jsonb_build_array(${(fixed ?? []).map(literal).join(", ")})` : roleAgg(role),
457
+ via: options.via === void 0 ? "null::text" : `${literal(options.via)}::text`,
458
+ expiresAt: options.expiresAt,
459
+ disabledAt: options.disabledAt,
460
+ grantedBy: options.grantedBy === void 0 ? "null::text" : `${col(options.grantedBy)}::text`,
461
+ reason: options.reason === void 0 ? "null::text" : `${col(options.reason)}::text`,
462
+ memberGroup: options.group === void 0 ? "null::text" : typeof options.group === "string" ? `${literal(options.group)}::text` : `${col(options.group.column)}::text`,
463
+ managed: managedColumn === void 0 ? "null::text" : managedColumn === "" ? `'idp'::text` : `${col(managedColumn)}::text`,
464
+ managedColumn,
465
+ seats: options.seats === void 0 ? "null::jsonb" : `to_jsonb(${col(options.seats)})`,
466
+ idColumn,
467
+ holds: (name) => name === options.scope ? "true" : void 0,
468
+ roleKey: role === void 0 ? "mf.role" : role.sql,
469
+ roleJoin: role === void 0 ? ` cross join lateral unnest(array[${(fixed ?? []).map(literal).join(", ")}]::text[]) mf(role)` : "",
470
+ idOf: (name) => {
471
+ if (name === options.scope) return `${col(idColumn)}::text`;
472
+ const column = options.within?.[name];
473
+ return column === void 0 ? void 0 : `${col(column)}::text`;
474
+ },
475
+ groupBy: [
476
+ col(idColumn),
477
+ ...withinEntries.map(([, column]) => col(column)),
478
+ ...[
479
+ options.expiresAt,
480
+ options.grantedBy,
481
+ options.reason,
482
+ groupColumn,
483
+ managedColumn === "" ? void 0 : managedColumn,
484
+ options.seats
485
+ ].filter((name) => name !== void 0).map(col)
486
+ ],
487
+ suspension: options.suspension,
488
+ columns: [
489
+ user.column.column,
490
+ idColumn,
491
+ ...withinEntries.map(([, column]) => column),
492
+ ...role?.columns ?? [],
493
+ ...[options.expiresAt, options.disabledAt].filter((name) => name !== void 0)
494
+ ],
495
+ manifest: compact({
496
+ user: columnManifest(user.column),
497
+ scope: { value: options.scope },
498
+ id: { column: idColumn },
499
+ role: role === void 0 ? { value: [...fixed ?? []] } : roleManifest(role),
500
+ within: withinEntries.length === 0 ? void 0 : { columns: Object.fromEntries(withinEntries) },
501
+ via: options.via === void 0 ? void 0 : { value: options.via },
502
+ expiresAt: options.expiresAt === void 0 ? void 0 : { column: options.expiresAt },
503
+ disabledAt: options.disabledAt === void 0 ? void 0 : { column: options.disabledAt }
504
+ })
505
+ };
506
+ const sql = sqlOf(shape);
507
+ return sourceOf({
508
+ ...sql,
509
+ scope: options.scope,
510
+ holds: [options.scope, ...withinEntries.map(([name]) => name)],
511
+ list: (keep = sql.keeps) => selectOf(shape, filters(shape, `$1::text = ${literal(options.scope)} and ${col(idColumn)}::text = $2::text`), true, keep)
512
+ }, options.query);
513
+ }
514
+ const AUTHZ_VERSION_TABLE = "permdock_authz_version";
515
+ /**
516
+ * The default schema of everything PermDock generates: helpers, seeds, the
517
+ * RBAC scaffold, the hook and the version table. Keep it out of the Data
518
+ * API's exposed schemas, so the `security definer` functions are not RPCs.
519
+ */
520
+ const PERMDOCK_SCHEMA = "permdock";
521
+ /**
522
+ * Reads the authorization version `permdock supabase hook generate` keeps in
523
+ * `<schema>.permdock_authz_version`: pass it to `claimsFirst(sources, { version })`.
524
+ */
525
+ function authzVersion(options) {
526
+ const table = qualified(`${options.schema ?? "permdock"}.${AUTHZ_VERSION_TABLE}`);
527
+ return async (principal) => {
528
+ const value = rowsOf(await options.query(`select version from ${table} where user_id = $1`, [principal.id]))[0]?.["version"];
529
+ const version = typeof value === "number" ? value : value === void 0 ? 0 : Number(value);
530
+ return Number.isFinite(version) ? version : void 0;
531
+ };
532
+ }
533
+ //#endregion
534
+ export { fromSupabasePostgres as a, roleManifest as c, fromJunction as i, keptKeys as l, PERMDOCK_SCHEMA as n, fromTable as o, authzVersion as r, roleColumn as s, AUTHZ_VERSION_TABLE as t };