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,91 @@
1
+ import { n as freezeDeep } from "./freeze-CrU8nQeX.js";
2
+ import { O as readPath, k as splitPath, w as assertSafeKey } from "./permissions-DVoF6dMt.js";
3
+ //#region src/conditions/ast.ts
4
+ function parentHop(parent) {
5
+ return typeof parent === "string" ? { field: parent } : parent;
6
+ }
7
+ function isConditionRef(value) {
8
+ return value !== null && typeof value === "object" && "ref" in value && typeof value.ref === "string";
9
+ }
10
+ function isConditionDate(value) {
11
+ return value !== null && typeof value === "object" && "date" in value && typeof value.date === "string" && !("ref" in value);
12
+ }
13
+ function isCondition(value) {
14
+ return value !== null && typeof value === "object" && "op" in value && typeof value.op === "string";
15
+ }
16
+ function isSqlFunctionField(value) {
17
+ return value !== null && typeof value === "object" && "field" in value && typeof value.field === "string" && !("ref" in value) && !("date" in value) && !("op" in value);
18
+ }
19
+ function hasConditionOp(condition, op) {
20
+ if (condition === void 0) return false;
21
+ if (condition.op === op) return true;
22
+ switch (condition.op) {
23
+ case "and":
24
+ case "or": return condition.conditions.some((child) => hasConditionOp(child, op));
25
+ case "not": return hasConditionOp(condition.condition, op);
26
+ case "sqlFunction": return hasConditionOp(condition.twin, op);
27
+ case "eq":
28
+ case "ne":
29
+ case "gt":
30
+ case "gte":
31
+ case "lt":
32
+ case "lte":
33
+ case "contains":
34
+ case "in":
35
+ case "notIn":
36
+ case "isNull":
37
+ case "memberOf":
38
+ case "related":
39
+ case "opaque":
40
+ case "liveSession": return false;
41
+ default:
42
+ /* v8 ignore next */
43
+ return condition;
44
+ }
45
+ }
46
+ //#endregion
47
+ //#region src/conditions/refs.ts
48
+ const REF_BRAND = Symbol.for("permdock.ref");
49
+ function createRef(path) {
50
+ const segments = splitPath(path);
51
+ for (const segment of segments) assertSafeKey(segment, "subject path");
52
+ const target = freezeDeep({ ref: path });
53
+ return new Proxy(target, {
54
+ get(object, property, receiver) {
55
+ if (property === "ref" || property === REF_BRAND) return Reflect.get(object, property === REF_BRAND ? "ref" : property, receiver);
56
+ if (property === "toJSON" || property === "valueOf" || property === Symbol.toStringTag) return;
57
+ if (typeof property !== "string") return;
58
+ assertSafeKey(property, "subject path");
59
+ return createRef(`${path}.${property}`);
60
+ },
61
+ getOwnPropertyDescriptor(object, property) {
62
+ if (property === "ref") return Reflect.getOwnPropertyDescriptor(object, property);
63
+ },
64
+ ownKeys() {
65
+ return ["ref"];
66
+ }
67
+ });
68
+ }
69
+ const principal = createRef("principal");
70
+ const context = createRef("context");
71
+ function isSubjectRef(value) {
72
+ if (value === null || typeof value !== "object" || !("ref" in value) || typeof value.ref !== "string") return false;
73
+ const ref = value.ref;
74
+ return ref === "principal" || ref.startsWith("principal.") || ref === "context" || ref.startsWith("context.");
75
+ }
76
+ function resolveConditionRef(ref, resolved) {
77
+ if (resolved === void 0) return;
78
+ if (ref === "principal" || ref.startsWith("principal.")) {
79
+ const path = ref === "principal" ? "" : ref.slice(10);
80
+ if (path === "") return resolved.principal;
81
+ if (resolved.principal === null) return;
82
+ return readPath(resolved.principal, path);
83
+ }
84
+ if (ref === "context" || ref.startsWith("context.")) {
85
+ const path = ref === "context" ? "" : ref.slice(8);
86
+ if (path === "") return resolved.context;
87
+ return readPath(resolved.context, path);
88
+ }
89
+ }
90
+ //#endregion
91
+ export { hasConditionOp as a, isConditionRef as c, resolveConditionRef as i, isSqlFunctionField as l, isSubjectRef as n, isCondition as o, principal as r, isConditionDate as s, context as t, parentHop as u };
@@ -0,0 +1,505 @@
1
+ import { C as restrictedStops, E as ownGet, d as isEdgeRelation, l as groupEntries, m as isPrincipalRelation, r as expandRelation, s as getRegistry, u as isComputedRelation } from "./permissions-DVoF6dMt.js";
2
+ import { t as idText } from "./ids-DC4V4CFu.js";
3
+ import { n as isThenable } from "./thenable-okc2xDsj.js";
4
+ function isRecord(value) {
5
+ return value !== null && typeof value === "object" && !Array.isArray(value);
6
+ }
7
+ function isInstant(value) {
8
+ return value === void 0 || typeof value === "number" && Number.isFinite(value);
9
+ }
10
+ function asChain(value) {
11
+ if (!isRecord(value) || !Array.isArray(value["ancestors"])) return;
12
+ const ancestors = [];
13
+ for (const item of value["ancestors"]) {
14
+ if (!isRecord(item) || typeof item["id"] !== "string" || item["id"] === "") return;
15
+ ancestors.push(item["restricted"] === true ? {
16
+ id: item["id"],
17
+ restricted: true
18
+ } : { id: item["id"] });
19
+ }
20
+ return {
21
+ ancestors,
22
+ ...value["restricted"] === true ? { restricted: true } : {},
23
+ ...value["truncated"] === true ? { truncated: true } : {}
24
+ };
25
+ }
26
+ function asRow(value) {
27
+ if (value === null || value === void 0) return { row: null };
28
+ return isRecord(value) ? { row: value } : void 0;
29
+ }
30
+ function asGroup(value) {
31
+ if (!isRecord(value) || typeof value["resource"] !== "string" || typeof value["id"] !== "string" || typeof value["relation"] !== "string" || value["id"] === "") return;
32
+ return {
33
+ resource: value["resource"],
34
+ id: value["id"],
35
+ relation: value["relation"]
36
+ };
37
+ }
38
+ function asHolders(value) {
39
+ if (!Array.isArray(value)) return;
40
+ const holders = [];
41
+ for (const item of value) {
42
+ if (!isRecord(item) || !isInstant(item["startsAt"]) || !isInstant(item["expiresAt"])) return;
43
+ const period = {
44
+ ...item["startsAt"] === void 0 ? {} : { startsAt: item["startsAt"] },
45
+ ...item["expiresAt"] === void 0 ? {} : { expiresAt: item["expiresAt"] }
46
+ };
47
+ if (isRecord(item["principal"]) && typeof item["principal"]["id"] === "string") {
48
+ holders.push({
49
+ principal: { id: item["principal"]["id"] },
50
+ ...period
51
+ });
52
+ continue;
53
+ }
54
+ const group = asGroup(item["group"]);
55
+ if (group === void 0) return;
56
+ holders.push({
57
+ group,
58
+ ...period
59
+ });
60
+ }
61
+ return holders;
62
+ }
63
+ function read(cache, key, call, validate) {
64
+ const entry = cache.get(key);
65
+ if (entry !== void 0) return entry.state === "ready" ? entry.value : entry.state;
66
+ if (call === void 0) return "failed";
67
+ const settle = (value) => {
68
+ const valid = validate(value);
69
+ cache.set(key, valid === void 0 ? { state: "failed" } : {
70
+ state: "ready",
71
+ value: valid
72
+ });
73
+ };
74
+ let result;
75
+ try {
76
+ result = call();
77
+ } catch {
78
+ cache.set(key, { state: "failed" });
79
+ return "failed";
80
+ }
81
+ if (isThenable(result)) {
82
+ const promise = Promise.resolve(result).then(settle, () => {
83
+ cache.set(key, { state: "failed" });
84
+ });
85
+ cache.set(key, {
86
+ state: "pending",
87
+ promise
88
+ });
89
+ return "pending";
90
+ }
91
+ settle(result);
92
+ const settled = cache.get(key);
93
+ return settled?.state === "ready" ? settled.value : "failed";
94
+ }
95
+ function relationReader(source, cache, resources) {
96
+ const concrete = (resource, id, relation) => read(cache, JSON.stringify([
97
+ "holders",
98
+ resource,
99
+ id,
100
+ relation
101
+ ]), source === void 0 ? void 0 : () => source.related({
102
+ resource,
103
+ id,
104
+ relation
105
+ }), asHolders);
106
+ return {
107
+ available: source !== void 0,
108
+ row(query) {
109
+ const load = source?.row?.bind(source);
110
+ return read(cache, JSON.stringify([
111
+ "row",
112
+ query.resource,
113
+ query.id
114
+ ]), load === void 0 ? void 0 : () => load({
115
+ resource: query.resource,
116
+ id: query.id
117
+ }), asRow);
118
+ },
119
+ chain(query) {
120
+ const through = query.through ?? "parent";
121
+ return read(cache, JSON.stringify([
122
+ "chain",
123
+ query.resource,
124
+ query.id,
125
+ query.depth,
126
+ through
127
+ ]), source === void 0 ? void 0 : () => source.ancestors({
128
+ resource: query.resource,
129
+ id: query.id,
130
+ depth: query.depth,
131
+ through
132
+ }), asChain);
133
+ },
134
+ holders(query) {
135
+ const node = resources?.get(query.resource);
136
+ const names = node === void 0 ? [query.relation] : expandRelation(node, query.relation);
137
+ const out = [];
138
+ let unread;
139
+ for (const name of names) {
140
+ const answer = concrete(query.resource, query.id, name);
141
+ if (answer === "pending" || answer === "failed") {
142
+ unread = answer === "failed" || unread === "failed" ? "failed" : "pending";
143
+ continue;
144
+ }
145
+ for (const holder of answer) out.push({
146
+ ...holder,
147
+ relation: name
148
+ });
149
+ }
150
+ return unread ?? out;
151
+ }
152
+ };
153
+ }
154
+ /** The loads still in flight, for an instance that awaits them before deciding. */
155
+ function pendingRelations(cache) {
156
+ const out = [];
157
+ for (const entry of cache.values()) if (entry.state === "pending") out.push(entry.promise);
158
+ return out;
159
+ }
160
+ function relationId(value) {
161
+ return idText(value);
162
+ }
163
+ /** Whether the holder's period covers `now`. */
164
+ function activeNow(holder, now) {
165
+ return (holder.startsAt === void 0 || holder.startsAt <= now) && (holder.expiresAt === void 0 || holder.expiresAt > now);
166
+ }
167
+ function holdsNow(holder, principalId, now) {
168
+ return "principal" in holder && holder.principal.id === principalId && activeNow(holder, now);
169
+ }
170
+ /** Where the walk starts after following `hops`, or why it cannot. */
171
+ function followHops(condition, first, reader) {
172
+ const hops = condition.hops ?? [];
173
+ let id = first;
174
+ for (let index = 1; index < hops.length; index += 1) {
175
+ const from = hops[index - 1];
176
+ const hop = hops[index];
177
+ if (from === void 0 || hop === void 0)
178
+ /* v8 ignore next */
179
+ return;
180
+ const chain = reader.chain({
181
+ resource: from.resource,
182
+ id,
183
+ depth: 1,
184
+ through: hop.link
185
+ });
186
+ if (chain === "pending" || chain === "failed") return "relation-unavailable";
187
+ const next = chain.ancestors[0]?.id;
188
+ if (next === void 0) return;
189
+ id = next;
190
+ }
191
+ return { id };
192
+ }
193
+ function restrictedAbove(condition, row, reader) {
194
+ const above = condition.restrictedAncestors;
195
+ if (above === void 0) return false;
196
+ const parent = relationId(ownGet(row, above.parent));
197
+ if (parent === void 0) return false;
198
+ const chain = reader.chain({
199
+ resource: above.resource,
200
+ id: parent,
201
+ depth: above.depth - 1
202
+ });
203
+ if (chain === "pending" || chain === "failed") return "relation-unavailable";
204
+ if (chain.restricted === true || chain.ancestors.some((ancestor) => ancestor.restricted === true)) return;
205
+ const own = relationId(ownGet(row, above.id));
206
+ const ids = [
207
+ ...own === void 0 ? [] : [own],
208
+ parent,
209
+ ...chain.ancestors.map((ancestor) => ancestor.id)
210
+ ];
211
+ if (new Set(ids).size !== ids.length || chain.truncated === true || chain.ancestors.length > above.depth - 1) return "relation-depth";
212
+ return false;
213
+ }
214
+ /** The instances a graph relation reads: the start, then ancestors until a restricted one or `depth`. */
215
+ function relationWalk(condition, row, reader) {
216
+ if (!isRecord(row)) return;
217
+ const first = relationId(ownGet(row, condition.field));
218
+ if (first === void 0) return;
219
+ const rowRestricted = condition.restricted !== void 0 && ownGet(row, condition.restricted) === true;
220
+ const hopped = condition.hops !== void 0 && condition.hops.length > 0;
221
+ if ((condition.parent === true || hopped) && rowRestricted) return;
222
+ const above = restrictedAbove(condition, row, reader);
223
+ if (above !== false) return above;
224
+ const start = hopped ? followHops(condition, first, reader) : { id: first };
225
+ if (start === void 0 || start === "relation-unavailable") return start;
226
+ const id = start.id;
227
+ if (condition.depth === 0 || rowRestricted) return {
228
+ ids: [id],
229
+ truncated: false
230
+ };
231
+ const chain = reader.chain({
232
+ resource: condition.resource,
233
+ id,
234
+ depth: condition.depth
235
+ });
236
+ if (chain === "pending" || chain === "failed") return "relation-unavailable";
237
+ const ids = [id];
238
+ const stops = condition.passRestricted !== true;
239
+ let stopped = stops && chain.restricted === true;
240
+ if (!stopped) for (const ancestor of chain.ancestors.slice(0, condition.depth)) {
241
+ ids.push(ancestor.id);
242
+ if (stops && ancestor.restricted === true) {
243
+ stopped = true;
244
+ break;
245
+ }
246
+ }
247
+ if (new Set(ids).size !== ids.length) return "relation-depth";
248
+ return {
249
+ ids,
250
+ truncated: !stopped && (chain.ancestors.length > condition.depth || chain.truncated === true)
251
+ };
252
+ }
253
+ /**
254
+ * Whether the subject holds the relation on the row's instance or an
255
+ * ancestor within `depth`. A cycle is `relation-depth`; so is a chain that
256
+ * goes on past `depth` with no holder below it. Any read the instance could
257
+ * not answer is `relation-unavailable` unless a holder was found elsewhere.
258
+ */
259
+ function resolveRelated(condition, row, subject, now, reader, permitted) {
260
+ if (condition.permission !== void 0) return resolveInherited(condition, condition.permission, row, reader, permitted);
261
+ const principal = subject.principal;
262
+ if (principal === null) return false;
263
+ const walk = relationWalk(condition, row, reader);
264
+ if (walk === void 0) return false;
265
+ if (walk === "relation-depth" || walk === "relation-unavailable") return walk;
266
+ if (condition.ids !== void 0) {
267
+ const held = new Set(condition.ids);
268
+ if (walk.ids.some((id) => held.has(id))) return true;
269
+ return walk.truncated ? "relation-depth" : false;
270
+ }
271
+ let unavailable = false;
272
+ let deep = false;
273
+ const explored = /* @__PURE__ */ new Map();
274
+ for (const id of walk.ids) {
275
+ const verdict = holdsRelation({
276
+ resource: condition.resource,
277
+ id,
278
+ relation: condition.relation
279
+ }, principal.id, now, reader, 16, /* @__PURE__ */ new Set(), explored);
280
+ if (verdict === true) return true;
281
+ if (verdict === "relation-unavailable") unavailable = true;
282
+ else if (verdict === "relation-depth") deep = true;
283
+ }
284
+ if (unavailable) return "relation-unavailable";
285
+ return walk.truncated || deep ? "relation-depth" : false;
286
+ }
287
+ function resolveInherited(condition, permission, row, reader, permitted) {
288
+ const walk = relationWalk(condition, row, reader);
289
+ if (walk === void 0) return false;
290
+ if (walk === "relation-depth" || walk === "relation-unavailable") return walk;
291
+ if (permitted === void 0) return "relation-unavailable";
292
+ let unknown = false;
293
+ for (const id of walk.ids) {
294
+ const verdict = permitted(condition.resource, id, permission);
295
+ if (verdict === true) return true;
296
+ if (verdict !== false && unknown === false) unknown = verdict;
297
+ }
298
+ return unknown;
299
+ }
300
+ function groupKey(group) {
301
+ return JSON.stringify([
302
+ group.resource,
303
+ group.id,
304
+ group.relation
305
+ ]);
306
+ }
307
+ /**
308
+ * Whether the principal holds `at.relation` on one instance, directly or
309
+ * through a group whose members hold it. Groups of `at`'s own resource nest
310
+ * at most `budget` deep; a group of another resource gets a fresh budget
311
+ * (declarations rule out cycles across resources). A group met twice on one
312
+ * path, or one past the budget, is `relation-depth`. `explored` holds the
313
+ * budget each group was walked with across the whole walk: a group already
314
+ * walked with as much budget adds nothing, since its verdict already reached
315
+ * the caller, so shared sub-groups cost one walk rather than one per path.
316
+ */
317
+ function holdsRelation(at, principalId, now, reader, budget, seen, explored) {
318
+ const key = groupKey(at);
319
+ const walked = explored.get(key);
320
+ if (walked !== void 0 && walked >= budget) return false;
321
+ explored.set(key, budget);
322
+ const holders = reader.holders(at);
323
+ if (holders === "pending" || holders === "failed") return "relation-unavailable";
324
+ if (holders.some((holder) => holdsNow(holder, principalId, now))) return true;
325
+ const path = new Set(seen).add(key);
326
+ let unavailable = false;
327
+ let deep = false;
328
+ for (const holder of holders) {
329
+ if (!("group" in holder) || !activeNow(holder, now)) continue;
330
+ const nested = holder.group.resource === at.resource;
331
+ if (nested && budget <= 0 || path.has(groupKey(holder.group))) {
332
+ deep = true;
333
+ continue;
334
+ }
335
+ const verdict = holdsRelation(holder.group, principalId, now, reader, nested ? budget - 1 : 16, path, explored);
336
+ if (verdict === true) return true;
337
+ if (verdict === "relation-unavailable") unavailable = true;
338
+ else if (verdict === "relation-depth") deep = true;
339
+ }
340
+ if (unavailable) return "relation-unavailable";
341
+ return deep ? "relation-depth" : false;
342
+ }
343
+ /** The holders one edge-table row names for `spec`: none when the row does not belong to it. */
344
+ function tableHolders(resourceName, spec, row, id) {
345
+ if (relationId(ownGet(row, spec.object ?? `${resourceName}_id`)) !== id) return [];
346
+ for (const [column, value] of Object.entries(spec.match ?? {})) if (ownGet(row, column) !== value) return [];
347
+ const expiresAt = spec.expiresAt === void 0 ? void 0 : seconds(ownGet(row, spec.expiresAt));
348
+ const period = expiresAt === void 0 ? {} : { expiresAt };
349
+ const groups = spec.groups;
350
+ const direct = relationId(ownGet(row, spec.subject ?? "user_id"));
351
+ if (groups === void 0) return direct === void 0 ? [] : [{
352
+ principal: { id: direct },
353
+ ...period
354
+ }];
355
+ if (groups.column === void 0) {
356
+ const out = direct === void 0 ? [] : [{
357
+ principal: { id: direct },
358
+ ...period
359
+ }];
360
+ for (const group of groupEntries(spec)) {
361
+ const groupId = relationId(ownGet(row, group.subject));
362
+ if (groupId !== void 0) out.push({
363
+ group: {
364
+ resource: group.resource,
365
+ id: groupId,
366
+ relation: group.relation
367
+ },
368
+ ...period
369
+ });
370
+ }
371
+ return out;
372
+ }
373
+ const kind = ownGet(row, groups.column);
374
+ if (kind === null || kind === void 0 || kind === groups.direct) return direct === void 0 ? [] : [{
375
+ principal: { id: direct },
376
+ ...period
377
+ }];
378
+ const group = groupEntries(spec).find((entry) => entry.resource === kind);
379
+ const groupId = group === void 0 ? void 0 : relationId(ownGet(row, group.subject));
380
+ return group === void 0 || groupId === void 0 ? [] : [{
381
+ group: {
382
+ resource: group.resource,
383
+ id: groupId,
384
+ relation: group.relation
385
+ },
386
+ ...period
387
+ }];
388
+ }
389
+ function seconds(value) {
390
+ if (value instanceof Date) {
391
+ const time = value.getTime();
392
+ return Number.isNaN(time) ? void 0 : time / 1e3;
393
+ }
394
+ if (typeof value === "number" && Number.isFinite(value)) return value;
395
+ if (typeof value === "string") {
396
+ const parsed = Date.parse(value);
397
+ return Number.isNaN(parsed) ? void 0 : parsed / 1e3;
398
+ }
399
+ }
400
+ function restrictedOf(node, row) {
401
+ return node.restricted !== void 0 && row !== void 0 && ownGet(row, node.restricted) === true;
402
+ }
403
+ function edgeHolder(edge) {
404
+ const holder = { principal: { id: edge.principal } };
405
+ if (edge.startsAt !== void 0) holder.startsAt = edge.startsAt;
406
+ if (edge.expiresAt !== void 0) holder.expiresAt = edge.expiresAt;
407
+ return holder;
408
+ }
409
+ /**
410
+ * An in-process `RelationSource` over plain rows and edges, read against the
411
+ * resource definitions in `permissions`. For tests, fixtures and small apps.
412
+ */
413
+ function memoryRelations(permissions, data = {}) {
414
+ const registry = getRegistry(permissions);
415
+ const byId = /* @__PURE__ */ new Map();
416
+ for (const [name, rows] of Object.entries(data.rows ?? {})) {
417
+ const node = registry.get(name);
418
+ const index = /* @__PURE__ */ new Map();
419
+ for (const row of rows) {
420
+ const id = relationId(ownGet(row, node?.id ?? "id"));
421
+ if (id !== void 0) index.set(id, row);
422
+ }
423
+ byId.set(name, index);
424
+ }
425
+ const rowOf = (resource, id) => byId.get(resource)?.get(id);
426
+ return {
427
+ row({ resource, id }) {
428
+ return rowOf(resource, id) ?? null;
429
+ },
430
+ ancestors({ resource, id, depth, through }) {
431
+ const node = registry.get(resource);
432
+ const start = rowOf(resource, id);
433
+ if (node === void 0 || start === void 0) return { ancestors: [] };
434
+ if (through !== "parent") {
435
+ const link = Object.hasOwn(node.links, through) ? node.links[through] : void 0;
436
+ const next = link === void 0 ? void 0 : relationId(ownGet(start, link.field));
437
+ if (next === void 0 || depth < 1) return { ancestors: [] };
438
+ return { ancestors: [{ id: next }] };
439
+ }
440
+ const restricted = restrictedOf(node, start);
441
+ const stops = restrictedStops(node, "parent");
442
+ if (restricted && stops || node.parent === void 0 || node.parent.resource !== resource) return restricted ? {
443
+ restricted: true,
444
+ ancestors: []
445
+ } : { ancestors: [] };
446
+ const field = node.parent.field;
447
+ const seen = /* @__PURE__ */ new Set([id]);
448
+ const ancestors = [];
449
+ let next = relationId(ownGet(start, field));
450
+ while (next !== void 0 && ancestors.length < depth) {
451
+ const row = rowOf(resource, next);
452
+ if (row === void 0) {
453
+ next = void 0;
454
+ break;
455
+ }
456
+ const hidden = restrictedOf(node, row);
457
+ ancestors.push(hidden ? {
458
+ id: next,
459
+ restricted: true
460
+ } : { id: next });
461
+ if (seen.has(next) || hidden && stops) {
462
+ next = void 0;
463
+ break;
464
+ }
465
+ seen.add(next);
466
+ next = relationId(ownGet(row, field));
467
+ }
468
+ const chain = restricted ? {
469
+ restricted: true,
470
+ ancestors
471
+ } : { ancestors };
472
+ return next === void 0 || rowOf(resource, next) === void 0 ? chain : {
473
+ ...chain,
474
+ truncated: true
475
+ };
476
+ },
477
+ related({ resource, id, relation }) {
478
+ const spec = registry.get(resource)?.relations[relation];
479
+ if (spec === void 0 || isComputedRelation(spec)) return [];
480
+ if (isEdgeRelation(spec)) {
481
+ const table = data.tables?.[spec.edge];
482
+ if (table !== void 0) return table.flatMap((row) => tableHolders(resource, spec, row, id));
483
+ return (data.edges?.[resource]?.[relation] ?? []).filter((edge) => edge.id === id).map(edgeHolder);
484
+ }
485
+ const row = rowOf(resource, id);
486
+ if (row === void 0) return [];
487
+ if (isPrincipalRelation(spec)) {
488
+ const holder = relationId(ownGet(row, spec.principal));
489
+ if (holder === void 0) return [];
490
+ const startsAt = spec.period?.startsAt === void 0 ? void 0 : seconds(ownGet(row, spec.period.startsAt));
491
+ const expiresAt = spec.period?.expiresAt === void 0 ? void 0 : seconds(ownGet(row, spec.period.expiresAt));
492
+ return [{
493
+ principal: { id: holder },
494
+ ...startsAt === void 0 ? {} : { startsAt },
495
+ ...expiresAt === void 0 ? {} : { expiresAt }
496
+ }];
497
+ }
498
+ if (spec.memberOf !== void 0) return [];
499
+ const holder = relationId(ownGet(row, spec.field));
500
+ return holder === void 0 ? [] : [{ principal: { id: holder } }];
501
+ }
502
+ };
503
+ }
504
+ //#endregion
505
+ export { relationWalk as a, relationReader as i, pendingRelations as n, resolveRelated as o, relationId as r, memoryRelations as t };
@@ -0,0 +1,28 @@
1
+ //#region src/ssf/replay.ts
2
+ function memoryReplayStore() {
3
+ const seen = /* @__PURE__ */ new Map();
4
+ function evict(now = Date.now() / 1e3) {
5
+ for (const [jti, expiresAt] of seen) if (expiresAt !== void 0 && expiresAt <= now) seen.delete(jti);
6
+ }
7
+ return {
8
+ seen(jti) {
9
+ evict();
10
+ return seen.has(jti);
11
+ },
12
+ remember(jti, expiresAt) {
13
+ evict();
14
+ seen.set(jti, expiresAt);
15
+ },
16
+ claim(key, expiresAt) {
17
+ evict();
18
+ if (seen.has(key)) return false;
19
+ seen.set(key, expiresAt);
20
+ return true;
21
+ },
22
+ release(key) {
23
+ seen.delete(key);
24
+ }
25
+ };
26
+ }
27
+ //#endregion
28
+ export { memoryReplayStore as t };
@@ -0,0 +1,5 @@
1
+ import { g as ReplayStore } from "./types-9AWO9EGt.js";
2
+ //#region src/ssf/replay.d.ts
3
+ declare function memoryReplayStore(): ReplayStore;
4
+ //#endregion
5
+ export { memoryReplayStore as t };
@@ -0,0 +1,20 @@
1
+ //#region src/core/resource-ref.ts
2
+ /** The row's `id` as a string, when it is a string or a number. */
3
+ function resourceIdOf(data) {
4
+ if (data === null || typeof data !== "object" || !("id" in data)) return;
5
+ const id = data.id;
6
+ return typeof id === "string" || typeof id === "number" ? String(id) : void 0;
7
+ }
8
+ /**
9
+ * The `resource` of a decision event: the permission's resource type and the
10
+ * row's `id`, or `wireId` (the id the request named) when the row has none.
11
+ */
12
+ function resourceRef(permission, data, wireId) {
13
+ const id = resourceIdOf(data) ?? (typeof wireId === "string" || typeof wireId === "number" ? String(wireId) : void 0);
14
+ return id === void 0 ? { type: permission.resource } : {
15
+ type: permission.resource,
16
+ id
17
+ };
18
+ }
19
+ //#endregion
20
+ export { resourceRef as n, resourceIdOf as t };
@@ -0,0 +1,27 @@
1
+ //#region src/core/revocations.ts
2
+ function isRevocationEvent(value) {
3
+ if (value === null || typeof value !== "object") return false;
4
+ const event = value;
5
+ return typeof event["principal"] === "string" && event["principal"].length > 0 && (event["kind"] === "session-revoked" || event["kind"] === "changed") && (event["session"] === void 0 || typeof event["session"] === "string") && (event["tenant"] === void 0 || typeof event["tenant"] === "string");
6
+ }
7
+ /** In-process feed; a multi-replica app bridges `revoke` to its own pub/sub. */
8
+ function memoryRevocationFeed() {
9
+ const listeners = /* @__PURE__ */ new Set();
10
+ return Object.freeze({
11
+ subscribe(listener) {
12
+ listeners.add(listener);
13
+ return () => {
14
+ listeners.delete(listener);
15
+ };
16
+ },
17
+ revoke(event) {
18
+ if (!isRevocationEvent(event)) throw new TypeError("PermDock: invalid revocation event.");
19
+ const frozen = Object.freeze({ ...event });
20
+ for (const listener of listeners) try {
21
+ listener(frozen);
22
+ } catch {}
23
+ }
24
+ });
25
+ }
26
+ //#endregion
27
+ export { memoryRevocationFeed as t };