permdock 0.6.0 → 0.8.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 (507) hide show
  1. package/README.md +2 -3
  2. package/dist/{2020-C9VN-x8c.js → 2020-CJbO8Bvz.js} +1 -3
  3. package/dist/a2a/index.d.ts +7 -7
  4. package/dist/a2a/index.js +9 -9
  5. package/dist/action-result-CL-QCITA.d.ts +19 -0
  6. package/dist/{adapter-context-CRhqyzCk.js → adapter-context-CIQpQxbE.js} +8 -2
  7. package/dist/{adoption-scan-DCYe60Pi.js → adoption-scan-BLs67P1l.js} +5 -5
  8. package/dist/agent/index.d.ts +3 -3
  9. package/dist/agent/index.js +1 -1
  10. package/dist/ai-sdk/index.d.ts +31 -10
  11. package/dist/ai-sdk/index.js +22 -12
  12. package/dist/{app-data-MuyzVqX8.js → app-data-UNNm07jV.js} +10 -7
  13. package/dist/{approval-header-CJACtHkv.js → approval-header-8QV6MU4H.js} +6 -3
  14. package/dist/{approval-prompt-Dg5LeAcT.js → approval-prompt-B8hQY69x.js} +5 -6
  15. package/dist/{approval-prompt-DvSSPQJX.d.ts → approval-prompt-PYagyQUj.d.ts} +13 -11
  16. package/dist/approvals/index.d.ts +5 -5
  17. package/dist/approvals/index.js +7 -7
  18. package/dist/{approvals-p1PGoVjb.js → approvals-DnIBTuXE.js} +128 -78
  19. package/dist/{approvers-CqPOLD-o.js → approvers-B4r0N_Uz.js} +8 -2
  20. package/dist/{arazzo-41WuzHou.js → arazzo-3RhGfkAK.js} +2 -2
  21. package/dist/{arazzo-CaUVBn7D.js → arazzo-B5-ulWif.js} +6 -6
  22. package/dist/{args-IIolxxKA.js → args-0FrVs5EH.js} +125 -8
  23. package/dist/astro/index.d.ts +30 -12
  24. package/dist/astro/index.js +2 -2
  25. package/dist/{audience-DabClFLQ.js → audience-BAkBDMqn.js} +8 -8
  26. package/dist/{auth-DRLEizbL.js → auth--yPyZNgr.js} +21 -10
  27. package/dist/authzen/index.d.ts +171 -25
  28. package/dist/authzen/index.js +321 -149
  29. package/dist/{automation-BNM3TtDo.d.ts → automation-DqEoWHBc.d.ts} +42 -32
  30. package/dist/{automation-DVjOckjV.js → automation-x3KEUusw.js} +22 -21
  31. package/dist/base-url-BQbddZO5.js +9 -0
  32. package/dist/better-auth/index.d.ts +2 -2
  33. package/dist/better-auth/index.js +13 -7
  34. package/dist/better-supabase/index.d.ts +392 -220
  35. package/dist/better-supabase/index.js +293 -152
  36. package/dist/{bind-DOyrv6zi.d.ts → bind-Cp2hBHzP.d.ts} +27 -12
  37. package/dist/{bind-CAvgUuKs.js → bind-D_sZSVA3.js} +22 -10
  38. package/dist/{body-CH5of8Ne.js → body-CJQwYVa8.js} +3 -3
  39. package/dist/{body-text-QcXok_SI.js → body-text-DQhcmqdY.js} +8 -4
  40. package/dist/{boundary-BM8a_P6E.js → boundary-BV3O1eud.js} +8 -2
  41. package/dist/{boundary-BmHxVH1J.d.ts → boundary-C9ck-3uK.d.ts} +13 -4
  42. package/dist/{budget-NbEtbJC_.js → budget-BELja5A9.js} +6 -3
  43. package/dist/{budget-JqcRqyhK.d.ts → budget-hYsPz_yE.d.ts} +6 -3
  44. package/dist/{build-instance-Bu_eDqYw.js → build-instance-CNWaYJyr.js} +3 -3
  45. package/dist/{canonical-json-BC8_nMTw.js → canonical-json-DwilZ1iB.js} +6 -3
  46. package/dist/{capability-N1K9IpqS.js → capability-BqX94r07.js} +31 -25
  47. package/dist/{capability-Drg-1YhL.d.ts → capability-ChuiONQU.d.ts} +41 -29
  48. package/dist/{casbin-Dyu2gnUD.js → casbin-H0rKxBx2.js} +16 -8
  49. package/dist/{casbin-Cr7RLtA3.js → casbin-cbSbhT_k.js} +2 -2
  50. package/dist/{casl-64gpT-8x.js → casl-C4OINZHI.js} +2 -2
  51. package/dist/{casl-DjEDhTCP.js → casl-CHHoCldP.js} +19 -10
  52. package/dist/catalog/index.d.ts +104 -23
  53. package/dist/catalog/index.js +117 -8
  54. package/dist/{catalog-HD2gf5mY.js → catalog-BFpz2EmT.js} +57 -26
  55. package/dist/{catalog-DZVbrF-z.js → catalog-DCspHDc8.js} +3 -3
  56. package/dist/{catalog-doc-Cdn7-0pQ.js → catalog-doc-DjMKzJp9.js} +53 -16
  57. package/dist/{catalog-fingerprint-CCP0-yQS.js → catalog-fingerprint-e6aCWosn.js} +19 -15
  58. package/dist/catalog-mRQQQhNK.js +1 -0
  59. package/dist/catalog-operations-Dadrl7Z-.js +60 -0
  60. package/dist/{create-CQWIpUG-.js → challenge-DImNcR7B.js} +157 -39
  61. package/dist/chat/index.d.ts +1 -1
  62. package/dist/chat/index.js +13 -10
  63. package/dist/chat-sdk/index.d.ts +44 -26
  64. package/dist/chat-sdk/index.js +17 -17
  65. package/dist/checks-CGkP3Z7A.js +40 -0
  66. package/dist/{claims-map-7oQ3ue4X.js → claims-map-CKkoAAYF.js} +5 -2
  67. package/dist/{claims-map-Ca-QX8C6.d.ts → claims-map-D1Pb5oRq.d.ts} +8 -5
  68. package/dist/claude-agent/index.d.ts +6 -6
  69. package/dist/claude-agent/index.js +6 -3
  70. package/dist/clerk/index.d.ts +11 -7
  71. package/dist/clerk/index.js +6 -6
  72. package/dist/cli/bin.js +4 -4
  73. package/dist/cli/index.d.ts +82 -7
  74. package/dist/cli/index.js +6 -6
  75. package/dist/{clients-C7zLFuWT.d.ts → clients-C_NOET3z.d.ts} +5 -5
  76. package/dist/{clients-DjU5ABMy.js → clients-DYr3U86j.js} +3 -3
  77. package/dist/cloud/index.d.ts +186 -38
  78. package/dist/cloud/index.js +293 -31
  79. package/dist/{cloud-ytQ3uviA.js → cloud-BFlGMaak.js} +5 -6
  80. package/dist/{codemod-5mpSpnUY.js → codemod-DLQ9Zpo4.js} +3 -4
  81. package/dist/{codemod-ua2hHy7w.js → codemod-DWSN2erG.js} +523 -201
  82. package/dist/collect-B5BL3klN.js +1 -0
  83. package/dist/{collect-mLTY4nwb.js → collect-B7ZFAJU3.js} +36 -64
  84. package/dist/{collect-Ci6akVwH.js → collect-Bzv3le0A.js} +6 -6
  85. package/dist/{compare-pfyVnBjE.js → compare-DTfyUunF.js} +2 -2
  86. package/dist/compile/index.d.ts +2 -2
  87. package/dist/compile/index.js +1 -1
  88. package/dist/{compile-1bsAezL0.d.ts → compile-BFzysW3o.d.ts} +36 -12
  89. package/dist/{compile-CMqMx_IN.js → compile-EzEMB-7v.js} +77 -33
  90. package/dist/{completion-BTFrHZhX.js → completion-saoYiRFO.js} +17 -8
  91. package/dist/config-BwPBfN0t.js +108 -0
  92. package/dist/{config-Bj2Ixq3d.js → config-DBeXXmBF.js} +2 -2
  93. package/dist/{config-report-DSpsLpCE.js → config-report-BipSWA6V.js} +9 -6
  94. package/dist/config-shape-ykV0Vm2n.js +134 -0
  95. package/dist/{connection-DjhIJSs2.js → connection-B72dg5Q2.js} +23 -22
  96. package/dist/connector-schema-CYLQNMYq.js +434 -0
  97. package/dist/{context-B_u3_bDJ.js → context-BnIzxTNE.js} +4 -3
  98. package/dist/convex/index.d.ts +13 -7
  99. package/dist/convex/index.js +9 -6
  100. package/dist/core-H-mbhpZc.js +341 -0
  101. package/dist/core-hWIARPDz.d.ts +206 -0
  102. package/dist/{create-CBMmFie-.d.ts → create-BSNrVuxh.d.ts} +87 -34
  103. package/dist/{create-B30OMUOJ.d.ts → create-BVq1lNQE.d.ts} +49 -28
  104. package/dist/{create-D_NmPOdH.d.ts → create-CM1FciYG.d.ts} +37 -29
  105. package/dist/{create-CGm28gyI.js → create-Cq4Uox0f.js} +13 -9
  106. package/dist/{create-DCF2SvoT.js → create-_noSrY1T.js} +15 -21
  107. package/dist/{credential-BcoiejpY.js → credential-CyyyvCsL.js} +42 -39
  108. package/dist/{credentials-DPyHmYz5.js → credentials-CdDxp7jN.js} +6 -6
  109. package/dist/{deciding-columns-Sq12mEA6.js → deciding-columns-NB4wcyBf.js} +13 -2
  110. package/dist/{delegation-j6-rc37o.js → delegation-CDB6_keF.js} +31 -22
  111. package/dist/delivery/index.d.ts +5 -5
  112. package/dist/delivery/index.js +6 -5
  113. package/dist/{delivery-DCAgNyCn.js → delivery-BupfvJIV.js} +81 -20
  114. package/dist/{delivery-event-xX4obB8F.js → delivery-event-JioK5YbS.js} +6 -6
  115. package/dist/denied-text-CHNlVInN.d.ts +22 -0
  116. package/dist/{describe-BybMRY7A.js → describe-Bb4hGK5d.js} +6 -5
  117. package/dist/{describe-B5qgDvEW.d.ts → describe-ByS9LgHK.d.ts} +5 -5
  118. package/dist/{device-BARQ8eYG.js → device-BwbJNmb2.js} +11 -8
  119. package/dist/{diff-CmuSD3vc.js → diff-CN8IYhC_.js} +2 -2
  120. package/dist/{diff-3jbx6Rm4.js → diff-iZWV65nC.js} +23 -14
  121. package/dist/{digest-B3kc_PgQ.d.ts → digest-8Yx2CchM.d.ts} +3 -3
  122. package/dist/{doctor-BdZw53-k.js → doctor-CHD1M9R5.js} +485 -141
  123. package/dist/{doctor-3ZqNHX_G.js → doctor-D3wo-yuz.js} +4 -4
  124. package/dist/drizzle/index.d.ts +33 -19
  125. package/dist/drizzle/index.js +17 -9
  126. package/dist/elysia/index.d.ts +17 -11
  127. package/dist/elysia/index.js +5 -5
  128. package/dist/{errors-BKy0EfhN.js → errors-B6R_lg2a.js} +13 -4
  129. package/dist/{errors-BWXBMaKK.d.ts → errors-CHwoRRpB.d.ts} +4 -1
  130. package/dist/{errors-CWTY6uih.js → errors-Vpu6rKHl.js} +14 -10
  131. package/dist/{errors-DH5QEGXh.d.ts → errors-zi_4T-rx.d.ts} +22 -6
  132. package/dist/{evaluate-CNClBvcj.js → evaluate-Dd8Ta0Ie.js} +185 -80
  133. package/dist/{evaluations-beAooV0n.js → evaluations-IBceAeKT.js} +41 -20
  134. package/dist/{evaluations-C_1vdSZc.d.ts → evaluations-z8dQFDaN.d.ts} +12 -6
  135. package/dist/eve/index.d.ts +9 -6
  136. package/dist/eve/index.js +4 -4
  137. package/dist/{event-time-CsegxXxB.js → event-time-BGy48400.js} +8 -4
  138. package/dist/{expiry-D4_YKRKD.js → expiry-6XByK0dm.js} +8 -5
  139. package/dist/express/index.d.ts +9 -6
  140. package/dist/express/index.js +9 -6
  141. package/dist/fastify/index.d.ts +16 -10
  142. package/dist/fastify/index.js +8 -5
  143. package/dist/{fetch-adapter-Dw0MTS3D.d.ts → fetch-adapter-C1DCvpqV.d.ts} +9 -6
  144. package/dist/{fetch-adapter-DD_gfmrC.js → fetch-adapter-JL43jD3E.js} +14 -11
  145. package/dist/fields-D0vUI6dq.js +498 -0
  146. package/dist/{files-C5ZI27eV.js → files-B3AA05f1.js} +21 -5
  147. package/dist/{files-D_JIzUrP.js → files-BSjrtIHw.js} +11 -4
  148. package/dist/{fixtures-B7XrLeY7.js → fixtures-A1_sp_tR.js} +15 -6
  149. package/dist/{flags-C3DktBDY.js → flags-DXjoTVbS.js} +2 -2
  150. package/dist/{freeze-CrU8nQeX.js → freeze-jjan0lCv.js} +4 -1
  151. package/dist/{from-snapshot-CTCMsFZk.js → from-snapshot-DCakWRsr.js} +26 -16
  152. package/dist/gen-B5kvbAoZ.js +58 -0
  153. package/dist/gen-DWCYcMQM.js +827 -0
  154. package/dist/generate-CRVV5V7l.js +165 -0
  155. package/dist/generate-CezbCaTI.js +275 -0
  156. package/dist/{grantee-hxrUsbpM.js → grantee-Dke-9rd1.js} +4 -4
  157. package/dist/{grantee-conditions-CcXf8hMM.js → grantee-conditions-BrYPe-w0.js} +12 -12
  158. package/dist/{grantee-match-DbENBHLB.js → grantee-match-7RZZvoT_.js} +12 -6
  159. package/dist/{graph-sql-B-dsAT6j.d.ts → graph-sql-BwFC4Qjs.d.ts} +3 -3
  160. package/dist/h3/index.d.ts +10 -7
  161. package/dist/h3/index.js +3 -3
  162. package/dist/headers-B9jQxjtW.d.ts +10 -0
  163. package/dist/{helpers-CBYVMjwh.js → helpers-DJicaG6f.js} +40 -28
  164. package/dist/hono/index.d.ts +16 -10
  165. package/dist/hono/index.js +5 -5
  166. package/dist/{hosted-BPk51-kX.d.ts → hosted-Cmtxogd0.d.ts} +44 -20
  167. package/dist/{hosted-B46-5LYE.js → hosted-D0IzESu_.js} +68 -25
  168. package/dist/{http-ujKm0JXE.js → http-DH94eh6f.js} +4 -4
  169. package/dist/{http-BBoKefeS.js → http-DKLXrFGk.js} +13 -7
  170. package/dist/{http-DXJ37RDA.js → http-DOL33cO0.js} +11 -8
  171. package/dist/{import-wyqXUyjm.js → import-CST57XLp.js} +64 -51
  172. package/dist/{import-CNV7I2Dw.js → import-_YqhhwvX.js} +6 -6
  173. package/dist/{index-B8YjkEZ4.d.ts → index-B8s204GL.d.ts} +64 -52
  174. package/dist/{index-Ch8LpNDp.d.ts → index-BT5-1VsX.d.ts} +64 -25
  175. package/dist/{index-DuWxc5dt.d.ts → index-BW_0MZOS.d.ts} +388 -149
  176. package/dist/index-BhxEUY9J.d.ts +233 -0
  177. package/dist/index-Bv5iXPqU.d.ts +210 -0
  178. package/dist/{index-C-6Letxg.d.ts → index-_9UiQIkt.d.ts} +164 -77
  179. package/dist/index.d.ts +22 -21
  180. package/dist/index.js +35 -33
  181. package/dist/{init-GG6Jh8HD.js → init-Dz_PsHdv.js} +5 -5
  182. package/dist/{init-DeMYsnYJ.js → init-cE3A8aXq.js} +10 -10
  183. package/dist/{instance-options-BsVpyGIk.d.ts → instance-options-B0KXqTrJ.d.ts} +4 -4
  184. package/dist/{instance-snapshot-BOEhcqIF.js → instance-snapshot--JWiTrvO.js} +81 -56
  185. package/dist/{instant-BluqDvyS.js → instant-DK3Iz83e.js} +2 -2
  186. package/dist/{internals-Dk8A8fX3.js → internals-B3IgHrvo.js} +6 -3
  187. package/dist/{json-schema-B-vAwlde.js → json-schema-BPGa-RjQ.js} +9 -3
  188. package/dist/{json-schema-CN_iLFH2.d.ts → json-schema-BfXgnRNT.d.ts} +4 -4
  189. package/dist/jwt/index.d.ts +125 -17
  190. package/dist/jwt/index.js +157 -16
  191. package/dist/{kernel-D0NVb1cK.js → kernel-C-fYydV2.js} +151 -16
  192. package/dist/kysely/index.d.ts +49 -33
  193. package/dist/kysely/index.js +9 -7
  194. package/dist/{live-options-BaAFCIiu.js → live-options-BBIT68le.js} +2 -2
  195. package/dist/{load-DFS_ry0W.js → load-DjSU5KXO.js} +6 -6
  196. package/dist/load-Dm0pSYH3.js +1 -0
  197. package/dist/{login-Dfe5RlYk.js → login-D-8tMqzo.js} +4 -4
  198. package/dist/{login-imhuwvn3.js → login-DplQ0s84.js} +18 -15
  199. package/dist/{manifest-dvL2XEe1.js → manifest-Cgiq5oqc.js} +67 -37
  200. package/dist/{manifest-mx5ghSFM.d.ts → manifest-CzzWtnAb.d.ts} +144 -28
  201. package/dist/{manifest-schema-C0kK_8V0.js → manifest-schema-2r37XRhD.js} +80 -9
  202. package/dist/{manifest-C8IzW3Do.js → manifest-wg8WkkpD.js} +11 -7
  203. package/dist/{map-claims-D3oRmTk0.js → map-claims-BNWCJtmP.js} +27 -18
  204. package/dist/{map-error-Dr70oA_3.js → map-error-pasIGqMT.js} +7 -7
  205. package/dist/{markers-C6joDI3o.js → markers-BeHZ4x9Q.js} +20 -5
  206. package/dist/mcp/index.d.ts +154 -47
  207. package/dist/mcp/index.js +200 -41
  208. package/dist/{migrate-CIq4-E9F.js → migrate-B7oP_sQU.js} +102 -31
  209. package/dist/module-values-BJTBdo6y.js +107 -0
  210. package/dist/nest/index.d.ts +23 -13
  211. package/dist/nest/index.js +18 -11
  212. package/dist/next/client.d.ts +5 -2
  213. package/dist/next/client.js +1 -1
  214. package/dist/next/index.d.ts +72 -26
  215. package/dist/next/index.js +110 -6
  216. package/dist/next/plugin.d.ts +1 -1
  217. package/dist/next/plugin.js +4 -3
  218. package/dist/node/index.d.ts +5 -5
  219. package/dist/node/index.js +3 -3
  220. package/dist/{ocsf-BFp-PZZA.js → ocsf-TcjRBgIs.js} +15 -5
  221. package/dist/openai/index.d.ts +13 -7
  222. package/dist/openai/index.js +3 -3
  223. package/dist/openapi/index.d.ts +61 -30
  224. package/dist/openapi/index.js +2 -2
  225. package/dist/{openapi-B7HZ0f-r.js → openapi-BOsx0xn9.js} +34 -24
  226. package/dist/{openapi-C4dDTVEd.js → openapi-CBZUhA3l.js} +4 -5
  227. package/dist/{openapi-DD1SV-5-.js → openapi-VeHHU2l9.js} +23 -14
  228. package/dist/{operation-findings-DgATDpvh.js → operation-findings-CXtFzlKJ.js} +3 -3
  229. package/dist/{operations-X0VM7F3m.d.ts → operations-Ci_rT6Uo.d.ts} +10 -7
  230. package/dist/orpc/index.d.ts +68 -14
  231. package/dist/orpc/index.js +62 -13
  232. package/dist/otel/index.d.ts +7 -4
  233. package/dist/otel/index.js +8 -5
  234. package/dist/output-files-BHOIlrfD.js +1 -0
  235. package/dist/{output-files-DhRBBE4n.js → output-files-BIQ_9pIs.js} +29 -17
  236. package/dist/{output-1im__-08.js → output-tkju6U7R.js} +15 -7
  237. package/dist/ownership-B4L59T9u.js +1054 -0
  238. package/dist/parse-1_ZheTW5.js +151 -0
  239. package/dist/parse-local-manifest-BQhTlLQS.d.ts +10 -0
  240. package/dist/parse-local-manifest-DEiCF4ah.js +69 -0
  241. package/dist/{parse-request-D_tUXG6M.js → parse-request-CwCZpyjV.js} +7 -8
  242. package/dist/{paths-DXSHAMIa.js → paths-CUvURzHp.js} +4 -1
  243. package/dist/pdp/index.d.ts +9 -6
  244. package/dist/pdp/index.js +23 -12
  245. package/dist/{peer-CRvC7Hg1.js → peer-C9LvBCcb.js} +1 -1
  246. package/dist/peer-Q0fuZ6hx.js +982 -0
  247. package/dist/{permdock-SV8ZINYT.d.ts → permdock-B6Sf4T_S.d.ts} +270 -117
  248. package/dist/{permdock-BrAscV28.js → permdock-L-_I_3zP.js} +226 -74
  249. package/dist/{permission-registry-Br4jSNVi.js → permission-registry-B8tYxPIt.js} +24 -11
  250. package/dist/{vocabulary-CN8H_9UF.d.ts → permission-types-CAY-GU7e.d.ts} +130 -104
  251. package/dist/{permissions-u_KHg-sN.d.ts → permissions-Bx6UI8n1.d.ts} +6 -2
  252. package/dist/{permissions-B-wCP5ZC.js → permissions-CVXmRILq.js} +3 -3
  253. package/dist/{permissions-BPxlwVhN.js → permissions-mDcTWoBs.js} +8 -5
  254. package/dist/pg-DQTqRrou.js +60 -0
  255. package/dist/{pins-8ILTftC9.js → pins-nqarl3oE.js} +4 -1
  256. package/dist/pkce-CnmmYqUZ.js +21 -0
  257. package/dist/{policy-77FSAq_V.d.ts → policy-Ba4bDhaj.d.ts} +5 -5
  258. package/dist/{policy-DbM5YYtV.js → policy-CLQ8__GF.js} +49 -20
  259. package/dist/{policy-from-catalog-C2gMa2Dj.js → policy-from-catalog-CJgOm6aq.js} +28 -25
  260. package/dist/{policy-module-CTlwMvLI.js → policy-module-xym9fnSq.js} +12 -6
  261. package/dist/{policy-types-n0uRTsW8.d.ts → policy-types-CCiDRZBH.d.ts} +802 -334
  262. package/dist/postgres-store-DcyrPS-r.js +1028 -0
  263. package/dist/{postgrest-DAjUkF9w.js → postgrest-D4nuPXIQ.js} +88 -36
  264. package/dist/{postgrest-CEgRbefE.d.ts → postgrest-DicQyqm-.d.ts} +60 -30
  265. package/dist/powersync-DHNQX06W.js +1117 -0
  266. package/dist/{powersync-DISt6SUe.js → powersync-DXqGuq9A.js} +3 -3
  267. package/dist/powersync-Djf-zCpB.js +1 -0
  268. package/dist/preset/index.d.ts +38 -28
  269. package/dist/preset/index.js +1 -1
  270. package/dist/{preset-DZdU0tne.js → preset-BjLzeFpp.js} +58 -34
  271. package/dist/{principal-source-pHneukrx.js → principal-source-C6N60GtM.js} +10 -10
  272. package/dist/prisma/index.d.ts +69 -41
  273. package/dist/prisma/index.js +21 -17
  274. package/dist/{problem-CTviyH5L.js → problem-BVLHFK33.js} +41 -21
  275. package/dist/{problem-details-cn5X30gZ.js → problem-details-CLDgX1KV.js} +13 -4
  276. package/dist/{problem-types-CJ2325SZ.js → problem-types-DSsRfONQ.js} +4 -1
  277. package/dist/prompt-BYc6drYW.js +938 -0
  278. package/dist/protected-action-BE7N_Luo.d.ts +58 -0
  279. package/dist/protected-action-DUYqb-Ma.js +80 -0
  280. package/dist/{protected-BlF0F6wL.js → protected-action-QEA8arRB.js} +48 -14
  281. package/dist/{provider-B1al-AZz.js → provider-C55OGXJ7.js} +5 -4
  282. package/dist/{provider-DILL9oPK.d.ts → provider-DXfq5c2d.d.ts} +1 -1
  283. package/dist/{provider-store-DM6DNcta.js → provider-store-CaTv00tr.js} +13 -9
  284. package/dist/pull-B65ndFNZ.js +1 -0
  285. package/dist/{pull-jEwbf80J.js → pull-CwpGaQSi.js} +12 -11
  286. package/dist/{push-BD4f15co.js → push-DgssgzkK.js} +62 -16
  287. package/dist/{pushed-policy-DCW91KQU.d.ts → pushed-policy-D1Eoi6NM.d.ts} +12 -6
  288. package/dist/{pushed-policy-CqtxkV4G.js → pushed-policy-ITwYKvvH.js} +10 -7
  289. package/dist/react/index.d.ts +9 -8
  290. package/dist/react/index.js +7 -6
  291. package/dist/react/provider-client.d.ts +1 -1
  292. package/dist/react/provider-client.js +1 -1
  293. package/dist/react-native/index.d.ts +104 -51
  294. package/dist/react-native/index.js +394 -67
  295. package/dist/{refs-K6eWUJ0H.js → refs-C8BKxc_e.js} +17 -3
  296. package/dist/{relation-walk-3OyDBF0S.js → relation-walk-DK_gkgL7.js} +12 -9
  297. package/dist/{relations-BnCWnJGI.js → relations-BxvRvDHK.js} +3 -3
  298. package/dist/{replay-Du1tJjG7.js → replay-BU09ad4L.js} +1 -1
  299. package/dist/{replay-Bkm-Ne4l.d.ts → replay-DNftIb_R.d.ts} +1 -1
  300. package/dist/{request-context-C81Pip9n.js → request-context-C25ilqiJ.js} +8 -8
  301. package/dist/{request-schema-CMreVuFM.js → request-schema-DhX7UbfQ.js} +4 -1
  302. package/dist/resend/index.d.ts +34 -28
  303. package/dist/resend/index.js +29 -29
  304. package/dist/resolve-names-CF7xXLSG.js +201 -0
  305. package/dist/{resource-relations-D_jw0BFx.js → resource-relations-8-pCScBO.js} +18 -9
  306. package/dist/{retire-CALjIQ7e.js → retire-B2xffQgY.js} +15 -6
  307. package/dist/{revocations-R07lFBnX.d.ts → revocations-BaUXHM1N.d.ts} +6 -3
  308. package/dist/{rls-DTvYd-lI.js → rls-CNEH2_BG.js} +743 -624
  309. package/dist/{rls-BAqP4q66.js → rls-Ca8Jz9b5.js} +41 -10
  310. package/dist/{role-builder-uWQZ4v84.js → role-builder-BK2-T6oD.js} +41 -20
  311. package/dist/rolldown-runtime-C3I60J0A.js +4 -0
  312. package/dist/{row-conditions-h2HythXQ.js → row-conditions-BAGHOmVq.js} +4 -3
  313. package/dist/{rpc-VSl5ylaQ.js → rpc-fNqAIqQk.js} +8 -5
  314. package/dist/{run-CUKuz0A8.js → run-Bz26OTfO.js} +26 -23
  315. package/dist/run-D-JE8QWb.js +1 -0
  316. package/dist/{run-ticket-DocwaTKn.d.ts → run-ticket-DbWI9f99.d.ts} +33 -13
  317. package/dist/{run-ticket-sxFI6LAk.js → run-ticket-Dv7aF7Dk.js} +29 -8
  318. package/dist/{runtime-D3VTAiCA.js → runtime-BGnrOkVH.js} +5 -2
  319. package/dist/{saas-BCXRuXca.js → saas-iWnUdwCt.js} +42 -29
  320. package/dist/{scan-qvOe0hS3.js → scan-DCj1KQfn.js} +1 -1
  321. package/dist/{schema-B4v0Qrac.js → schema-BOJjqlWL.js} +3 -2
  322. package/dist/{schema-yLuBWWsh.js → schema-Dst9I9Gs.js} +9 -5
  323. package/dist/scim/index.d.ts +3 -2
  324. package/dist/scim/index.js +3 -1
  325. package/dist/scim-D8YupzX1.js +44 -0
  326. package/dist/{scim-ClHtpyV3.js → scim-jJBJ7g1Z.js} +35 -551
  327. package/dist/{scopes-CUPSjo9q.js → scopes-0Up_UA2t.js} +42 -24
  328. package/dist/server/index.d.ts +12 -12
  329. package/dist/server/index.js +13 -13
  330. package/dist/{server-C3WXAHZj.js → server-3cVlTLde.js} +31 -31
  331. package/dist/{server-types-CKQiCnON.d.ts → server-types-CIlpSA2G.d.ts} +81 -46
  332. package/dist/{sha256-D9ihqmvd.js → sha256-C-4WXKIu.js} +4 -3
  333. package/dist/{shared-BAK8t4Uo.js → shared-Afctg7B0.js} +100 -61
  334. package/dist/{shared-DvvFzYXe.js → shared-l0oGGetg.js} +9 -6
  335. package/dist/{signals-D3NcTKUS.js → signals-B1vHR3fN.js} +2 -2
  336. package/dist/{sink-BEZSlMS_.js → sink-D9_vh372.js} +32 -21
  337. package/dist/{sink-4-eQIRWf.d.ts → sink-Dvi7YZG_.d.ts} +44 -20
  338. package/dist/{skills-B6lVdD_W.js → skills-Bjj7BNEQ.js} +16 -12
  339. package/dist/{skills-CTYwkl44.js → skills-OuoMR49L.js} +3 -3
  340. package/dist/{snapshot-B7DkYg6g.js → snapshot-CXlzi69u.js} +21 -18
  341. package/dist/{snapshot-cache-PXI-vGpY.d.ts → snapshot-cache-BAXZ0KOp.d.ts} +21 -12
  342. package/dist/{snapshot-cache-DZHQ0KF6.js → snapshot-cache-Bx_4xC_6.js} +14 -11
  343. package/dist/solid/index.d.ts +55 -15
  344. package/dist/solid/index.js +46 -12
  345. package/dist/solid-start/index.d.ts +30 -12
  346. package/dist/solid-start/index.js +3 -3
  347. package/dist/sources-B1Os_YUu.d.ts +312 -0
  348. package/dist/{sources-vs5dGOsS.js → sources-CMAM-2A3.js} +156 -51
  349. package/dist/sources-qoIJQrJv.js +11 -0
  350. package/dist/{sql-B5T1IL83.js → sql-0WjxIp9g.js} +32 -7
  351. package/dist/sql-B80DFdpG.d.ts +10 -0
  352. package/dist/{src-Cu2m75uo.js → src-DZ0l9UAg.js} +305 -123
  353. package/dist/ssf/index.d.ts +4 -4
  354. package/dist/ssf/index.js +665 -224
  355. package/dist/{standard-webhooks-rbD7LS6h.d.ts → standard-webhooks-C-qX4mJW.d.ts} +7 -7
  356. package/dist/{standard-webhooks-DgFFD-Ga.js → standard-webhooks-D67a3nzk.js} +5 -5
  357. package/dist/{store-BDutJkDL.js → store-RNFvaJJv.js} +43 -29
  358. package/dist/{store-options-u0ycEe8s.js → store-options-Dil3lraY.js} +105 -15
  359. package/dist/stores-C0Kta5Ft.d.ts +59 -0
  360. package/dist/{stores-CGhM8BN_.js → stores-DxZWDXCs.js} +42 -5
  361. package/dist/{stream-CvdUS9V1.js → stream-CDvF0sJm.js} +5 -5
  362. package/dist/{stream-CeCMJmBB.d.ts → stream-ltuLdtTG.d.ts} +4 -3
  363. package/dist/{style-DiKWnAvn.js → style-DblOtSga.js} +1 -1
  364. package/dist/{style-Uao76wO7.js → style-Ds11Hmk4.js} +3 -1
  365. package/dist/{subject-settings-CkEwrw3W.js → subject-settings-8sH5HlII.js} +8 -4
  366. package/dist/{row-check-Dt35czLy.d.ts → subject-settings-vNW8qmUH.d.ts} +30 -18
  367. package/dist/supabase/index.d.ts +48 -37
  368. package/dist/supabase/index.js +6 -6
  369. package/dist/supabase/middleware.d.ts +19 -13
  370. package/dist/supabase/middleware.js +7 -7
  371. package/dist/{supabase-x5JtR2tc.js → supabase-BL1qJzzY.js} +82 -36
  372. package/dist/{supabase-By_frk3U.js → supabase-D39cuGPt.js} +3 -3
  373. package/dist/{supabase-hook-BMoEhZir.js → supabase-hook-B-yXnzUl.js} +1206 -286
  374. package/dist/supabase-hook-H-MtE9Wd.js +1 -0
  375. package/dist/supautils-BU-pAEpf.js +808 -0
  376. package/dist/{support-session-C6xJQYut.js → support-session-BsmPCbz8.js} +22 -22
  377. package/dist/svelte/PermissionBoundary.svelte +2 -6
  378. package/dist/svelte/Protected.svelte +2 -8
  379. package/dist/svelte/index.d.ts +9 -8
  380. package/dist/svelte/index.js +10 -9
  381. package/dist/svelte/runtime.d.ts +4 -4
  382. package/dist/svelte/runtime.js +4 -4
  383. package/dist/svelte/source.d.ts +9 -8
  384. package/dist/svelte/source.js +6 -5
  385. package/dist/sveltekit/index.d.ts +30 -12
  386. package/dist/sveltekit/index.js +2 -2
  387. package/dist/{ownership-DqaJNJPn.js → tables-DeMNEy6V.js} +1025 -1085
  388. package/dist/tanstack-start/index.d.ts +22 -10
  389. package/dist/tanstack-start/index.js +2 -2
  390. package/dist/{target-Bw37TFNA.js → target-qdEAnnhU.js} +6 -6
  391. package/dist/{tenancy-DN2QAx9z.js → tenancy-5d1zVBvK.js} +36 -21
  392. package/dist/terminal/index.d.ts +23 -14
  393. package/dist/terminal/index.js +17 -20
  394. package/dist/testing/core.d.ts +2 -0
  395. package/dist/testing/core.js +1 -0
  396. package/dist/testing/fixtures/index.d.ts +15 -0
  397. package/dist/testing/fixtures/index.js +831 -0
  398. package/dist/testing/index.d.ts +235 -285
  399. package/dist/testing/index.js +502 -927
  400. package/dist/testing/saas/index.d.ts +43 -27
  401. package/dist/testing/saas/index.js +2 -2
  402. package/dist/testing/saas/permissions.d.ts +1 -1
  403. package/dist/testing/saas/permissions.js +1 -1
  404. package/dist/text-diff-BtfSmdUo.js +444 -0
  405. package/dist/{thenable-yD7SabqG.js → thenable-BNSM1U2R.js} +12 -3
  406. package/dist/{time-DkWjdL98.js → time-nR1JesoH.js} +32 -8
  407. package/dist/{token-BLZcjQgt.js → token-DC9EQiet.js} +15 -13
  408. package/dist/{tool-refusal-CMLN5xhn.js → tool-refusal-Qpjs_W6M.js} +5 -2
  409. package/dist/trpc/index.d.ts +11 -8
  410. package/dist/trpc/index.js +15 -9
  411. package/dist/type-helpers-BIPIDa6a.d.ts +50 -0
  412. package/dist/{types-8RnwUAvE.d.ts → types-AMJ5qoU_.d.ts} +49 -30
  413. package/dist/{types-C_IiEs64.d.ts → types-B2mlGuhW.d.ts} +14 -11
  414. package/dist/{types-_WhUP7ud.d.ts → types-B4uqKDnp.d.ts} +25 -12
  415. package/dist/{types-CX7AvRqP.d.ts → types-BJk0BKRX.d.ts} +24 -14
  416. package/dist/types-B_d_g7T3.d.ts +262 -0
  417. package/dist/{types-BdtSDbBO.d.ts → types-B_tiYvk8.d.ts} +59 -32
  418. package/dist/{types-DqzsnlSA.js → types-CcUXciSj.js} +17 -5
  419. package/dist/{types-Dfv0aTER.d.ts → types-DC1Loeh3.d.ts} +449 -168
  420. package/dist/{types-lUlG3TVd.d.ts → types-DHKPcqzr.d.ts} +2 -2
  421. package/dist/{types-C791HFu9.d.ts → types-DjuMBNF9.d.ts} +68 -32
  422. package/dist/{types-C863OQiR.d.ts → types-HzqOtvsJ.d.ts} +23 -12
  423. package/dist/{types-Druu9wLM.d.ts → types-ZzRGoViD.d.ts} +77 -24
  424. package/dist/{types-BzzaHxt3.d.ts → types-ah9NlU6j.d.ts} +137 -48
  425. package/dist/{types-CVZSNocA.d.ts → types-djVzLlIV.d.ts} +31 -14
  426. package/dist/{types-BtHtcKMr.d.ts → types-yUuPR5Hy.d.ts} +47 -24
  427. package/dist/unplugin/index.d.ts +1 -1
  428. package/dist/unplugin/index.js +2 -2
  429. package/dist/usage-CYeXek0p.js +1 -0
  430. package/dist/{usage-SveTRTyr.js → usage-CxEzS4ey.js} +50 -26
  431. package/dist/{usage-CRVl9V3t.js → usage-ab0PdusX.js} +2 -2
  432. package/dist/{validation-error-ZfUHbKvf.js → validation-error-CYg2kJEw.js} +4 -1
  433. package/dist/{validation-error-DHUrAkku.d.ts → validation-error-YGg2mXyH.d.ts} +5 -2
  434. package/dist/{validity-CZ7-y0Cj.js → validity-Buc7w8E9.js} +13 -10
  435. package/dist/{verifier-DHuh-okk.js → verifier-DUV6pLqZ.js} +10 -4
  436. package/dist/{verify-BaAKx7t6.js → verify-DZeqoWu5.js} +417 -489
  437. package/dist/version-DMQ0dnN5.js +48 -0
  438. package/dist/version-DizhmD72.js +1 -0
  439. package/dist/{views-DTIIO-oQ.js → views-CD8wuL4Z.js} +19 -6
  440. package/dist/vocabulary-DEJ5j4mR.d.ts +70 -0
  441. package/dist/vue/index.d.ts +71 -21
  442. package/dist/vue/index.js +50 -13
  443. package/dist/{waiter-B986w1oK.d.ts → waiter-Bu9zAlE0.d.ts} +13 -10
  444. package/dist/{waiter-BGUtGYoU.js → waiter-aBLM63_f.js} +1 -1
  445. package/dist/{watch-vea54PRw.js → watch-Cx_WciLE.js} +8 -8
  446. package/dist/watch-DB42U1ib.js +1 -0
  447. package/dist/webmcp/index.d.ts +11 -11
  448. package/dist/webmcp/index.js +8 -5
  449. package/dist/{where-scope-C9vfEphl.js → where-scope-DlCdCM_8.js} +56 -30
  450. package/dist/{who-can-DWBAcaCQ.js → who-can-rI7dCR9Q.js} +23 -20
  451. package/dist/workflow/index.d.ts +3 -3
  452. package/dist/workflow/index.js +13 -13
  453. package/dist/workflow-sdk/index.d.ts +19 -13
  454. package/dist/workflow-sdk/index.js +6 -6
  455. package/dist/{wrap-gX61EtpB.js → wrap-B2wziJI_.js} +11 -5
  456. package/dist/{wrap-C5jC6sKI.d.ts → wrap-DlJE3gS_.d.ts} +8 -5
  457. package/package.json +25 -14
  458. package/schemas/catalog-v1.json +3 -0
  459. package/schemas/cli-result-v1.json +1 -0
  460. package/schemas/cloud-api-v1.json +152 -7
  461. package/schemas/connector-v1.json +8 -0
  462. package/schemas/supabase-claims-v1.json +5 -0
  463. package/schemas/supabase-manifest-v1.json +308 -75
  464. package/skills/permdock/SKILL.md +1 -0
  465. package/skills/permdock-agents/references/runtimes.md +3 -1
  466. package/skills/permdock-approvals/references/stores-and-resume.md +2 -1
  467. package/skills/permdock-credentials/references/tokens-keys-links.md +8 -6
  468. package/skills/permdock-data/references/queries-and-rls.md +6 -2
  469. package/skills/permdock-tenancy/SKILL.md +1 -1
  470. package/skills/permdock-tenancy/references/ownership-and-custom-roles.md +2 -1
  471. package/skills/permdock-wire/references/adapters.md +28 -22
  472. package/skills/permdock-wire/references/policy-options.md +1 -0
  473. package/dist/catalog-BoWglDPI.js +0 -1
  474. package/dist/collect-D7eQDffE.js +0 -1
  475. package/dist/config-bs_kZeYq.js +0 -162
  476. package/dist/denied-text-CiFQNuMV.d.ts +0 -19
  477. package/dist/fields-OYG_JR78.js +0 -203
  478. package/dist/generate-CNU1pIOo.js +0 -171
  479. package/dist/headers-BIjfMaoC.js +0 -8
  480. package/dist/headers-CIbDTUTK.d.ts +0 -7
  481. package/dist/index-Cp_ilKi1.d.ts +0 -91
  482. package/dist/index-CueFnxQc.d.ts +0 -110
  483. package/dist/load-BxEtwlBS.js +0 -1
  484. package/dist/output-files-B3IZJksC.js +0 -1
  485. package/dist/package-root-Dk_ETdkp.js +0 -31
  486. package/dist/parse-Cxq0WxrA.js +0 -53
  487. package/dist/parse-local-manifest-5ODwqu8b.d.ts +0 -10
  488. package/dist/parse-local-manifest-CVSs6J9I.js +0 -34
  489. package/dist/peer-C8swJ2GH.js +0 -50
  490. package/dist/policies-DP2nqRoF.js +0 -295
  491. package/dist/powersync-BkWWCS1K.js +0 -538
  492. package/dist/powersync-MMJ2mI2q.js +0 -1
  493. package/dist/problem-details-B45V5d2b.d.ts +0 -7
  494. package/dist/prompt-DfZLJLIn.js +0 -32
  495. package/dist/protected-RFGpakN9.d.ts +0 -38
  496. package/dist/pull-CvpINcMK.js +0 -1
  497. package/dist/run-DDwUaJDU.js +0 -1
  498. package/dist/sources-Xc4zkszI.d.ts +0 -190
  499. package/dist/stores-BUGNbJTt.d.ts +0 -30
  500. package/dist/supabase-hook-CCw5m35C.js +0 -1
  501. package/dist/supautils-B6HYL9eL.js +0 -91
  502. package/dist/text-diff-BQcUapOb.js +0 -15
  503. package/dist/types-B3_ooZgZ.d.ts +0 -172
  504. package/dist/usage-CZpSQP6L.js +0 -1
  505. package/dist/version-CEbQ5UeM.js +0 -18
  506. package/dist/version-DXkYUISx.js +0 -1
  507. package/dist/watch--ovlPOc0.js +0 -1
package/dist/ssf/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { r as isRecord, t as compact } from "../compact-CAf557ZB.js";
2
- import { o as epochSeconds } from "../time-DkWjdL98.js";
3
- import { n as readBodyText } from "../body-text-QcXok_SI.js";
4
- import { t as cancelApprovals } from "../helpers-CBYVMjwh.js";
5
- import { i as issuerFromDiscovery, t as joseTokenVerifier } from "../verifier-DHuh-okk.js";
6
- import { t as memoryReplayStore } from "../replay-Du1tJjG7.js";
2
+ import { o as statusProblem } from "../problem-details-CLDgX1KV.js";
3
+ import { o as epochSeconds } from "../time-nR1JesoH.js";
4
+ import { n as readBodyText } from "../body-text-DQhcmqdY.js";
5
+ import { f as validationProblem, l as problemResponse, o as methodNotAllowed, s as notFoundProblem } from "../problem-BVLHFK33.js";
6
+ import { t as cancelApprovals } from "../helpers-DJicaG6f.js";
7
+ import { i as issuerFromDiscovery, t as joseTokenVerifier } from "../verifier-DUV6pLqZ.js";
8
+ import { t as memoryReplayStore } from "../replay-BU09ad4L.js";
7
9
  import { t as timeoutSignal } from "../timeout-D51niuQP.js";
8
10
  //#region src/ssf/claims.ts
9
11
  function asSubject(mapped, session, issuer) {
@@ -78,73 +80,15 @@ function eventName(uri) {
78
80
  return RISC_NAMES.find((known) => known === name);
79
81
  }
80
82
  }
83
+ /** Every CAEP and RISC event URI PermDock's receiver handles. */
84
+ function knownEventTypes() {
85
+ return [...CAEP_NAMES.map((name) => `${CAEP_PREFIX}${name}`), ...RISC_NAMES.map((name) => `${RISC_PREFIX}${name}`)];
86
+ }
81
87
  /** RISC events that end every session of the subject. */
82
88
  function revokesAccount(name) {
83
89
  return RISC_NAMES.some((known) => known === name);
84
90
  }
85
91
  //#endregion
86
- //#region src/ssf/poll.ts
87
- /** Milliseconds a poll or acknowledgement request may take. */
88
- const POLL_TIMEOUT_MS = 3e4;
89
- /**
90
- * One RFC 8936 poll round: fetch the pending SETs, ingest them and acknowledge
91
- * the ones that were accepted. Returns the acknowledged `jti` values.
92
- */
93
- async function pollOnce(input) {
94
- const { options, acks, ingest, emit } = input;
95
- const fetchFn = options.fetch ?? globalThis.fetch;
96
- const headers = { "content-type": "application/json" };
97
- if (options.token !== void 0) headers["authorization"] = `Bearer ${options.token}`;
98
- const body = {
99
- maxEvents: 100,
100
- returnImmediately: true
101
- };
102
- if (acks.length > 0) body["acks"] = acks;
103
- const requestInit = compact({
104
- method: "POST",
105
- headers,
106
- body: JSON.stringify(body),
107
- signal: timeoutSignal(POLL_TIMEOUT_MS, options.signal)
108
- });
109
- const response = await fetchFn(options.endpoint, requestInit);
110
- if (!response.ok) {
111
- emit({
112
- type: "poll-failed",
113
- err: "connection_failed"
114
- });
115
- return [];
116
- }
117
- const parsed = await response.json();
118
- if (!isRecord(parsed) || !isRecord(parsed["sets"])) return [];
119
- const tokens = Object.entries(parsed["sets"]).flatMap(([jti, jwt]) => typeof jwt === "string" ? [{
120
- jti,
121
- jwt
122
- }] : []);
123
- const outcomes = await Promise.all(tokens.map(async ({ jti, jwt }) => ({
124
- jti,
125
- result: await ingest(jwt)
126
- })));
127
- const processed = outcomes.flatMap((row) => row.result.ok ? [row.jti] : []);
128
- const setErrs = {};
129
- for (const { jti, result } of outcomes) if (!result.ok && result.cause !== void 0) setErrs[jti] = {
130
- err: result.err,
131
- description: result.description
132
- };
133
- const failed = Object.keys(setErrs).length;
134
- if (processed.length > 0 || failed > 0) await fetchFn(options.endpoint, compact({
135
- method: "POST",
136
- headers,
137
- body: JSON.stringify(compact({
138
- acks: processed,
139
- setErrs: failed > 0 ? setErrs : void 0,
140
- maxEvents: 0,
141
- returnImmediately: true
142
- })),
143
- signal: timeoutSignal(POLL_TIMEOUT_MS, options.signal)
144
- }));
145
- return processed;
146
- }
147
- //#endregion
148
92
  //#region src/ssf/wire.ts
149
93
  const SET_TYP = "secevent+jwt";
150
94
  const LOGOUT_TYP = "logout+jwt";
@@ -207,6 +151,285 @@ function parseEvery(every) {
207
151
  return Number(match[1]) * scale;
208
152
  }
209
153
  //#endregion
154
+ //#region src/ssf/transmitter.ts
155
+ /** SSF 1.0 delivery method URN for RFC 8935 push. */
156
+ const SSF_PUSH_DELIVERY = "urn:ietf:rfc:8935";
157
+ /** SSF 1.0 delivery method URN for RFC 8936 poll. */
158
+ const SSF_POLL_DELIVERY = "urn:ietf:rfc:8936";
159
+ /** Milliseconds one push may take. */
160
+ const PUSH_TIMEOUT_MS = 3e4;
161
+ /** The largest error body `pushSet` reads. */
162
+ const MAX_ERROR_BYTES = 16384;
163
+ /**
164
+ * Signs one event as an RFC 8417 Security Event Token (`typ: secevent+jwt`):
165
+ * `sub_id` is the event's subject and `events` holds exactly one entry, as SSF
166
+ * 1.0 requires. `iss` is the signer's own.
167
+ */
168
+ function signSet(event, signer, options) {
169
+ return signer.sign(compact({
170
+ sub_id: event.subject,
171
+ events: { [event.type]: event.payload },
172
+ txn: options.txn
173
+ }), compact({
174
+ typ: SET_TYP,
175
+ audience: options.audience,
176
+ jti: options.jti,
177
+ issuedAt: options.issuedAt
178
+ }));
179
+ }
180
+ const ERR_CAUSES = {
181
+ invalid_request: "invalid-request",
182
+ invalid_key: "invalid-key",
183
+ invalid_issuer: "invalid-issuer",
184
+ invalid_audience: "invalid-audience",
185
+ authentication_failed: "authentication-failed",
186
+ access_denied: "access-denied"
187
+ };
188
+ async function errorBody(response) {
189
+ const read = await readBodyText(response, MAX_ERROR_BYTES);
190
+ if (!read.ok) return {};
191
+ try {
192
+ const parsed = JSON.parse(read.text);
193
+ if (!isRecord(parsed)) return {};
194
+ return compact({
195
+ err: typeof parsed["err"] === "string" ? parsed["err"] : void 0,
196
+ description: typeof parsed["description"] === "string" ? parsed["description"] : void 0
197
+ });
198
+ } catch {
199
+ return {};
200
+ }
201
+ }
202
+ /**
203
+ * Pushes one SET to a receiver (RFC 8935). A `2xx` is delivery; a `400` maps
204
+ * the receiver's `err` to a cause; `401` and `403` are `authentication-failed`
205
+ * and `access-denied`; a network failure, a timeout, a `429` or a `5xx` is
206
+ * `unavailable` with `retry: true`. Never throws.
207
+ */
208
+ async function pushSet(set, options) {
209
+ const fetchFn = options.fetch ?? globalThis.fetch;
210
+ let response;
211
+ try {
212
+ response = await fetchFn(options.endpoint, {
213
+ method: "POST",
214
+ headers: compact({
215
+ "content-type": SET_CONTENT,
216
+ accept: "application/json",
217
+ authorization: options.authorization
218
+ }),
219
+ body: set,
220
+ signal: timeoutSignal(PUSH_TIMEOUT_MS, options.signal)
221
+ });
222
+ } catch {
223
+ return {
224
+ ok: false,
225
+ cause: "unavailable",
226
+ retry: true
227
+ };
228
+ }
229
+ if (response.ok) {
230
+ await response.body?.cancel();
231
+ return { ok: true };
232
+ }
233
+ return deliveryFailure(response);
234
+ }
235
+ /** The `SetDelivery` failure for a non-`2xx` RFC 8935 or RFC 8936 response. */
236
+ async function deliveryFailure(response) {
237
+ const { err, description } = await errorBody(response);
238
+ if (response.status === 429 || response.status >= 500) return compact({
239
+ ok: false,
240
+ cause: "unavailable",
241
+ description,
242
+ retry: true
243
+ });
244
+ const cause = (response.status === 401 ? "authentication-failed" : response.status === 403 ? "access-denied" : void 0) ?? (err !== void 0 && Object.hasOwn(ERR_CAUSES, err) ? ERR_CAUSES[err] : void 0) ?? "invalid-request";
245
+ return compact({
246
+ ok: false,
247
+ cause,
248
+ description,
249
+ retry: false
250
+ });
251
+ }
252
+ function reason(value) {
253
+ return typeof value === "string" ? { en: value } : value;
254
+ }
255
+ function caep(name, input, extra) {
256
+ return Object.freeze({
257
+ type: `${CAEP_PREFIX}${name}`,
258
+ subject: input.subject,
259
+ payload: Object.freeze(compact({
260
+ event_timestamp: input.eventTimestamp ?? epochSeconds(),
261
+ initiating_entity: input.initiatingEntity,
262
+ reason_admin: reason(input.reasonAdmin),
263
+ reason_user: reason(input.reasonUser),
264
+ ...extra
265
+ }))
266
+ });
267
+ }
268
+ /** CAEP 1.0 event builders; each returns a `SetEvent` for `signSet`. */
269
+ const caepEvents = Object.freeze({
270
+ sessionRevoked: (input) => caep("session-revoked", input, {}),
271
+ credentialChange: (input) => caep("credential-change", input, compact({
272
+ credential_type: input.credentialType,
273
+ change_type: input.changeType,
274
+ friendly_name: input.friendlyName,
275
+ x509_issuer: input.x509Issuer,
276
+ x509_serial: input.x509Serial,
277
+ fido2_aaguid: input.fido2Aaguid
278
+ })),
279
+ tokenClaimsChange: (input) => caep("token-claims-change", input, { claims: input.claims }),
280
+ assuranceLevelChange: (input) => caep("assurance-level-change", input, compact({
281
+ namespace: input.namespace,
282
+ current_level: input.currentLevel,
283
+ previous_level: input.previousLevel,
284
+ change_direction: input.changeDirection
285
+ })),
286
+ deviceComplianceChange: (input) => caep("device-compliance-change", input, {
287
+ previous_status: input.previousStatus,
288
+ current_status: input.currentStatus
289
+ })
290
+ });
291
+ function risc(name, subject, payload) {
292
+ return Object.freeze({
293
+ type: `${RISC_PREFIX}${name}`,
294
+ subject,
295
+ payload: Object.freeze(payload)
296
+ });
297
+ }
298
+ /**
299
+ * RISC 1.0 event builders for the events PermDock's receiver treats as revoking
300
+ * every session.
301
+ */
302
+ const riscEvents = Object.freeze({
303
+ accountDisabled: (input) => risc("account-disabled", input.subject, compact({ reason: input.reason })),
304
+ accountPurged: (input) => risc("account-purged", input.subject, {}),
305
+ credentialCompromise: (input) => risc("credential-compromise", input.subject, compact({
306
+ credential_type: input.credentialType,
307
+ event_timestamp: input.eventTimestamp ?? epochSeconds(),
308
+ initiating_entity: input.initiatingEntity,
309
+ reason_admin: reason(input.reasonAdmin),
310
+ reason_user: reason(input.reasonUser)
311
+ }))
312
+ });
313
+ /**
314
+ * The SSF 1.0 section 8.1.4 verification event for `stream`, echoing the
315
+ * receiver's `state`. Its subject is the stream, never a principal.
316
+ */
317
+ function streamVerificationEvent(stream, state) {
318
+ return Object.freeze({
319
+ type: VERIFICATION_EVENT,
320
+ subject: Object.freeze({
321
+ format: "opaque",
322
+ id: stream
323
+ }),
324
+ payload: Object.freeze(compact({ state }))
325
+ });
326
+ }
327
+ //#endregion
328
+ //#region src/ssf/poll-client.ts
329
+ /** Milliseconds one poll request may take. */
330
+ const POLL_TIMEOUT_MS = 3e4;
331
+ /** The largest poll response read. */
332
+ const MAX_SETS_BYTES = 4194304;
333
+ /**
334
+ * One RFC 8936 poll request: sends `acks` and `setErrs` and answers the SETs
335
+ * the transmitter returns, unverified. A failure maps as `pushSet`'s does; a
336
+ * `2xx` body without a `sets` object is `invalid-request`. Never throws.
337
+ */
338
+ async function pollSets(options) {
339
+ const fetchFn = options.fetch ?? globalThis.fetch;
340
+ const acks = options.acks ?? [];
341
+ const setErrs = options.setErrs ?? {};
342
+ let response;
343
+ try {
344
+ response = await fetchFn(options.endpoint, {
345
+ method: "POST",
346
+ headers: compact({
347
+ "content-type": "application/json",
348
+ accept: "application/json",
349
+ authorization: options.authorization
350
+ }),
351
+ body: JSON.stringify(compact({
352
+ acks: acks.length > 0 ? acks : void 0,
353
+ setErrs: Object.keys(setErrs).length > 0 ? setErrs : void 0,
354
+ maxEvents: options.maxEvents ?? 100,
355
+ returnImmediately: options.returnImmediately ?? true
356
+ })),
357
+ signal: timeoutSignal(POLL_TIMEOUT_MS, options.signal)
358
+ });
359
+ } catch {
360
+ return {
361
+ ok: false,
362
+ cause: "unavailable",
363
+ retry: true
364
+ };
365
+ }
366
+ if (!response.ok) return deliveryFailure(response);
367
+ const read = await readBodyText(response, MAX_SETS_BYTES);
368
+ let parsed;
369
+ try {
370
+ parsed = read.ok ? JSON.parse(read.text) : void 0;
371
+ } catch {
372
+ parsed = void 0;
373
+ }
374
+ if (!isRecord(parsed) || !isRecord(parsed["sets"])) return {
375
+ ok: false,
376
+ cause: "invalid-request",
377
+ description: "poll response has no sets object",
378
+ retry: false
379
+ };
380
+ return {
381
+ ok: true,
382
+ sets: Object.entries(parsed["sets"]).flatMap(([jti, set]) => typeof set === "string" ? [{
383
+ jti,
384
+ set
385
+ }] : []),
386
+ moreAvailable: parsed["moreAvailable"] === true
387
+ };
388
+ }
389
+ //#endregion
390
+ //#region src/ssf/poll.ts
391
+ /**
392
+ * One RFC 8936 poll round: fetch the pending SETs, ingest them and acknowledge
393
+ * the ones that were accepted. Returns the acknowledged `jti` values.
394
+ */
395
+ async function pollOnce(input) {
396
+ const { options, acks, ingest, emit } = input;
397
+ const transport = compact({
398
+ endpoint: options.endpoint,
399
+ authorization: options.token === void 0 ? void 0 : `Bearer ${options.token}`,
400
+ fetch: options.fetch,
401
+ signal: options.signal
402
+ });
403
+ const polled = await pollSets({
404
+ ...transport,
405
+ acks
406
+ });
407
+ if (!polled.ok) {
408
+ emit({
409
+ type: "poll-failed",
410
+ err: "connection_failed"
411
+ });
412
+ return [];
413
+ }
414
+ const outcomes = await Promise.all(polled.sets.map(async ({ jti, set }) => ({
415
+ jti,
416
+ result: await ingest(set)
417
+ })));
418
+ const processed = outcomes.flatMap((row) => row.result.ok ? [row.jti] : []);
419
+ const setErrs = {};
420
+ for (const { jti, result } of outcomes) if (!result.ok && result.cause !== void 0) setErrs[jti] = {
421
+ err: result.err,
422
+ description: result.description
423
+ };
424
+ if (processed.length > 0 || Object.keys(setErrs).length > 0) await pollSets({
425
+ ...transport,
426
+ acks: processed,
427
+ setErrs,
428
+ maxEvents: 0
429
+ });
430
+ return processed;
431
+ }
432
+ //#endregion
210
433
  //#region src/ssf/receiver.ts
211
434
  /** Seconds a SET without `exp` stays acceptable after its `iat`. */
212
435
  const DEFAULT_SET_MAX_AGE = 86400;
@@ -217,8 +440,8 @@ const CHANGED_EVENTS = /* @__PURE__ */ new Set([
217
440
  ]);
218
441
  /**
219
442
  * When the replay record of a SET may be dropped: its `exp`, or for a SET
220
- * without one (RFC 8417 section 2.2) the end of its acceptance window, so
221
- * the same `jti` cannot pass verification again once the record is gone.
443
+ * without one (RFC 8417 section 2.2) the end of its acceptance window, so the
444
+ * same `jti` cannot pass verification again once the record is gone.
222
445
  */
223
446
  function replayExpiresAt(claims, clockTolerance = 0, maxTokenAge = DEFAULT_SET_MAX_AGE) {
224
447
  if (typeof claims["exp"] === "number") return claims["exp"] + clockTolerance;
@@ -655,13 +878,16 @@ function createPermDock(policy, options) {
655
878
  }
656
879
  //#endregion
657
880
  //#region src/ssf/set-queue.ts
658
- /** The largest poll request body read: acknowledgements and errors for many SETs. */
881
+ /**
882
+ * The largest poll request body read: acknowledgements and errors for many
883
+ * SETs.
884
+ */
659
885
  const MAX_POLL_BYTES = 262144;
660
886
  const DEFAULT_MAX_EVENTS = 100;
661
887
  /**
662
888
  * An in-process `SetQueue`: pending SETs per stream in insertion order. A
663
- * process restart loses them; a deployment with more than one instance needs
664
- * a shared queue.
889
+ * process restart loses them; a deployment with more than one instance needs a
890
+ * shared queue.
665
891
  */
666
892
  function memorySetQueue() {
667
893
  const streams = /* @__PURE__ */ new Map();
@@ -723,10 +949,10 @@ function parsePollRequest(text) {
723
949
  };
724
950
  }
725
951
  /**
726
- * The RFC 8936 poll endpoint over a `SetQueue`. It applies the request's
727
- * `acks` and `setErrs`, then answers `{ sets, moreAvailable }` with up to
728
- * `maxEvents` pending SETs. It answers at once whatever `returnImmediately`
729
- * says, which RFC 8936 section 2.4 allows.
952
+ * The RFC 8936 poll endpoint over a `SetQueue`. It applies the request's `acks`
953
+ * and `setErrs`, then answers `{ sets, moreAvailable }` with up to `maxEvents`
954
+ * pending SETs. It answers at once whatever `returnImmediately` says, which RFC
955
+ * 8936 section 2.4 allows.
730
956
  */
731
957
  function setPollHandler(options) {
732
958
  const cap = options.maxEvents ?? DEFAULT_MAX_EVENTS;
@@ -760,171 +986,386 @@ function setPollHandler(options) {
760
986
  };
761
987
  }
762
988
  //#endregion
763
- //#region src/ssf/transmitter.ts
764
- /** SSF 1.0 delivery method URN for RFC 8935 push. */
765
- const SSF_PUSH_DELIVERY = "urn:ietf:rfc:8935";
766
- /** SSF 1.0 delivery method URN for RFC 8936 poll. */
767
- const SSF_POLL_DELIVERY = "urn:ietf:rfc:8936";
768
- /** Milliseconds one push may take. */
769
- const PUSH_TIMEOUT_MS = 3e4;
770
- /** The largest error body `pushSet` reads. */
771
- const MAX_ERROR_BYTES = 16384;
989
+ //#region src/ssf/streams.ts
772
990
  /**
773
- * Signs one event as an RFC 8417 Security Event Token (`typ: secevent+jwt`):
774
- * `sub_id` is the event's subject and `events` holds exactly one entry, as
775
- * SSF 1.0 requires. `iss` is the signer's own.
991
+ * An in-process `SsfStreamStore`. A process restart loses every stream; a
992
+ * deployment with more than one instance needs a shared store.
776
993
  */
777
- function signSet(event, signer, options) {
778
- return signer.sign(compact({
779
- sub_id: event.subject,
780
- events: { [event.type]: event.payload },
781
- txn: options.txn
782
- }), compact({
783
- typ: SET_TYP,
784
- audience: options.audience,
785
- jti: options.jti,
786
- issuedAt: options.issuedAt
787
- }));
994
+ function memorySsfStreamStore() {
995
+ const entries = /* @__PURE__ */ new Map();
996
+ return Object.freeze({
997
+ name: "memory",
998
+ create(owner, configuration) {
999
+ const id = configuration.stream_id;
1000
+ entries.set(id, {
1001
+ stream: Object.freeze({
1002
+ owner,
1003
+ configuration
1004
+ }),
1005
+ status: Object.freeze({
1006
+ stream_id: id,
1007
+ status: "enabled"
1008
+ })
1009
+ });
1010
+ },
1011
+ get(streamId) {
1012
+ return entries.get(streamId)?.stream ?? null;
1013
+ },
1014
+ list(owner) {
1015
+ return [...entries.values()].map((entry) => entry.stream).filter((stream) => owner === void 0 || stream.owner === owner);
1016
+ },
1017
+ update(configuration) {
1018
+ const entry = entries.get(configuration.stream_id);
1019
+ if (entry !== void 0) entries.set(configuration.stream_id, {
1020
+ stream: Object.freeze({
1021
+ owner: entry.stream.owner,
1022
+ configuration
1023
+ }),
1024
+ status: entry.status
1025
+ });
1026
+ },
1027
+ delete(streamId) {
1028
+ entries.delete(streamId);
1029
+ },
1030
+ status(streamId) {
1031
+ return entries.get(streamId)?.status ?? null;
1032
+ },
1033
+ setStatus(status) {
1034
+ const entry = entries.get(status.stream_id);
1035
+ if (entry !== void 0) entries.set(status.stream_id, {
1036
+ stream: entry.stream,
1037
+ status: Object.freeze({ ...status })
1038
+ });
1039
+ }
1040
+ });
788
1041
  }
789
- const ERR_CAUSES = {
790
- invalid_request: "invalid-request",
791
- invalid_key: "invalid-key",
792
- invalid_issuer: "invalid-issuer",
793
- invalid_audience: "invalid-audience",
794
- authentication_failed: "authentication-failed",
795
- access_denied: "access-denied"
796
- };
797
- async function errorBody(response) {
798
- const read = await readBodyText(response, MAX_ERROR_BYTES);
799
- if (!read.ok) return {};
800
- try {
801
- const parsed = JSON.parse(read.text);
802
- if (!isRecord(parsed)) return {};
803
- return compact({
804
- err: typeof parsed["err"] === "string" ? parsed["err"] : void 0,
805
- description: typeof parsed["description"] === "string" ? parsed["description"] : void 0
806
- });
807
- } catch {
808
- return {};
809
- }
1042
+ //#endregion
1043
+ //#region src/ssf/transmitter-handler.ts
1044
+ /** The largest stream-management request body read. */
1045
+ const MAX_BODY_BYTES = 65536;
1046
+ /** SETs drained or flushed per queue read. */
1047
+ const BATCH = 100;
1048
+ const STATUSES = [
1049
+ "enabled",
1050
+ "paused",
1051
+ "disabled"
1052
+ ];
1053
+ function isStatus(value) {
1054
+ return STATUSES.some((status) => status === value);
1055
+ }
1056
+ function isHttpUrl(value) {
1057
+ if (typeof value !== "string" || !URL.canParse(value)) return false;
1058
+ const { protocol } = new URL(value);
1059
+ return protocol === "https:" || protocol === "http:";
1060
+ }
1061
+ function readDelivery(value) {
1062
+ if (!isRecord(value)) return "delivery must be an object";
1063
+ const { method, endpoint_url, authorization_header } = value;
1064
+ if (method === "urn:ietf:rfc:8936") return { method };
1065
+ if (method !== "urn:ietf:rfc:8935") return `delivery.method must be ${SSF_PUSH_DELIVERY} or ${SSF_POLL_DELIVERY}`;
1066
+ if (!isHttpUrl(endpoint_url)) return "delivery.endpoint_url must be an http or https URL for push";
1067
+ if (authorization_header !== void 0 && typeof authorization_header !== "string") return "delivery.authorization_header must be a string";
1068
+ return compact({
1069
+ method,
1070
+ endpoint_url,
1071
+ authorization_header
1072
+ });
810
1073
  }
811
1074
  /**
812
- * Pushes one SET to a receiver (RFC 8935). A `2xx` is delivery; a `400`
813
- * maps the receiver's `err` to a cause; `401` and `403` are
814
- * `authentication-failed` and `access-denied`; a network failure, a timeout,
815
- * a `429` or a `5xx` is `unavailable` with `retry: true`. Never throws.
1075
+ * The receiver-supplied properties of a stream request (SSF 1.0 section 8.1.1).
1076
+ * `previous` keeps the properties a PATCH leaves out; without it an absent
1077
+ * property takes its default. Transmitter-supplied properties are ignored.
816
1078
  */
817
- async function pushSet(set, options) {
818
- const fetchFn = options.fetch ?? globalThis.fetch;
819
- let response;
820
- try {
821
- response = await fetchFn(options.endpoint, {
822
- method: "POST",
823
- headers: compact({
824
- "content-type": SET_CONTENT,
825
- accept: "application/json",
826
- authorization: options.authorization
827
- }),
828
- body: set,
829
- signal: timeoutSignal(PUSH_TIMEOUT_MS, options.signal)
830
- });
831
- } catch {
832
- return {
833
- ok: false,
834
- cause: "unavailable",
835
- retry: true
836
- };
837
- }
838
- if (response.ok) {
839
- await response.body?.cancel();
840
- return { ok: true };
1079
+ function readProperties(body, previous) {
1080
+ let delivery = previous?.delivery ?? { method: "urn:ietf:rfc:8936" };
1081
+ if (body["delivery"] !== void 0) {
1082
+ const read = readDelivery(body["delivery"]);
1083
+ if (typeof read === "string") return read;
1084
+ delivery = read;
841
1085
  }
842
- const { err, description } = await errorBody(response);
843
- if (response.status === 429 || response.status >= 500) return compact({
844
- ok: false,
845
- cause: "unavailable",
846
- description,
847
- retry: true
1086
+ const requested = body["events_requested"];
1087
+ if (requested !== void 0 && !(Array.isArray(requested) && requested.every((event) => typeof event === "string"))) return "events_requested must be an array of strings";
1088
+ const description = body["description"];
1089
+ if (description !== void 0 && typeof description !== "string") return "description must be a string";
1090
+ return compact({
1091
+ delivery,
1092
+ events_requested: requested ?? previous?.events_requested ?? [],
1093
+ description: description ?? previous?.description
848
1094
  });
849
- const cause = (response.status === 401 ? "authentication-failed" : response.status === 403 ? "access-denied" : void 0) ?? (err !== void 0 && Object.hasOwn(ERR_CAUSES, err) ? ERR_CAUSES[err] : void 0) ?? "invalid-request";
1095
+ }
1096
+ function propertiesOf(configuration) {
850
1097
  return compact({
851
- ok: false,
852
- cause,
853
- description,
854
- retry: false
1098
+ delivery: configuration.delivery,
1099
+ events_requested: configuration.events_requested ?? [],
1100
+ description: configuration.description
855
1101
  });
856
1102
  }
857
- function reason(value) {
858
- return typeof value === "string" ? { en: value } : value;
1103
+ async function readBody(request) {
1104
+ const read = await readBodyText(request, MAX_BODY_BYTES);
1105
+ if (!read.ok) return problemResponse(statusProblem(413, `request body exceeds ${MAX_BODY_BYTES} bytes`));
1106
+ let parsed;
1107
+ try {
1108
+ parsed = JSON.parse(read.text);
1109
+ } catch {
1110
+ return validationProblem("body was not valid JSON");
1111
+ }
1112
+ return isRecord(parsed) ? parsed : validationProblem("body must be a JSON object");
859
1113
  }
860
- function caep(name, input, extra) {
861
- return Object.freeze({
862
- type: `${CAEP_PREFIX}${name}`,
863
- subject: input.subject,
864
- payload: Object.freeze(compact({
865
- event_timestamp: input.eventTimestamp ?? epochSeconds(),
866
- initiating_entity: input.initiatingEntity,
867
- reason_admin: reason(input.reasonAdmin),
868
- reason_user: reason(input.reasonUser),
869
- ...extra
1114
+ async function owned(streams, id, owner) {
1115
+ if (typeof id !== "string" || id === "") return validationProblem("stream_id is required");
1116
+ const stream = await streams.get(id);
1117
+ return stream?.owner === owner ? stream : notFoundProblem();
1118
+ }
1119
+ /**
1120
+ * Acknowledges every pending SET of `stream`; a queue that never empties is
1121
+ * read at most until it repeats.
1122
+ */
1123
+ async function drain(queue, stream) {
1124
+ let previous;
1125
+ for (;;) {
1126
+ const pending = await queue.pending(stream, BATCH);
1127
+ const first = pending[0]?.jti;
1128
+ if (first === void 0 || first === previous) return;
1129
+ previous = first;
1130
+ await Promise.all(pending.map(({ jti }) => Promise.resolve(queue.ack(stream, jti))));
1131
+ }
1132
+ }
1133
+ /**
1134
+ * Pushes the SETs a paused push stream held, oldest first, until one may be
1135
+ * retried.
1136
+ */
1137
+ async function flush(queue, configuration, fetchFn) {
1138
+ const { stream_id: stream, delivery } = configuration;
1139
+ if (delivery.endpoint_url === void 0) return;
1140
+ let previous;
1141
+ for (;;) {
1142
+ const pending = await queue.pending(stream, BATCH);
1143
+ const first = pending[0]?.jti;
1144
+ if (first === void 0 || first === previous) return;
1145
+ previous = first;
1146
+ for (const { jti, set } of pending) {
1147
+ const result = await pushSet(set, compact({
1148
+ endpoint: delivery.endpoint_url,
1149
+ authorization: delivery.authorization_header,
1150
+ fetch: fetchFn
1151
+ }));
1152
+ if (result.ok) await queue.ack(stream, jti);
1153
+ else if (result.retry) return;
1154
+ else await queue.fail(stream, jti, {
1155
+ err: result.cause.replaceAll("-", "_"),
1156
+ description: result.description ?? result.cause
1157
+ });
1158
+ }
1159
+ }
1160
+ }
1161
+ async function deliver(stream, status, jti, set, options) {
1162
+ const { stream_id: id, delivery } = stream.configuration;
1163
+ if (delivery.method === "urn:ietf:rfc:8936" || status === "paused" || delivery.endpoint_url === void 0) {
1164
+ await options.queue.enqueue(id, jti, set);
1165
+ return {
1166
+ stream: id,
1167
+ jti,
1168
+ queued: true,
1169
+ delivery: { ok: true }
1170
+ };
1171
+ }
1172
+ return {
1173
+ stream: id,
1174
+ jti,
1175
+ queued: false,
1176
+ delivery: await pushSet(set, compact({
1177
+ endpoint: delivery.endpoint_url,
1178
+ authorization: delivery.authorization_header,
1179
+ fetch: options.fetch
870
1180
  }))
871
- });
1181
+ };
872
1182
  }
873
- /** CAEP 1.0 event builders; each returns a `SetEvent` for `signSet`. */
874
- const caepEvents = Object.freeze({
875
- sessionRevoked: (input) => caep("session-revoked", input, {}),
876
- credentialChange: (input) => caep("credential-change", input, compact({
877
- credential_type: input.credentialType,
878
- change_type: input.changeType,
879
- friendly_name: input.friendlyName,
880
- x509_issuer: input.x509Issuer,
881
- x509_serial: input.x509Serial,
882
- fido2_aaguid: input.fido2Aaguid
883
- })),
884
- tokenClaimsChange: (input) => caep("token-claims-change", input, { claims: input.claims }),
885
- assuranceLevelChange: (input) => caep("assurance-level-change", input, compact({
886
- namespace: input.namespace,
887
- current_level: input.currentLevel,
888
- previous_level: input.previousLevel,
889
- change_direction: input.changeDirection
890
- })),
891
- deviceComplianceChange: (input) => caep("device-compliance-change", input, {
892
- previous_status: input.previousStatus,
893
- current_status: input.currentStatus
894
- })
895
- });
896
- function risc(name, subject, payload) {
897
- return Object.freeze({
898
- type: `${RISC_PREFIX}${name}`,
899
- subject,
900
- payload: Object.freeze(payload)
901
- });
1183
+ /**
1184
+ * Signs `event` once per distinct stream audience and delivers it to every
1185
+ * stream that is not disabled and has the event in `events_delivered`: a push
1186
+ * stream through `pushSet`, a poll stream or a paused stream into the queue.
1187
+ * Answers one row per stream that took the event.
1188
+ */
1189
+ async function fanOutSet(event, options) {
1190
+ const groups = /* @__PURE__ */ new Map();
1191
+ for (const stream of await options.streams.list()) {
1192
+ const { configuration } = stream;
1193
+ const status = (await options.streams.status(configuration.stream_id))?.status;
1194
+ const delivered = configuration.events_delivered ?? configuration.events_requested ?? [];
1195
+ if (status === void 0 || status === "disabled" || !delivered.includes(event.type)) continue;
1196
+ const key = JSON.stringify(configuration.aud);
1197
+ const group = groups.get(key) ?? {
1198
+ audience: configuration.aud,
1199
+ targets: []
1200
+ };
1201
+ group.targets.push({
1202
+ stream,
1203
+ status
1204
+ });
1205
+ groups.set(key, group);
1206
+ }
1207
+ return (await Promise.all([...groups.values()].map(async ({ audience, targets }) => {
1208
+ const jti = globalThis.crypto.randomUUID();
1209
+ const set = await signSet(event, options.signer, {
1210
+ audience,
1211
+ jti
1212
+ });
1213
+ return Promise.all(targets.map(({ stream, status }) => deliver(stream, status, jti, set, options)));
1214
+ }))).flat();
902
1215
  }
903
- /** RISC 1.0 event builders for the events PermDock's receiver treats as revoking every session. */
904
- const riscEvents = Object.freeze({
905
- accountDisabled: (input) => risc("account-disabled", input.subject, compact({ reason: input.reason })),
906
- accountPurged: (input) => risc("account-purged", input.subject, {}),
907
- credentialCompromise: (input) => risc("credential-compromise", input.subject, compact({
908
- credential_type: input.credentialType,
909
- event_timestamp: input.eventTimestamp ?? epochSeconds(),
910
- initiating_entity: input.initiatingEntity,
911
- reason_admin: reason(input.reasonAdmin),
912
- reason_user: reason(input.reasonUser)
913
- }))
914
- });
915
1216
  /**
916
- * The SSF 1.0 section 8.1.4 verification event for `stream`, echoing the
917
- * receiver's `state`. Its subject is the stream, never a principal.
1217
+ * An SSF 1.0 transmitter as one Fetch handler, routed by path suffix:
1218
+ * `/.well-known/ssf-configuration` (section 7.1), `/stream` (8.1.1), `/status`
1219
+ * (8.1.2), `/verify` (8.1.4) and `/poll` (RFC 8936). Each receiver sees only
1220
+ * the streams it created. Disabling or deleting a stream drops its pending
1221
+ * SETs; a paused stream holds them until it is enabled again.
918
1222
  */
919
- function streamVerificationEvent(stream, state) {
920
- return Object.freeze({
921
- type: VERIFICATION_EVENT,
922
- subject: Object.freeze({
923
- format: "opaque",
924
- id: stream
925
- }),
926
- payload: Object.freeze(compact({ state }))
1223
+ function ssfTransmitter(options) {
1224
+ const base = (options.endpoint ?? options.issuer).replace(/\/+$/u, "");
1225
+ const supported = options.eventsSupported ?? knownEventTypes();
1226
+ const audienceOf = options.audience ?? ((receiver) => receiver);
1227
+ const cap = options.maxEvents ?? 100;
1228
+ const { streams, queue } = options;
1229
+ const metadata = compact({
1230
+ spec_version: "1_0",
1231
+ issuer: options.issuer,
1232
+ jwks_uri: options.jwksUri,
1233
+ delivery_methods_supported: [SSF_PUSH_DELIVERY, SSF_POLL_DELIVERY],
1234
+ configuration_endpoint: `${base}/stream`,
1235
+ status_endpoint: `${base}/status`,
1236
+ verification_endpoint: `${base}/verify`,
1237
+ authorization_schemes: [{ spec_urn: "urn:ietf:rfc:6750" }],
1238
+ default_subjects: "ALL"
1239
+ });
1240
+ const configurationOf = (id, owner, properties) => compact({
1241
+ stream_id: id,
1242
+ iss: options.issuer,
1243
+ aud: audienceOf(owner),
1244
+ events_supported: supported,
1245
+ events_requested: properties.events_requested,
1246
+ events_delivered: properties.events_requested.filter((event) => supported.includes(event)),
1247
+ delivery: properties.delivery.method === "urn:ietf:rfc:8936" ? {
1248
+ method: SSF_POLL_DELIVERY,
1249
+ endpoint_url: `${base}/poll?stream_id=${encodeURIComponent(id)}`
1250
+ } : properties.delivery,
1251
+ description: properties.description
927
1252
  });
1253
+ const stream = async (request, url, owner) => {
1254
+ switch (request.method) {
1255
+ case "GET": {
1256
+ const id = url.searchParams.get("stream_id");
1257
+ if (id === null) return jsonResponse(200, (await streams.list(owner)).map((entry) => entry.configuration));
1258
+ const found = await owned(streams, id, owner);
1259
+ return found instanceof Response ? found : jsonResponse(200, found.configuration);
1260
+ }
1261
+ case "POST": {
1262
+ const body = await readBody(request);
1263
+ if (body instanceof Response) return body;
1264
+ const properties = readProperties(body);
1265
+ if (typeof properties === "string") return validationProblem(properties);
1266
+ const configuration = configurationOf(globalThis.crypto.randomUUID(), owner, properties);
1267
+ await streams.create(owner, configuration);
1268
+ return jsonResponse(201, configuration);
1269
+ }
1270
+ case "PATCH":
1271
+ case "PUT": {
1272
+ const body = await readBody(request);
1273
+ if (body instanceof Response) return body;
1274
+ const found = await owned(streams, body["stream_id"], owner);
1275
+ if (found instanceof Response) return found;
1276
+ const properties = readProperties(body, request.method === "PATCH" ? propertiesOf(found.configuration) : void 0);
1277
+ if (typeof properties === "string") return validationProblem(properties);
1278
+ const configuration = configurationOf(found.configuration.stream_id, owner, properties);
1279
+ await streams.update(configuration);
1280
+ return jsonResponse(200, configuration);
1281
+ }
1282
+ case "DELETE": {
1283
+ const found = await owned(streams, url.searchParams.get("stream_id"), owner);
1284
+ if (found instanceof Response) return found;
1285
+ await streams.delete(found.configuration.stream_id);
1286
+ await drain(queue, found.configuration.stream_id);
1287
+ return new Response(null, { status: 204 });
1288
+ }
1289
+ default: return methodNotAllowed("GET, POST, PATCH, PUT, DELETE");
1290
+ }
1291
+ };
1292
+ const statusOf = async (id) => await streams.status(id) ?? {
1293
+ stream_id: id,
1294
+ status: "enabled"
1295
+ };
1296
+ const status = async (request, url, owner) => {
1297
+ if (request.method === "GET") {
1298
+ const found = await owned(streams, url.searchParams.get("stream_id"), owner);
1299
+ return found instanceof Response ? found : jsonResponse(200, await statusOf(found.configuration.stream_id));
1300
+ }
1301
+ if (request.method !== "POST") return methodNotAllowed("GET, POST");
1302
+ const body = await readBody(request);
1303
+ if (body instanceof Response) return body;
1304
+ const found = await owned(streams, body["stream_id"], owner);
1305
+ if (found instanceof Response) return found;
1306
+ const next = body["status"];
1307
+ const reason = body["reason"];
1308
+ if (!isStatus(next)) return validationProblem(`status must be one of ${STATUSES.join(", ")}`);
1309
+ if (reason !== void 0 && typeof reason !== "string") return validationProblem("reason must be a string");
1310
+ const id = found.configuration.stream_id;
1311
+ const before = await statusOf(id);
1312
+ const updated = compact({
1313
+ stream_id: id,
1314
+ status: next,
1315
+ reason
1316
+ });
1317
+ await streams.setStatus(updated);
1318
+ if (next === "disabled") await drain(queue, id);
1319
+ else if (next === "enabled" && before.status === "paused" && found.configuration.delivery.method === "urn:ietf:rfc:8935") await flush(queue, found.configuration, options.fetch);
1320
+ return jsonResponse(200, updated);
1321
+ };
1322
+ const verify = async (request, owner) => {
1323
+ if (request.method !== "POST") return methodNotAllowed("POST");
1324
+ const body = await readBody(request);
1325
+ if (body instanceof Response) return body;
1326
+ const found = await owned(streams, body["stream_id"], owner);
1327
+ if (found instanceof Response) return found;
1328
+ const state = body["state"];
1329
+ if (state !== void 0 && typeof state !== "string") return validationProblem("state must be a string");
1330
+ const { configuration } = found;
1331
+ const current = await statusOf(configuration.stream_id);
1332
+ if (current.status === "disabled") return problemResponse(statusProblem(409, "stream is disabled"));
1333
+ const jti = globalThis.crypto.randomUUID();
1334
+ const set = await signSet(streamVerificationEvent(configuration.stream_id, state), options.signer, {
1335
+ audience: configuration.aud,
1336
+ jti
1337
+ });
1338
+ await deliver(found, current.status, jti, set, options);
1339
+ return new Response(null, { status: 204 });
1340
+ };
1341
+ const poll = async (request, url, owner) => {
1342
+ const id = url.searchParams.get("stream_id");
1343
+ const found = id === null ? null : await streams.get(id);
1344
+ if (found?.owner !== owner || found.configuration.delivery.method !== "urn:ietf:rfc:8936") return notFoundProblem();
1345
+ const current = await statusOf(found.configuration.stream_id);
1346
+ return setPollHandler({
1347
+ queue,
1348
+ authorize: () => found.configuration.stream_id,
1349
+ maxEvents: current.status === "enabled" ? cap : 0
1350
+ })(request);
1351
+ };
1352
+ return async (request) => {
1353
+ const url = new URL(request.url);
1354
+ const path = url.pathname.replace(/\/+$/u, "");
1355
+ if (path.endsWith("/.well-known/ssf-configuration")) return request.method === "GET" ? jsonResponse(200, metadata) : methodNotAllowed("GET");
1356
+ let owner;
1357
+ try {
1358
+ owner = await options.authorize(request);
1359
+ } catch {
1360
+ owner = null;
1361
+ }
1362
+ if (owner === null) return problemResponse(statusProblem(401, "stream management not authorized"), void 0, void 0, { "WWW-Authenticate": "Bearer" });
1363
+ if (path.endsWith("/stream")) return stream(request, url, owner);
1364
+ if (path.endsWith("/status")) return status(request, url, owner);
1365
+ if (path.endsWith("/verify")) return verify(request, owner);
1366
+ if (path.endsWith("/poll")) return poll(request, url, owner);
1367
+ return notFoundProblem();
1368
+ };
928
1369
  }
929
1370
  //#endregion
930
- export { SSF_POLL_DELIVERY, SSF_PUSH_DELIVERY, caepEvents, createPermDock, memoryReplayStore, memorySetQueue, pushSet, riscEvents, setPollHandler, signSet, streamVerificationEvent };
1371
+ export { SSF_POLL_DELIVERY, SSF_PUSH_DELIVERY, caepEvents, createPermDock, fanOutSet, memoryReplayStore, memorySetQueue, memorySsfStreamStore, pollSets, pushSet, riscEvents, setPollHandler, signSet, ssfTransmitter, streamVerificationEvent };