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,371 @@
1
+ import { t as compact } from "./compact-y6vfu2_f.js";
2
+ import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
3
+ import { i as flattenApprovers } from "./approvers-DT4AVyIg.js";
4
+ import { s as rootMembershipId } from "./scopes-CVdPrWN-.js";
5
+ import { t as parseDuration } from "./duration-xK2jGFVc.js";
6
+ import { d as matchGrantee } from "./grantee-Cv5Sogfv.js";
7
+ import { t as ApprovalError } from "./errors-DRnGZHzF.js";
8
+ //#region src/approvals/types.ts
9
+ const APPROVAL_HEADER = "PermDock-Approval";
10
+ const DEFAULT_APPROVAL_TTL_MS = 36e5;
11
+ /** The approvals a request needs in total: `approvers.quorum` (or 1), or the sum of its stages' quorums. */
12
+ function approvalQuorum(request) {
13
+ const stages = request.approvers?.stages;
14
+ if (stages !== void 0) return stages.reduce((sum, stage) => sum + (stage.quorum ?? 1), 0);
15
+ return request.approvers?.quorum ?? 1;
16
+ }
17
+ /**
18
+ * The instant from which `approvers.escalation.to` may approve, in epoch
19
+ * milliseconds, or `undefined` when the request has no escalation or its
20
+ * `after` does not parse (then nobody escalates: fail-closed).
21
+ */
22
+ function escalationOpenAt(request) {
23
+ const after = request.approvers?.escalation?.after;
24
+ const seconds = parseDuration(after);
25
+ if (seconds === void 0) return;
26
+ return Date.parse(request.createdAt) + seconds * 1e3;
27
+ }
28
+ /** The instant from which a stage's own `escalation.to` may approve it, in epoch milliseconds; `undefined` when it has none or `after` does not parse. */
29
+ function stageEscalationOpenAt(request, stage) {
30
+ const seconds = parseDuration(stage.escalation?.after);
31
+ if (seconds === void 0) return;
32
+ return Date.parse(request.createdAt) + seconds * 1e3;
33
+ }
34
+ /** The key a verdict's `relations` lists a relation approver under. */
35
+ function approverRelationKey(item) {
36
+ return JSON.stringify([
37
+ item.resource,
38
+ item.relation,
39
+ item.through ?? null,
40
+ item.depth ?? null
41
+ ]);
42
+ }
43
+ //#endregion
44
+ //#region src/approvals/page.ts
45
+ const DEFAULT_PAGE_SIZE = 50;
46
+ const MAX_PAGE_SIZE = 200;
47
+ const MAX_PAGES = 1e3;
48
+ /** The page size of a query: `limit` within 1 to 200, 50 when absent. */
49
+ function approvalPageSize(limit) {
50
+ if (limit === void 0 || !Number.isFinite(limit)) return DEFAULT_PAGE_SIZE;
51
+ return Math.min(Math.max(Math.trunc(limit), 1), MAX_PAGE_SIZE);
52
+ }
53
+ function positionOf(request) {
54
+ return [request.createdAt, request.token];
55
+ }
56
+ function compare(a, b) {
57
+ if (a[0] !== b[0]) return a[0] < b[0] ? -1 : 1;
58
+ if (a[1] === b[1]) return 0;
59
+ return a[1] < b[1] ? -1 : 1;
60
+ }
61
+ /** The `next` cursor after `request`, for a store that pages in its own query. */
62
+ function encodeApprovalCursor(request) {
63
+ return JSON.stringify(positionOf(request));
64
+ }
65
+ /** The `(createdAt, token)` position a `next` cursor names, or `null` for one that does not parse. */
66
+ function decodeApprovalCursor(cursor) {
67
+ try {
68
+ const parsed = JSON.parse(cursor);
69
+ return Array.isArray(parsed) && parsed.length === 2 && typeof parsed[0] === "string" && typeof parsed[1] === "string" ? [parsed[0], parsed[1]] : null;
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * Pages already-filtered requests in `(createdAt, token)` order, as the
76
+ * built-in stores do: `limit` within 1 to 200 (50 when absent), `cursor` from
77
+ * the previous page's `next`, and no items for a cursor that does not parse.
78
+ * A custom `ApprovalStore` that filters in memory returns it from `list`.
79
+ */
80
+ function pageApprovals(matching, query) {
81
+ const after = query.cursor === void 0 ? void 0 : decodeApprovalCursor(query.cursor);
82
+ if (after === null) return { items: [] };
83
+ const sorted = matching.filter((request) => after === void 0 || compare(positionOf(request), after) > 0).toSorted((a, b) => compare(positionOf(a), positionOf(b)));
84
+ const size = approvalPageSize(query.limit);
85
+ const items = sorted.slice(0, size);
86
+ const last = items.at(-1);
87
+ return sorted.length > size && last !== void 0 ? {
88
+ items,
89
+ next: encodeApprovalCursor(last)
90
+ } : { items };
91
+ }
92
+ /** Every matching request of `store`, following `next` until the last page (at most 1000 pages of 200). */
93
+ function listAllApprovals(store, filter) {
94
+ const collect = async (cursor, pages, items) => {
95
+ const page = await store.list(cursor === void 0 ? {
96
+ ...filter,
97
+ limit: MAX_PAGE_SIZE
98
+ } : {
99
+ ...filter,
100
+ limit: MAX_PAGE_SIZE,
101
+ cursor
102
+ });
103
+ const next = [...items, ...page.items];
104
+ return page.next === void 0 || pages + 1 >= MAX_PAGES ? next : collect(page.next, pages + 1, next);
105
+ };
106
+ return collect(void 0, 0, []);
107
+ }
108
+ //#endregion
109
+ //#region src/approvals/store.ts
110
+ function tenantOf(request) {
111
+ return request.subject.principal?.tenant;
112
+ }
113
+ function membershipTenants(subject) {
114
+ const principal = subject.principal;
115
+ if (principal === null) return [];
116
+ const tenants = /* @__PURE__ */ new Set();
117
+ if (principal.tenant !== void 0) tenants.add(principal.tenant);
118
+ for (const membership of principal.memberships ?? []) {
119
+ const tenant = rootMembershipId(membership);
120
+ if (tenant !== void 0) tenants.add(tenant);
121
+ }
122
+ return [...tenants];
123
+ }
124
+ function belongsToTenant(subject, tenant) {
125
+ return membershipTenants(subject).includes(tenant);
126
+ }
127
+ function holdsRole(subject, role, tenant) {
128
+ const principal = subject.principal;
129
+ if (principal === null) return false;
130
+ if ((principal.roles ?? []).includes(role)) return true;
131
+ for (const membership of principal.memberships ?? []) {
132
+ if (!membership.roles.includes(role)) continue;
133
+ if (tenant !== void 0 && rootMembershipId(membership) !== tenant) continue;
134
+ return true;
135
+ }
136
+ return false;
137
+ }
138
+ function matchesApprovers(by, subject, tenant, now, facts) {
139
+ const items = flattenApprovers(by);
140
+ if (items.length === 0) return false;
141
+ for (const item of items) {
142
+ if (item.kind === "any-of") {
143
+ if (!item.of.some((entry) => matchesApprovers(entry, subject, tenant, now, facts))) return false;
144
+ continue;
145
+ }
146
+ if (item.kind === "permission") {
147
+ if (!facts.permissions.has(item.permission)) return false;
148
+ continue;
149
+ }
150
+ if (item.kind === "role") {
151
+ if (!holdsRole(subject, item.role, tenant)) return false;
152
+ continue;
153
+ }
154
+ if (item.kind === "user") {
155
+ if (subject.principal?.id !== item.id) return false;
156
+ continue;
157
+ }
158
+ if (item.kind === "relation") {
159
+ if (!facts.relations.has(approverRelationKey(item))) return false;
160
+ continue;
161
+ }
162
+ const result = matchGrantee(item, subject, now, void 0);
163
+ if (!result.matched || result.where !== void 0) return false;
164
+ }
165
+ return true;
166
+ }
167
+ /** Approvals recorded per stage index. */
168
+ function stageCounts(approvals, stages) {
169
+ const counts = stages.map(() => 0);
170
+ for (const item of approvals ?? []) if (item.stage !== void 0 && item.stage < counts.length) counts[item.stage] = (counts[item.stage] ?? 0) + 1;
171
+ return counts;
172
+ }
173
+ function isComplete(request, approvals) {
174
+ const stages = request.approvers?.stages;
175
+ if (stages === void 0) return approvals.length >= approvalQuorum(request);
176
+ const counts = stageCounts(approvals, stages);
177
+ return stages.every((stage, index) => (counts[index] ?? 0) >= (stage.quorum ?? 1));
178
+ }
179
+ function matchesFilter(request, filter) {
180
+ if (filter.status !== void 0 && request.status !== filter.status) return false;
181
+ if (filter.principalId !== void 0 && request.subject.principal?.id !== filter.principalId) return false;
182
+ if (filter.actorId !== void 0 && request.subject.actor?.id !== filter.actorId) return false;
183
+ if (filter.tenant !== void 0 && tenantOf(request) !== filter.tenant) return false;
184
+ if (filter.session !== void 0 && request.subject.session !== filter.session) return false;
185
+ return true;
186
+ }
187
+ function assertSeparateApprover(request, by, requireDistinctApprover) {
188
+ const principal = by.principal;
189
+ if (principal === null) throw new ApprovalError("approver-unauthenticated", "approver must be authenticated");
190
+ if (request.subject.actor !== void 0 && principal.id === request.subject.actor.id) throw new ApprovalError("approver-is-actor", "approver is the actor of this request");
191
+ if ((requireDistinctApprover || request.approvers?.distinct !== false) && request.subject.principal !== null && principal.id === request.subject.principal.id) throw new ApprovalError("approver-is-principal", "approver is the principal of this request");
192
+ return principal;
193
+ }
194
+ function assertNotRepeated(request, id) {
195
+ if ((request.approvals ?? []).some((item) => item.by === id)) throw new ApprovalError("approver-repeated", "approver has already approved this request");
196
+ }
197
+ function vouchedRule(verdict) {
198
+ return typeof verdict.vouched === "string" && verdict.vouched !== "" ? verdict.vouched : void 0;
199
+ }
200
+ /**
201
+ * Refuses `by` as an approver of `request`, or returns the index of the
202
+ * stage the approval counts for (`undefined` without `stages`). Eligibility
203
+ * is `approvers.by` or, under `stages`, the first incomplete stage
204
+ * (`sequential`) or any incomplete stage (`all`); `approvers.escalation.to`
205
+ * is eligible too once the request has waited `escalation.after`. A
206
+ * principal who already approved is refused, so one person never completes
207
+ * two stages. `relations` are the relation approvers `by` holds on the
208
+ * request's resource (see `ApprovalVerdict.relations`).
209
+ */
210
+ function assertApprover(request, by, requireDistinctApprover, now = /* @__PURE__ */ new Date(), relations = [], permissions = []) {
211
+ const principal = assertSeparateApprover(request, by, requireDistinctApprover);
212
+ const tenant = request.subject.principal?.tenant;
213
+ if (tenant !== void 0 && !belongsToTenant(by, tenant)) throw new ApprovalError("approver-not-eligible", "approver does not belong to the request tenant");
214
+ assertNotRepeated(request, principal.id);
215
+ const approvers = request.approvers;
216
+ if (approvers === void 0) return;
217
+ const facts = {
218
+ relations: new Set(relations),
219
+ permissions: new Set(permissions)
220
+ };
221
+ const instant = now.getTime() / 1e3;
222
+ const eligible = (target) => matchesApprovers(target, by, tenant, instant, facts);
223
+ const stageEscalated = (stage) => {
224
+ const openAt = stageEscalationOpenAt(request, stage);
225
+ return stage.escalation !== void 0 && openAt !== void 0 && now.getTime() >= openAt && eligible(stage.escalation.to);
226
+ };
227
+ const openAt = escalationOpenAt(request);
228
+ const escalated = approvers.escalation !== void 0 && openAt !== void 0 && now.getTime() >= openAt && eligible(approvers.escalation.to);
229
+ const stages = approvers.stages;
230
+ if (stages === void 0) {
231
+ if (escalated || approvers.by !== void 0 && eligible(approvers.by)) return;
232
+ throw new ApprovalError("approver-not-eligible", "approver does not hold an eligible role");
233
+ }
234
+ const counts = stageCounts(request.approvals, stages);
235
+ const open = stages.flatMap((stage, index) => (counts[index] ?? 0) < (stage.quorum ?? 1) ? [index] : []);
236
+ const candidates = approvers.mode === "sequential" ? open.slice(0, 1) : open;
237
+ for (const index of candidates) {
238
+ const stage = stages[index];
239
+ if (stage !== void 0 && (escalated || eligible(stage.by) || stageEscalated(stage))) return index;
240
+ }
241
+ throw new ApprovalError("approver-not-eligible", approvers.mode === "sequential" ? "approver is not eligible for the current stage" : "approver is not eligible for an open stage");
242
+ }
243
+ function isSystemSubject(by) {
244
+ return by.actor?.kind === "system";
245
+ }
246
+ /**
247
+ * The request after `verdict`, for a store to persist: a rejection resolves
248
+ * it; an approval is appended to `approvals` and resolves it once there are
249
+ * `approvers.quorum` (default 1). Throws an `ApprovalError` when the request
250
+ * is not pending, has expired or `verdict.by` may not approve it. Stores
251
+ * should write the result only when the stored row is still pending with the
252
+ * same number of approvals, so two approvers racing both count.
253
+ */
254
+ function applyApprovalVerdict(request, verdict, now = /* @__PURE__ */ new Date()) {
255
+ const principal = verdict.by.principal;
256
+ if (principal === null) throw new ApprovalError("approver-unauthenticated", "approver must be authenticated");
257
+ if (request.status !== "pending") throw new ApprovalError("approval-not-pending", "approval is not pending");
258
+ if (Date.parse(request.expiresAt) <= now.getTime()) throw new ApprovalError("approval-expired", "approval has expired");
259
+ const vouched = vouchedRule(verdict);
260
+ const stage = verdict.status === "rejected" && isSystemSubject(verdict.by) || vouched !== void 0 ? void 0 : assertApprover(request, verdict.by, false, now, verdict.relations, verdict.permissions);
261
+ if (vouched !== void 0) assertNotRepeated(request, assertSeparateApprover(request, verdict.by, false).id);
262
+ if (verdict.status === "rejected") return freezeDeep(compact({
263
+ ...request,
264
+ status: "rejected",
265
+ resolvedAt: now.toISOString(),
266
+ resolvedBy: principal.id,
267
+ vouched,
268
+ note: verdict.note ?? request.note
269
+ }));
270
+ const approvals = [...request.approvals ?? [], compact({
271
+ by: principal.id,
272
+ at: now.toISOString(),
273
+ stage,
274
+ vouched
275
+ })];
276
+ if (vouched === void 0 && !isComplete(request, approvals)) return freezeDeep(compact({
277
+ ...request,
278
+ approvals,
279
+ note: verdict.note ?? request.note
280
+ }));
281
+ return freezeDeep(compact({
282
+ ...request,
283
+ status: "approved",
284
+ approvals,
285
+ resolvedAt: now.toISOString(),
286
+ resolvedBy: principal.id,
287
+ vouched,
288
+ note: verdict.note ?? request.note
289
+ }));
290
+ }
291
+ function rejectPending(request, meta, now) {
292
+ return freezeDeep(compact({
293
+ ...request,
294
+ status: "rejected",
295
+ resolvedAt: now.toISOString(),
296
+ resolvedBy: `system:${meta.by}`,
297
+ note: meta.note
298
+ }));
299
+ }
300
+ /** A request a new ask may replace: expired, or past its deadline. */
301
+ function isStale(request, now) {
302
+ return request.status === "expired" || Date.parse(request.expiresAt) <= now.getTime();
303
+ }
304
+ function memoryApprovalStore(options = {}) {
305
+ const ttl = options.ttl ?? 36e5;
306
+ const records = /* @__PURE__ */ new Map();
307
+ return {
308
+ ttl,
309
+ create(request) {
310
+ const current = records.get(request.token);
311
+ if (current !== void 0 && !isStale(current, /* @__PURE__ */ new Date())) return;
312
+ records.set(request.token, freezeDeep(request));
313
+ },
314
+ get(token) {
315
+ return records.get(token) ?? null;
316
+ },
317
+ resolve(token, verdict) {
318
+ const current = records.get(token);
319
+ if (current === void 0) throw new ApprovalError("approval-not-found", "approval was not found");
320
+ const next = applyApprovalVerdict(current, verdict, /* @__PURE__ */ new Date());
321
+ records.set(token, next);
322
+ return next;
323
+ },
324
+ consume(token, now = /* @__PURE__ */ new Date()) {
325
+ const current = records.get(token);
326
+ if (current?.status !== "approved" || current.consumedAt !== void 0 || Date.parse(current.expiresAt) <= now.getTime()) return null;
327
+ const next = freezeDeep({
328
+ ...current,
329
+ consumedAt: now.toISOString()
330
+ });
331
+ records.set(token, next);
332
+ return next;
333
+ },
334
+ list(query) {
335
+ const matching = [];
336
+ for (const request of records.values()) if (matchesFilter(request, query)) matching.push(request);
337
+ return pageApprovals(matching, query);
338
+ },
339
+ expire(now = /* @__PURE__ */ new Date()) {
340
+ let count = 0;
341
+ const instant = now.getTime();
342
+ for (const [token, request] of records) {
343
+ const deadline = Date.parse(request.expiresAt);
344
+ if (request.status !== "pending" && deadline + ttl <= instant) {
345
+ records.delete(token);
346
+ continue;
347
+ }
348
+ if (request.status === "pending" && deadline <= instant) {
349
+ records.set(token, freezeDeep(compact({
350
+ ...request,
351
+ status: "expired"
352
+ })));
353
+ count += 1;
354
+ }
355
+ }
356
+ return count;
357
+ },
358
+ cancel(filter, meta) {
359
+ const now = /* @__PURE__ */ new Date();
360
+ let count = 0;
361
+ for (const [token, request] of records) {
362
+ if (request.status !== "pending" || !matchesFilter(request, filter)) continue;
363
+ records.set(token, rejectPending(request, meta, now));
364
+ count += 1;
365
+ }
366
+ return count;
367
+ }
368
+ };
369
+ }
370
+ //#endregion
371
+ export { decodeApprovalCursor as a, pageApprovals as c, approvalQuorum as d, approverRelationKey as f, approvalPageSize as i, APPROVAL_HEADER as l, assertApprover as n, encodeApprovalCursor as o, escalationOpenAt as p, memoryApprovalStore as r, listAllApprovals as s, applyApprovalVerdict as t, DEFAULT_APPROVAL_TTL_MS as u };
@@ -0,0 +1,36 @@
1
+ import { Tt as Snapshot, Yn as Decision } from "./policy-CFZAr_Al.js";
2
+ import { f as Permission } from "./permissions-DttnqqxC.js";
3
+ import { n as ApprovalState, r as ClientPermDock, s as PermissionState } from "./types-kxznc7cn.js";
4
+ //#region src/client/store.d.ts
5
+ type ClientStore = {
6
+ get(): ClientPermDock;
7
+ subscribe(listener: () => void): () => void;
8
+ permissionState(permission: Permission, data?: unknown): PermissionState;
9
+ requestApproval(decision: Decision, note?: string): Promise<void>;
10
+ /** Hydrate from a pushed snapshot; a compact JWS goes through the verifier. */
11
+ replace(value: unknown): void;
12
+ /** Stay `pending` until `value` settles, then hydrate; a rejection fails closed. */
13
+ follow(value: PromiseLike<Snapshot | string>): void;
14
+ /**
15
+ * `follow()` once per `value`, without suspending. A thenable React already
16
+ * settled (`status: 'fulfilled'`) hydrates at once.
17
+ */
18
+ track(value: PromiseLike<Snapshot | string>): void;
19
+ /**
20
+ * The approval state for a decision. While something subscribes, an
21
+ * `approval-required` decision is polled at `<approvals>/<token>`.
22
+ */
23
+ approvalState(decision: Decision): ApprovalState;
24
+ /**
25
+ * Hydrate from a resolved `snapshotPromise` during render. Idempotent per `source`;
26
+ * subscribers are notified in a microtask, never synchronously inside render.
27
+ */
28
+ adopt(value: Snapshot | string, source: object): void;
29
+ snapshot(): Snapshot;
30
+ /** The tenant the store currently answers for. */
31
+ tenant(): string | undefined;
32
+ /** Stops polls, drops in-flight results and persistence; the store keeps answering from its last snapshot. */
33
+ dispose(): void;
34
+ };
35
+ //#endregion
36
+ export { ClientStore as t };