@classytic/arc 2.28.0 → 2.31.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 (239) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -0
  3. package/TRADEMARK.md +22 -0
  4. package/dist/{BaseController-B65zbz9m.mjs → BaseController-De7GqHck.mjs} +25 -24
  5. package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
  6. package/dist/EventTransport-9mlTgqzE.mjs +104 -0
  7. package/dist/{HookSystem-C1vB_Gc9.mjs → HookSystem-BcmPyq5I.mjs} +16 -35
  8. package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
  9. package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-qq0mn2s9.mjs} +3 -2
  10. package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-BE5NwaQk.mjs} +1 -0
  11. package/dist/audit/index.d.mts +3 -2
  12. package/dist/audit/index.mjs +3 -2
  13. package/dist/auth/audit.d.mts +1 -0
  14. package/dist/auth/audit.mjs +1 -0
  15. package/dist/auth/index.d.mts +5 -4
  16. package/dist/auth/index.mjs +6 -5
  17. package/dist/auth/redis-session.d.mts +2 -1
  18. package/dist/auth/redis-session.mjs +1 -0
  19. package/dist/authorizationDecision-ChvUQGG1.mjs +266 -0
  20. package/dist/{buildHandler-Dtwd8fdz.mjs → buildHandler-CDrCJzmB.mjs} +34 -7
  21. package/dist/cache/index.d.mts +4 -3
  22. package/dist/cache/index.mjs +4 -3
  23. package/dist/{caching-_NJeDd1_.mjs → caching-BFHA6Scf.mjs} +2 -1
  24. package/dist/cleanup/index.d.mts +4 -3
  25. package/dist/cleanup/index.mjs +9 -13
  26. package/dist/cli/commands/describe.d.mts +2 -1
  27. package/dist/cli/commands/describe.mjs +3 -2
  28. package/dist/cli/commands/docs.d.mts +1 -0
  29. package/dist/cli/commands/docs.mjs +3 -2
  30. package/dist/cli/commands/doctor.d.mts +1 -0
  31. package/dist/cli/commands/doctor.mjs +1 -0
  32. package/dist/cli/commands/generate.d.mts +2 -1
  33. package/dist/cli/commands/generate.mjs +2 -1
  34. package/dist/cli/commands/init.d.mts +2 -1
  35. package/dist/cli/commands/init.mjs +2 -1
  36. package/dist/cli/commands/introspect.d.mts +1 -0
  37. package/dist/cli/commands/introspect.mjs +2 -1
  38. package/dist/cli/index.d.mts +3 -2
  39. package/dist/cli/index.mjs +3 -2
  40. package/dist/{constants-DNre0wRg.mjs → constants-D3Dv4LAV.mjs} +1 -0
  41. package/dist/context/index.d.mts +1 -0
  42. package/dist/context/index.mjs +3 -2
  43. package/dist/core/index.d.mts +3 -2
  44. package/dist/core/index.mjs +7 -5
  45. package/dist/{core-BGa8TXJR.mjs → core-BGpIxINN.mjs} +4 -49
  46. package/dist/{createActionRouter-C-N7z2EL.mjs → createActionRouter-CDXEdasl.mjs} +8 -7
  47. package/dist/{createAggregationRouter-wzwFa_dW.mjs → createAggregationRouter-KrQDzx-k.mjs} +10 -22
  48. package/dist/{createApp-Du5G54TM.mjs → createApp-Df89BEni.mjs} +505 -209
  49. package/dist/defineAggregation-DbPPS8RI.mjs +48 -0
  50. package/dist/{defineResource-2zvVVpxg.mjs → defineResource-Bv6EtN1x.mjs} +90 -72
  51. package/dist/discovery/index.d.mts +1 -0
  52. package/dist/discovery/index.mjs +1 -0
  53. package/dist/docs/index.d.mts +3 -2
  54. package/dist/docs/index.mjs +3 -2
  55. package/dist/{elevation-C9s5hFP_.d.mts → elevation-BXCfVcNG.d.mts} +1 -0
  56. package/dist/{elevation-CIz1GjGm.mjs → elevation-D2l1mh4g.mjs} +4 -3
  57. package/dist/encryption/index.d.mts +2 -1
  58. package/dist/encryption/index.mjs +3 -2
  59. package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-C5NeD6bT.mjs} +3 -2
  60. package/dist/{errorHandler-C6yv4ZTW.d.mts → errorHandler-CpYUJmPA.d.mts} +1 -0
  61. package/dist/{errors-DHcHVAgk.d.mts → errors-BGdVwP25.d.mts} +1 -0
  62. package/dist/{errors-DkO8Nk6-.mjs → errors-Cj42AntO.mjs} +1 -0
  63. package/dist/{eventPlugin-DrQ_FesK.mjs → eventPlugin-CkffEihm.mjs} +6 -106
  64. package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
  65. package/dist/events/index.d.mts +4 -3
  66. package/dist/events/index.mjs +17 -340
  67. package/dist/events/transports/redis-stream-entry.d.mts +2 -1
  68. package/dist/events/transports/redis-stream-entry.mjs +1 -0
  69. package/dist/events/transports/redis.d.mts +2 -1
  70. package/dist/events/transports/redis.mjs +1 -0
  71. package/dist/{externalPaths-BE6wFpYv.d.mts → externalPaths-CmGOxOtD.d.mts} +1 -0
  72. package/dist/factory/index.d.mts +9 -5
  73. package/dist/factory/index.mjs +7 -6
  74. package/dist/{fastify-augmentation-OzYGIiU1.d.mts → fastify-augmentation-zh0_AYHa.d.mts} +13 -4
  75. package/dist/{applyPermissionResult-BnyVE9eD.mjs → fields-CB5Cuzk9.mjs} +2 -107
  76. package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
  77. package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
  78. package/dist/{generate-D0wZupBg.mjs → generate-EcA6ui4i.mjs} +2 -1
  79. package/dist/{headers-BvlQSDMB.mjs → headers-3zvE0rM3.mjs} +2 -1
  80. package/dist/{health-CB_m4S32.mjs → health-DjZYjM7H.mjs} +1 -0
  81. package/dist/hooks/index.d.mts +2 -1
  82. package/dist/hooks/index.mjs +2 -1
  83. package/dist/idempotency/index.d.mts +3 -2
  84. package/dist/idempotency/index.mjs +5 -4
  85. package/dist/idempotency/redis.d.mts +2 -1
  86. package/dist/idempotency/redis.mjs +1 -0
  87. package/dist/{index-CjVg-Epg.d.mts → index-Bc2ox8_U.d.mts} +6 -5
  88. package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
  89. package/dist/{index-BMnbzvtO.d.mts → index-CEJNZFtX.d.mts} +242 -24
  90. package/dist/index-CFThn1K9.d.mts +224 -0
  91. package/dist/{index-DPRH0Cme.d.mts → index-CpzxqePp.d.mts} +203 -97
  92. package/dist/index.d.mts +9 -8
  93. package/dist/index.mjs +11 -9
  94. package/dist/{init-tlRSt667.mjs → init-BEiNZBsJ.mjs} +19 -23
  95. package/dist/{init-BPEu8cs-.d.mts → init-Cscs4lab.d.mts} +1 -0
  96. package/dist/integrations/event-gateway.d.mts +3 -2
  97. package/dist/integrations/event-gateway.mjs +2 -1
  98. package/dist/integrations/index.d.mts +4 -3
  99. package/dist/integrations/index.mjs +1 -0
  100. package/dist/integrations/jobs/index.d.mts +2 -1
  101. package/dist/integrations/jobs/index.mjs +108 -32
  102. package/dist/integrations/mcp/index.d.mts +9 -9
  103. package/dist/integrations/mcp/index.mjs +2 -1
  104. package/dist/integrations/mcp/testing.d.mts +3 -2
  105. package/dist/integrations/mcp/testing.mjs +2 -2
  106. package/dist/integrations/streamline.d.mts +1 -0
  107. package/dist/integrations/streamline.mjs +3 -2
  108. package/dist/integrations/webhooks.d.mts +1 -0
  109. package/dist/integrations/webhooks.mjs +1 -0
  110. package/dist/integrations/websocket-pushref-redis.d.mts +2 -1
  111. package/dist/integrations/websocket-pushref-redis.mjs +1 -0
  112. package/dist/integrations/websocket-redis.d.mts +2 -1
  113. package/dist/integrations/websocket-redis.mjs +1 -0
  114. package/dist/integrations/websocket.d.mts +3 -2
  115. package/dist/integrations/websocket.mjs +1 -0
  116. package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
  117. package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
  118. package/dist/{interface-n5hpKg1d.mjs → interface-DYzM0q-u.mjs} +1 -0
  119. package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-BYbLDi5D.mjs} +2 -1
  120. package/dist/{keys-Cd316u_y.mjs → keys-C0_pa1tY.mjs} +1 -0
  121. package/dist/{loadResources-DpU8pfjV.mjs → loadResources-yawi9tAE.mjs} +2 -1
  122. package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-BAjYZonx.mjs} +2 -1
  123. package/dist/logger/index.d.mts +1 -0
  124. package/dist/logger/index.mjs +1 -0
  125. package/dist/{mcpPlugin-Cs6nRGCt.mjs → mcpPlugin-B_es0hiF.mjs} +52 -60
  126. package/dist/{memory-CmnzXE5Z.mjs → memory-DR6wpa9F.mjs} +2 -1
  127. package/dist/{metrics-fdxI5mn_.mjs → metrics-CUdw_wLB.mjs} +2 -1
  128. package/dist/middleware/index.d.mts +2 -1
  129. package/dist/middleware/index.mjs +3 -2
  130. package/dist/migrations/index.d.mts +1 -3
  131. package/dist/migrations/index.mjs +2 -4
  132. package/dist/module-0pFJA6YW.mjs +78 -0
  133. package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-wOgj_fnj.mjs} +1 -0
  134. package/dist/{openapi-BLV4OMXb.mjs → openapi-B2L4js1v.mjs} +6 -5
  135. package/dist/permissions/index.d.mts +5 -4
  136. package/dist/permissions/index.mjs +6 -4
  137. package/dist/{permissions-BrtiBKGs.mjs → permissions-L--QDAir.mjs} +518 -316
  138. package/dist/{pipe-BOLmGIxa.mjs → pipe-DRDNsI2T.mjs} +2 -1
  139. package/dist/pipeline/index.d.mts +2 -1
  140. package/dist/pipeline/index.mjs +2 -1
  141. package/dist/{pipeline-BGRnV-To.mjs → pipeline-UPQFatit.mjs} +7 -20
  142. package/dist/plugins/index.d.mts +8 -7
  143. package/dist/plugins/index.mjs +16 -15
  144. package/dist/plugins/response-cache.d.mts +1 -0
  145. package/dist/plugins/response-cache.mjs +2 -1
  146. package/dist/plugins/tracing-entry.d.mts +2 -1
  147. package/dist/plugins/tracing-entry.mjs +2 -1
  148. package/dist/{pluralize-BhrgwZb9.mjs → pluralize-O0FZgESl.mjs} +1 -0
  149. package/dist/{preloadResources-CM4uUaFv.d.mts → preloadResources-CyoJMSiO.d.mts} +117 -12
  150. package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-Dz6BjzM6.mjs} +1 -0
  151. package/dist/presets/filesUpload.d.mts +6 -5
  152. package/dist/presets/filesUpload.mjs +9 -11
  153. package/dist/presets/index.d.mts +15 -2
  154. package/dist/presets/index.mjs +2 -1
  155. package/dist/presets/multiTenant.d.mts +2 -1
  156. package/dist/presets/multiTenant.mjs +3 -2
  157. package/dist/presets/search.d.mts +3 -2
  158. package/dist/presets/search.mjs +2 -1
  159. package/dist/{presets-DwFDVKP0.mjs → presets-C4-g4_4P.mjs} +27 -10
  160. package/dist/projection-BHw6xlOQ.mjs +18 -0
  161. package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
  162. package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-BZr8v46E.mjs} +5 -4
  163. package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
  164. package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-CMPY5Qms.mjs} +7 -3
  165. package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-Dn5JNmkj.mjs} +1 -0
  166. package/dist/{realtime-DEuDu9io.mjs → realtime-C5NoxWFY.mjs} +20 -8
  167. package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
  168. package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
  169. package/dist/{registerRoute-DTp18Ah_.mjs → registerRoute-CBN84fc7.mjs} +5 -2
  170. package/dist/registry/index.d.mts +3 -2
  171. package/dist/registry/index.mjs +3 -2
  172. package/dist/{registry-9km_w1aP.mjs → registry-4213U4zb.mjs} +3 -2
  173. package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-Dll8mGgc.mjs} +1 -0
  174. package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DIiZKGUt.mjs} +2 -1
  175. package/dist/repositoryFilter-f9eAfq_l.mjs +45 -0
  176. package/dist/{requestContext-MrlJwECf.mjs → requestContext-2TxXOJ7T.mjs} +1 -0
  177. package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-CUsjNX9R.mjs} +1 -0
  178. package/dist/{schedules-CjOd2MG9.mjs → schedules-DdtlICTf.mjs} +3 -2
  179. package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-D--wdJM-.mjs} +70 -17
  180. package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-Bm2enbnh.mjs} +2 -1
  181. package/dist/schemas/index.d.mts +1 -0
  182. package/dist/schemas/index.mjs +1 -0
  183. package/dist/scim/index.d.mts +1 -0
  184. package/dist/scim/index.mjs +2 -1
  185. package/dist/scope/index.d.mts +3 -2
  186. package/dist/scope/index.mjs +5 -4
  187. package/dist/{scope-DfaPntpo.mjs → scope-DHx5Fous.mjs} +4 -3
  188. package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
  189. package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-DjQJ7FKA.mjs} +1 -0
  190. package/dist/{sse-BQ1w0dfl.mjs → sse-CUTo9y0X.mjs} +5 -4
  191. package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B_5XcVVd.mjs} +2 -1
  192. package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
  193. package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-D1MP_gRG.mjs} +1 -0
  194. package/dist/{streaming-BQcW6_Kq.mjs → streaming-PSZwi8JV.mjs} +1 -0
  195. package/dist/subscribe-helpers-C0Tb2aUp.mjs +340 -0
  196. package/dist/sync/changelog.d.mts +1 -0
  197. package/dist/sync/changelog.mjs +1 -0
  198. package/dist/testing/cleanupStoreContract.d.mts +2 -1
  199. package/dist/testing/cleanupStoreContract.mjs +1 -0
  200. package/dist/testing/index.d.mts +167 -12
  201. package/dist/testing/index.mjs +522 -205
  202. package/dist/testing/outboxStoreContract.d.mts +1 -0
  203. package/dist/testing/outboxStoreContract.mjs +1 -0
  204. package/dist/testing/storageContract.d.mts +2 -1
  205. package/dist/testing/storageContract.mjs +1 -0
  206. package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
  207. package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-dAfBVUrk.mjs} +1 -0
  208. package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B0ryPo3I.mjs} +1 -0
  209. package/dist/types/index.d.mts +6 -5
  210. package/dist/types/index.mjs +1 -0
  211. package/dist/types/storage.d.mts +2 -1
  212. package/dist/types/storage.mjs +1 -0
  213. package/dist/{types-Dmw-6Qeo.d.mts → types-B7XeLEgK.d.mts} +127 -90
  214. package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
  215. package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
  216. package/dist/{types-Cu6vVJmh.d.mts → types-CBgvkp8O.d.mts} +82 -12
  217. package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
  218. package/dist/{types-QFGc3Cjv.d.mts → types-CwcUQ610.d.mts} +2 -6
  219. package/dist/{types-CSyCxl2V.mjs → types-Cys0ko9Z.mjs} +4 -3
  220. package/dist/usage/index.d.mts +3 -2
  221. package/dist/usage/index.mjs +0 -0
  222. package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-ChYJ6CdK.mjs} +1 -0
  223. package/dist/utils/index.d.mts +16 -10
  224. package/dist/utils/index.mjs +10 -9
  225. package/dist/{utils-taUVD4p3.mjs → utils-vL8BrDE2.mjs} +3 -2
  226. package/dist/{validate-Bk44F2yT.mjs → validate-_KbifpHF.mjs} +2 -1
  227. package/dist/{versioning-gKWyryT3.mjs → versioning-CHDTor3P.mjs} +3 -2
  228. package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
  229. package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
  230. package/package.json +15 -7
  231. package/skills/arc/SKILL.md +22 -8
  232. package/skills/arc/references/api-reference.md +4 -0
  233. package/skills/arc/references/auth.md +3 -0
  234. package/skills/arc/references/integrations.md +33 -0
  235. package/skills/arc/references/mcp.md +6 -7
  236. package/skills/arc/references/production.md +24 -25
  237. package/skills/arc-code-review/references/anti-patterns.md +3 -3
  238. package/dist/index-CZY4EGga.d.mts +0 -107
  239. package/dist/module-_-M7C5ES.mjs +0 -29
@@ -1,5 +1,6 @@
1
- import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-Uk8ONJv7.mjs";
2
- import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-UDtLaNj6.mjs";
1
+
2
+ import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-DEWNOMza.mjs";
3
+ import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-CduhKsJi.mjs";
3
4
  import { FastifyPluginAsync } from "fastify";
4
5
  import { RepositoryLike } from "@classytic/repo-core/adapter";
5
6
  //#region src/idempotency/idempotencyPlugin.d.ts
@@ -1,9 +1,10 @@
1
- import { n as requireSingleHeaderValue } from "../headers-BvlQSDMB.mjs";
2
- import { n as createSafeGetOne, t as createIsDuplicateKeyError } from "../store-helpers-DY6xq4sM.mjs";
3
- import { t as createIdempotencyResult } from "../interface-n5hpKg1d.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { n as requireSingleHeaderValue } from "../headers-3zvE0rM3.mjs";
3
+ import { n as createSafeGetOne, t as createIsDuplicateKeyError } from "../store-helpers-D1MP_gRG.mjs";
4
+ import { t as createIdempotencyResult } from "../interface-DYzM0q-u.mjs";
5
+ import { and, eq, exists, gt, lt, or, startsWith } from "@classytic/repo-core/filter";
4
6
  import { createHash } from "node:crypto";
5
7
  import fp from "fastify-plugin";
6
- import { and, eq, exists, gt, lt, or, startsWith } from "@classytic/repo-core/filter";
7
8
  import { update } from "@classytic/repo-core/update";
8
9
  //#region src/idempotency/repository-idempotency-adapter.ts
9
10
  function repositoryAsIdempotencyStore(repository, defaultTtlMs) {
@@ -1,2 +1,3 @@
1
- import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-UDtLaNj6.mjs";
1
+
2
+ import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-CduhKsJi.mjs";
2
3
  export { type IoredisLike, type RedisClient, RedisIdempotencyStore, type RedisIdempotencyStoreOptions, type UpstashRedisLike, ioredisAsIdempotencyClient, upstashAsIdempotencyClient };
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/idempotency/stores/redis.ts
2
3
  var RedisIdempotencyStore = class {
3
4
  name = "redis";
@@ -1,7 +1,8 @@
1
- import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, H as CrudController, L as RequestWithExtras, Lt as IController, Rt as IControllerResponse, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig, zt as IRequestContext } from "./index-DPRH0Cme.mjs";
2
- import { i as RequestScope } from "./types-DjC-KUCz.mjs";
3
- import { c as AnyRecord, t as PermissionCheck } from "./types-Dmw-6Qeo.mjs";
4
- import "./fastify-augmentation-OzYGIiU1.mjs";
1
+
2
+ import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, H as CrudController, L as RequestWithExtras, Lt as IController, Rt as IControllerResponse, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig, zt as IRequestContext } from "./index-CpzxqePp.mjs";
3
+ import { i as RequestScope } from "./types-ChuShpCP.mjs";
4
+ import { l as AnyRecord, r as PermissionCheck } from "./types-B7XeLEgK.mjs";
5
+ import "./fastify-augmentation-zh0_AYHa.mjs";
5
6
  import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
6
7
  import { z } from "zod";
7
8
  import { DataAdapter } from "@classytic/repo-core/adapter";
@@ -170,7 +171,7 @@ declare function defineAction<TSchema extends z.ZodTypeAny | undefined = undefin
170
171
  //#endregion
171
172
  //#region src/core/defineResource/seams.d.ts
172
173
  /**
173
- * Structural adapter boundary — the `ControllerLike` pattern (v2.10.6)
174
+ * Structural adapter boundary — the `ControllerLike` pattern
174
175
  * applied to adapters. `DataAdapter<T>` is invariant in `T`, so a
175
176
  * `DataAdapter<HydratedDocument<IProduct>>` built by the HOST does not
176
177
  * assign to a module's `DataAdapter<AnyRecord>` slot; before this type,
@@ -1,3 +1,5 @@
1
+
2
+ import { r as PermissionCheck } from "./types-B7XeLEgK.mjs";
1
3
  import { FastifyPluginAsync } from "fastify";
2
4
  //#region src/integrations/jobs/execution.d.ts
3
5
  /**
@@ -43,18 +45,6 @@ interface ExecuteTimedHandlerOptions<T> {
43
45
  declare function executeTimedHandler<T>(options: ExecuteTimedHandlerOptions<T>): Promise<T>;
44
46
  //#endregion
45
47
  //#region src/integrations/jobs/types.d.ts
46
- /**
47
- * Job queue integration — public contract (definitions, meta, dispatcher).
48
- *
49
- * Directory map (mechanical split of the former single file):
50
- * types.ts — this contract + `defineJob`
51
- * execution.ts — `executeTimedHandler` (timeout / cancellation / bulkhead)
52
- * repeat.ts — repeatable-schedule reconciliation (boot hygiene)
53
- * plugin.ts — BullMQ wiring (queues, workers, DLQ, routes, shutdown)
54
- * index.ts — public barrel; `src/integrations/jobs.ts` re-exports it
55
- * so the package subpath is unchanged
56
- */
57
- /** Repeat schedule — cron pattern or fixed interval. Explicit timezone is required. */
58
48
  interface JobRepeatOptions {
59
49
  /** Cron pattern (e.g. '0 9 * * *' = every day 09:00). Mutually exclusive with `every`. */
60
50
  pattern?: string;
@@ -177,6 +167,61 @@ interface JobsPluginOptions {
177
167
  jobs: JobDefinition[];
178
168
  /** URL prefix for job management endpoints (default: '/jobs') */
179
169
  prefix?: string;
170
+ /**
171
+ * Job management HTTP endpoints (`GET <prefix>/stats`,
172
+ * `GET <prefix>/:queue/:id/status`).
173
+ *
174
+ * **Disabled by default.** A job status carries `returnValue` and
175
+ * `failedReason` — the handler's own output and error text, which routinely
176
+ * hold export URLs, billing results, model output, recipient addresses, or
177
+ * internal stack detail. Serving that unauthenticated turns a job id into a
178
+ * read primitive over other tenants' work.
179
+ *
180
+ * Enable it deliberately, with a permission check:
181
+ *
182
+ * ```ts
183
+ * managementRoutes: { operatorPermission: requireRoles(["platform-ops"]) }
184
+ * ```
185
+ *
186
+ * Queue-level counts are also available through the metrics/health
187
+ * integration, which does not expose individual jobs.
188
+ */
189
+ managementRoutes?: false | {
190
+ /**
191
+ * REQUIRED — arc will not mount an unguarded management surface.
192
+ *
193
+ * **This is an OPERATOR surface, not a tenant-facing one.** A BullMQ job
194
+ * carries no framework-level tenant identity, and `getStatus` fetches
195
+ * straight by queue + id, so a row-level `policy` on the decision has
196
+ * nothing to filter: `requireOrgRole("manager")` would let a manager in
197
+ * org A read a known job handle from org B. `/stats` is inherently
198
+ * global for the same reason.
199
+ *
200
+ * Gate it on an operator role — `requireRoles(["platform-ops"])` — and
201
+ * keep tenant-facing job status in a resource that owns its own row
202
+ * policy. Arc REFUSES a request whose decision carries a `policy`
203
+ * rather than silently ignoring it.
204
+ */
205
+ operatorPermission: PermissionCheck;
206
+ /**
207
+ * Accept an `operatorPermission` that arc cannot prove is platform-only.
208
+ *
209
+ * By default the gate must carry `_platformOnly` (i.e. come from
210
+ * `requirePlatformRole`), because that property is unprovable from
211
+ * outside: `requireOrgRole("manager")` and the default
212
+ * `requireRoles(["ops"])` both return a bare allow with no policy, so a
213
+ * manager in org A passes and reads a known handle from org B. Boot fails
214
+ * rather than serving a surface whose guard reads as tenant-scoped.
215
+ *
216
+ * Set this only for a custom check you have verified consults platform
217
+ * identity alone.
218
+ */
219
+ allowUnverifiedOperatorPermission?: boolean;
220
+ /** Include the handler's return value in a status response. Default `false`. */
221
+ exposeResult?: boolean;
222
+ /** Include `failedReason` in a status response. Default `false`. */
223
+ exposeFailureReason?: boolean;
224
+ };
180
225
  /** Bridge job events to Arc's event bus (default: true) */
181
226
  bridgeEvents?: boolean;
182
227
  /** Default job options applied to all jobs */
@@ -192,19 +237,30 @@ interface JobsPluginOptions {
192
237
  };
193
238
  }
194
239
  interface JobDispatcher {
195
- dispatch<TData = unknown>(name: string, data: TData, options?: JobDispatchOptions): Promise<{
196
- jobId: string;
197
- }>;
240
+ dispatch<TData = unknown>(name: string, data: TData, options?: JobDispatchOptions): Promise<JobHandle>;
198
241
  getQueue(name: string): unknown | null;
199
242
  getStats(): Promise<Record<string, QueueStats>>;
200
243
  /**
201
244
  * Fetch a point-in-time status snapshot for a job by its ID.
202
- * Searches across all registered queues.
203
- * Returns `null` if the job doesn't exist or has been removed by retention policy.
245
+ * QUEUE-QUALIFIED: BullMQ job ids are local to their queue, so an id alone
246
+ * cannot identify a job. `dispatch()` returns the queue name alongside the id
247
+ * for exactly this reason.
248
+ *
249
+ * Returns `null` if the queue is not registered, or the job doesn't exist /
250
+ * has been removed by retention policy.
204
251
  */
205
- getStatus(jobId: string): Promise<JobStatus | null>;
252
+ getStatus(queue: string, jobId: string): Promise<JobStatus | null>;
206
253
  close(): Promise<void>;
207
254
  }
255
+ /**
256
+ * A dispatched job's address. The queue is part of the identity because BullMQ
257
+ * ids are queue-local — two queues can both hold `"123"`.
258
+ */
259
+ interface JobHandle {
260
+ /** Registered job name (= queue name). */
261
+ queue: string;
262
+ jobId: string;
263
+ }
208
264
  interface QueueStats {
209
265
  waiting: number;
210
266
  active: number;
@@ -1,6 +1,7 @@
1
- import { r as CacheStore, t as CacheLogger } from "./interface-BGZCzOGL.mjs";
2
- import { i as RequestScope, n as Mandate } from "./types-DjC-KUCz.mjs";
3
- import { n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-Dmw-6Qeo.mjs";
1
+
2
+ import { r as CacheStore, t as CacheLogger } from "./interface-BOk3YnTz.mjs";
3
+ import { i as RequestScope, n as Mandate } from "./types-ChuShpCP.mjs";
4
+ import { i as PermissionContext, r as PermissionCheck, t as AuthorizationDecision } from "./types-B7XeLEgK.mjs";
4
5
  import { FastifyReply, FastifyRequest } from "fastify";
5
6
  //#region src/permissions/agent.d.ts
6
7
  /**
@@ -162,13 +163,37 @@ interface RequireAgentScopeOptions<TDoc = Record<string, unknown>> extends Requi
162
163
  */
163
164
  declare function requireAgentScope<TDoc = Record<string, unknown>>(opts: RequireAgentScopeOptions<TDoc>): PermissionCheck<TDoc>;
164
165
  //#endregion
165
- //#region src/permissions/applyPermissionResult.d.ts
166
+ //#region src/permissions/authorizationDecision.d.ts
166
167
  /**
167
- * Normalize a permission check return value (`boolean | PermissionResult`)
168
- * into a concrete `PermissionResult`. This is the only place in Arc that
169
- * promotes booleans to results — keeps the type narrowing honest everywhere.
168
+ * A permission check returns either a bare boolean (terse allow/deny sugar) or
169
+ * a full {@link AuthorizationDecision}. There is no legacy `PermissionResult` —
170
+ * `AuthorizationDecision` is arc's single authorization contract.
170
171
  */
171
- declare function normalizePermissionResult(result: boolean | PermissionResult): PermissionResult;
172
+ type PermissionCheckReturn = boolean | AuthorizationDecision;
173
+ /**
174
+ * Normalize a check return into the canonical {@link AuthorizationDecision}.
175
+ * A boolean promotes to `{ effect: "allow" | "deny" }`; a decision passes
176
+ * through. This is the ONE place booleans are promoted, so the rest of the
177
+ * pipeline only ever handles decisions.
178
+ */
179
+ declare function normalizeToDecision(result: PermissionCheckReturn): AuthorizationDecision;
180
+ /**
181
+ * Run a permission check and return a canonical {@link AuthorizationDecision} —
182
+ * the transport-neutral PDP (HTTP, aggregation, MCP, and any future transport).
183
+ * A thin mapper over {@link evaluatePermissionOutcome}:
184
+ *
185
+ * - a structured `ArcError` is RE-THROWN so the transport surfaces it verbatim
186
+ * (e.g. a tier gate throwing `arc.tier_required` with machine-readable meta);
187
+ * - any OTHER throw is fail-closed to a `deny` decision (a broken check must
188
+ * never fall open to a 500 that skips authorization).
189
+ *
190
+ * Pure w.r.t. the request — it neither reads a reply nor mutates the request.
191
+ * Callers translate the returned decision into their own response mechanism and
192
+ * apply side-effects via {@link applyAuthorizationDecision}. HTTP additionally
193
+ * hardens a *thrown* check to 403-even-when-anonymous — that transport-specific
194
+ * nuance lives in {@link evaluateAndApplyPermission}, not here.
195
+ */
196
+ declare function evaluatePermissionDecision(check: PermissionCheck, context: PermissionContext): Promise<AuthorizationDecision>;
172
197
  /**
173
198
  * Minimal shape of a Fastify request that can receive permission side-effects.
174
199
  * We avoid depending on the full augmented `FastifyRequest` type here because
@@ -180,8 +205,9 @@ type RequestSink = FastifyRequest & {
180
205
  scope?: RequestScope;
181
206
  };
182
207
  /**
183
- * Apply a granted `PermissionResult` to a Fastify request — merges row-level
184
- * filters into `_policyFilters` and conditionally installs the scope.
208
+ * Apply an allowed {@link AuthorizationDecision} to a Fastify request — conjoins
209
+ * the decision's row-level `policy` into `_policyFilters` and conditionally
210
+ * installs the `scope`.
185
211
  *
186
212
  * **Scope install rule:** only writes `scope` when the current request scope
187
213
  * is absent or `public`. This prevents downgrading an already-authenticated
@@ -189,13 +215,41 @@ type RequestSink = FastifyRequest & {
189
215
  * narrower `service` scope — the original `member` wins because it came from
190
216
  * a more authoritative source).
191
217
  *
192
- * Safe to call with a non-granted result — it simply no-ops. Callers should
193
- * still check `result.granted` and send an error response before reaching here,
194
- * but this function tolerates the misuse defensively.
218
+ * Safe to call with a denied decision — it simply no-ops. Callers should still
219
+ * check `decision.effect` and send an error response before reaching here, but
220
+ * this function tolerates the misuse defensively.
221
+ *
222
+ * This is the enforcement point (PEP) — the ONE place scope + data policy are
223
+ * installed (and the obligation seam lives).
224
+ */
225
+ declare function applyAuthorizationDecision(decision: AuthorizationDecision, request: RequestSink): void;
226
+ //#endregion
227
+ //#region src/permissions/context.d.ts
228
+ /**
229
+ * Resolve the request scope for a permission check. Prefers the context's
230
+ * first-class `scope`; falls back to the raw HTTP `request.scope` when present,
231
+ * else `PUBLIC_SCOPE`. Primitives MUST use this instead of touching
232
+ * `ctx.request` so scope threads through combinators and non-HTTP transports
233
+ * (MCP, jobs) — which have no request — resolve identity correctly.
195
234
  */
196
- declare function applyPermissionResult(result: PermissionResult, request: RequestSink): void;
235
+ declare function scopeOf(ctx: PermissionContext): RequestScope;
197
236
  //#endregion
198
237
  //#region src/permissions/core.d.ts
238
+ /**
239
+ * Build an `allow` {@link AuthorizationDecision}, optionally attaching a row-level
240
+ * `policy` and/or a `scope` to install. The idiomatic "grant" return for arc
241
+ * 2.30 checks (parallels Cedar's `permit`).
242
+ *
243
+ * @example
244
+ * return allow(); // simple grant
245
+ * return allow({ policy: { ownerId: userId } }); // grant + row policy
246
+ */
247
+ declare function allow(extra?: Omit<AuthorizationDecision, "effect">): AuthorizationDecision;
248
+ /**
249
+ * Build a `deny` {@link AuthorizationDecision} with an optional human-readable
250
+ * reason (parallels Cedar's `forbid`). The idiomatic "refuse" return.
251
+ */
252
+ declare function deny(reason?: string): AuthorizationDecision;
199
253
  /**
200
254
  * Allow public access (no authentication required).
201
255
  *
@@ -248,6 +302,24 @@ declare function requireRoles(roles: readonly string[], options?: {
248
302
  */
249
303
  includeOrgRoles?: boolean;
250
304
  }): PermissionCheck;
305
+ /**
306
+ * Require a PLATFORM role — global roles only. An organization role can never
307
+ * satisfy this gate.
308
+ *
309
+ * `requireRoles(["ops"])` also accepts an ORG role named `ops` (that is its
310
+ * documented default), and `requireOrgRole("manager")` grants ANY organization's
311
+ * manager. Both return a bare allow with no policy, so a surface that is global
312
+ * by construction — a queue dashboard, a cluster-wide operations endpoint —
313
+ * cannot distinguish them from a real operator gate by looking at the decision.
314
+ * That makes "platform-only" a property the check has to DECLARE, which is what
315
+ * `_platformOnly` records and what such a surface can then require.
316
+ *
317
+ * Elevated scope passes: platform admin is the identity this gate is for.
318
+ *
319
+ * @example
320
+ * permissions: { list: requirePlatformRole("platform-ops") }
321
+ */
322
+ declare function requirePlatformRole(...args: string[] | [readonly string[]]): PermissionCheck;
251
323
  /**
252
324
  * Short-form alias of `requireRoles()`. Identical behavior — checks both
253
325
  * platform roles AND org roles. Prefer `requireRoles` for new code; this
@@ -272,11 +344,18 @@ declare function requireOwnership<TDoc = Record<string, unknown>>(ownerField?: E
272
344
  /**
273
345
  * Combine multiple checks — ALL must pass (AND logic).
274
346
  *
275
- * Each child runs against the **accumulated** state of previous children:
276
- * - `filters` from earlier children merge into the next child's `_policyFilters`
277
- * - `scope` from earlier children installs on the request before the next child runs
347
+ * Evaluation is PURE — nothing is written to the request. Each child runs
348
+ * against the accumulated state of previous children, threaded through a fresh
349
+ * child context:
350
+ * - `policy` from earlier children is CONJOINED (logical AND) — a later child
351
+ * can add or narrow restrictions but never silently replaces an earlier
352
+ * child's constraint on the same key (conflicting values are preserved under
353
+ * `$and`; see `conjoinPolicyFilters`)
354
+ * - `scope` installed by an earlier child is visible to the next through
355
+ * `scopeOf(ctx)`, and never downgrades an already-authoritative scope
278
356
  *
279
- * The final result carries both merged `filters` and merged `scope`.
357
+ * The returned decision carries the merged `policy` + `scope`; the enforcement
358
+ * point (`applyAuthorizationDecision`) applies them to the request once.
280
359
  *
281
360
  * @example
282
361
  * ```typescript
@@ -449,6 +528,145 @@ declare function createOrgPermissions(config: {
449
528
  */
450
529
  declare function createDynamicPermissionMatrix(config: DynamicPermissionMatrixConfig): DynamicPermissionMatrix;
451
530
  //#endregion
531
+ //#region src/permissions/explain.d.ts
532
+ /**
533
+ * The statically-known requirement of a permission check.
534
+ *
535
+ * - `public` — `allowPublic()`; anyone passes.
536
+ * - `roles` — grants if the caller holds ANY of these (platform OR org roles,
537
+ * unioned — matches how `requireRoles`/`requireOrgRole`/`anyOf` compose).
538
+ * - `scoped` — grants only within a caller SCOPE dimension (`_scopeContext`,
539
+ * e.g. `{ branchRole: "head_office" }`), optionally combined with `roles`. The
540
+ * scope dimensions are known statically even though their per-request VALUES
541
+ * aren't, so a consumer that holds the caller's scope (a FE that knows the
542
+ * active branch's role) can decide it client-side — the piece a flat `roles`
543
+ * requirement could not express.
544
+ * - `authenticated` — the check reads request-time facts (custom auth, service
545
+ * scope, ownership, grants) that no static analysis can decide; the definitive
546
+ * answer is computed per request. Treat as "server decides".
547
+ */
548
+ type PermissionRequirement = {
549
+ readonly kind: "public";
550
+ } | {
551
+ readonly kind: "roles";
552
+ readonly roles: readonly string[];
553
+ /**
554
+ * `true` when these roles are NECESSARY but not SUFFICIENT — the gate is an
555
+ * `allOf(...)` that also carries an opaque runtime branch (ownership /
556
+ * custom / dynamic / flow-mode …). A role MATCH is then `conditional`, not a
557
+ * definitive `allow`; a MISMATCH is still a definitive `deny`.
558
+ */
559
+ readonly conditional?: boolean;
560
+ } | {
561
+ readonly kind: "scoped";
562
+ /** Required scope dimensions: `value` string = must equal; `undefined` = must be present. */
563
+ readonly scope: Readonly<Record<string, string | undefined>>;
564
+ /** Roles ALSO required alongside the scope (union of platform + org roles), if any. */
565
+ readonly roles?: readonly string[];
566
+ /** See `roles.conditional` — the composite also has an opaque/contradictory branch. */
567
+ readonly conditional?: boolean;
568
+ } | {
569
+ readonly kind: "authenticated";
570
+ };
571
+ /**
572
+ * Extract a check's static requirement from its `PermissionCheckMeta`. Public
573
+ * wins; then a scope-context gate (optionally with roles); then the union of
574
+ * platform + org roles a role gate declares; otherwise "authenticated"
575
+ * (auth-required / custom / request-time checks). An `allOf` that couldn't be
576
+ * fully captured statically carries `conditional: true` (see `_conditional`).
577
+ */
578
+ declare function describePermission(check: PermissionCheck): PermissionRequirement;
579
+ /** Result of {@link explainAccess}. */
580
+ interface AccessExplanation {
581
+ /**
582
+ * `allow` / `deny` are DEFINITIVE from static metadata (public, or a role
583
+ * match against the supplied principal). `conditional` means the gate reads
584
+ * request-time state, so the real decision is made per request — this is not a
585
+ * denial, it is "cannot be determined statically".
586
+ */
587
+ decision: "allow" | "deny" | "conditional";
588
+ /** Human-readable rationale, safe to surface in a UI or an audit report. */
589
+ reason: string;
590
+ /** The check's static requirement (the same value {@link describePermission} returns). */
591
+ requirement: PermissionRequirement;
592
+ }
593
+ /**
594
+ * Explain whether a principal (by roles) passes a permission check, from static
595
+ * metadata alone — for permission-matrix UIs, docs, and audits. Omit `principal`
596
+ * to get the requirement-only view (roles → `conditional`).
597
+ *
598
+ * @example
599
+ * explainAccess(requireRoles("admin"), { roles: ["editor"] })
600
+ * // → { decision: "deny", reason: "requires one of: admin", requirement: { kind: "roles", roles: ["admin"] } }
601
+ */
602
+ declare function explainAccess(check: PermissionCheck, principal?: {
603
+ roles?: readonly string[];
604
+ orgRoles?: readonly string[];
605
+ /** The caller's scope-context values (e.g. `{ branchRole: "head_office" }`) — supply to decide a `scoped` gate. */
606
+ scope?: Readonly<Record<string, string | undefined>>;
607
+ }): AccessExplanation;
608
+ /**
609
+ * Introspect a whole permission map (`{ list, get, create, ... }` or any
610
+ * action→check record) into `action → requirement`. The reusable core of a
611
+ * `/permissions/matrix` endpoint or an access audit — framework-owned, so a host
612
+ * never hand-rolls `(check as any)._roles` peeking. Undefined slots (a CRUD op
613
+ * with no gate = public-by-omission) surface as `public` so the inventory is
614
+ * honest about what's exposed.
615
+ */
616
+ declare function describePermissionMap(permissions: Readonly<Record<string, PermissionCheck | undefined>>): Record<string, PermissionRequirement>;
617
+ /**
618
+ * The public attack surface of a permission map — the actions reachable with NO
619
+ * authentication (explicit `allowPublic()` or public-by-omission). Empty is the
620
+ * healthy default for a protected resource; a non-empty list is what a
621
+ * "what's exposed?" audit report should show.
622
+ */
623
+ declare function collectPublicSurface(permissions: Readonly<Record<string, PermissionCheck | undefined>>): string[];
624
+ //#endregion
625
+ //#region src/permissions/filter-merge.d.ts
626
+ /**
627
+ * Policy-filter composition — logical AND, never last-writer-wins.
628
+ *
629
+ * Row-level policy filters can arrive from several INDEPENDENT sources for one
630
+ * request: a tenant preset, an `ownedByUser` grant, an `allOf(...)` branch, a
631
+ * host permission check. Every one of them is a RESTRICTION the row must
632
+ * satisfy, so composing them is logical AND.
633
+ *
634
+ * The historical `{ ...base, ...incoming }` shallow spread did NOT implement AND:
635
+ * when two sources constrained the SAME key with different values, the later one
636
+ * silently REPLACED the earlier one — widening (or erasing) a restriction another
637
+ * layer deliberately imposed. That is a defense-in-depth defect, not a
638
+ * refinement. "Later can refine" is only sound when the refinement is provably
639
+ * narrower, and a bare overwrite proves nothing.
640
+ *
641
+ * {@link conjoinPolicyFilters} composes with AND semantics while preserving the
642
+ * common case byte-for-byte:
643
+ *
644
+ * - key present on only one side → carried through flat. Non-overlapping
645
+ * filters (the ~99% case) produce exactly the same object the old spread did,
646
+ * so there is ZERO behavior change for them.
647
+ * - same key, deep-equal value → kept once (idempotent — e.g. two checks
648
+ * both pinning the same `organizationId`).
649
+ * - same key, DIFFERENT value → BOTH constraints are preserved under an
650
+ * `$and`, so a row must satisfy both. For flat equality that conjunction is
651
+ * unsatisfiable, so the query returns nothing — the safe, correct outcome for
652
+ * contradictory policies (deny), and the earlier restriction is never dropped.
653
+ *
654
+ * Adapter safety: mongokit / sqlitekit compile `$and` natively at the DB layer,
655
+ * and arc's in-memory `simpleEqualityMatcher` (AccessControl.checkPolicyFilters)
656
+ * already fail-closes on operator-shaped filters. So a produced `$and` is either
657
+ * evaluated correctly by the DB or rejected fail-closed in memory — both safe.
658
+ *
659
+ * This is the pragmatic, adapter-neutral form of the AND semantics. A canonical
660
+ * filter IR in `repo-core` (nested and/or/not nodes each adapter compiles) is the
661
+ * fuller design, but this closes the security defect without one.
662
+ */
663
+ /**
664
+ * Conjoin two policy-filter maps with AND semantics. Never silently overwrites a
665
+ * same-key constraint with a different value — conflicting keys are preserved
666
+ * under `$and`. See the module doc for the full contract.
667
+ */
668
+ declare function conjoinPolicyFilters(base: Record<string, unknown> | undefined, incoming: Record<string, unknown> | undefined): Record<string, unknown>;
669
+ //#endregion
452
670
  //#region src/permissions/grants.d.ts
453
671
  /**
454
672
  * The grant-mode lattice, weakest → strongest. Holding a mode satisfies
@@ -474,7 +692,7 @@ declare function modeSatisfies(held: string | undefined, required: GrantMode): b
474
692
  * - `{ mode }` — the strongest mode the caller holds on `ctx.resourceId`;
475
693
  * the combinator applies the lattice against the required mode.
476
694
  * - `{ filters }` — list-shaped resolution: row filters that scope the
477
- * query to visible records (flows through `PermissionResult.filters` →
695
+ * query to visible records (flows through the decision's `policy` →
478
696
  * `_policyFilters` → the repository query). Grants access with the
479
697
  * filters attached.
480
698
  * - `{ mode, filters }` — mode gates; filters ride along when it passes.
@@ -655,8 +873,8 @@ declare function requireScopeContext<TDoc = Record<string, unknown>>(keyOrMap: s
655
873
  *
656
874
  * **Two call shapes:**
657
875
  * ```typescript
658
- * requireOrgInScope('acme-holding') // static
659
- * requireOrgInScope((ctx) => ctx.request.params.orgId) // dynamic
876
+ * requireOrgInScope('acme-holding') // static
877
+ * requireOrgInScope((ctx) => ctx.params?.orgId) // dynamic — from ctx facts, not the raw request
660
878
  * ```
661
879
  *
662
880
  * `elevated` scope grants unconditionally (cross-org bypass).
@@ -664,9 +882,9 @@ declare function requireScopeContext<TDoc = Record<string, unknown>>(keyOrMap: s
664
882
  * @example
665
883
  * ```typescript
666
884
  * permissions: {
667
- * list: requireOrgInScope((ctx) => ctx.request.params.orgId),
885
+ * list: requireOrgInScope((ctx) => ctx.params?.orgId),
668
886
  * create: allOf(
669
- * requireOrgInScope((ctx) => ctx.request.body?.organizationId),
887
+ * requireOrgInScope((ctx) => (ctx.data as { organizationId?: string })?.organizationId),
670
888
  * requireOrgRole('admin'),
671
889
  * ),
672
890
  * }
@@ -772,4 +990,4 @@ declare function fullPublic<TDoc = Record<string, unknown>>(overrides?: Permissi
772
990
  */
773
991
  declare function readOnly<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
774
992
  //#endregion
775
- export { allOf as A, applyPermissionResult as B, requireGrant as C, PermissionEventBus as D, DynamicPermissionMatrixConfig as E, requireAuth as F, requireDPoP as G, RequireAgentScopeOptions as H, requireOwnership as I, requireMandate as K, requireRoles as L, anyOf as M, denyAll as N, createDynamicPermissionMatrix as O, not as P, roles as R, modeSatisfies as S, DynamicPermissionMatrix as T, RequireMandateOptions as U, normalizePermissionResult as V, requireAgentScope as W, createRoleHierarchy as _, permissionMatrix as a, GrantResolution as b, publicReadAdminWrite as c, requireOrgMembership as d, requireOrgRole as f, RoleHierarchy as g, requireTeamMembership as h, ownerWithAdminBypass as i, allowPublic as j, createOrgPermissions as k, readOnly as l, requireServiceScope as m, authenticated as n, presets_d_exports as o, requireScopeContext as p, fullPublic as r, publicRead as s, adminOnly as t, requireOrgInScope as u, GRANT_MODES as v, ConnectEventsOptions as w, RequireGrantOptions as x, GrantMode as y, when as z };
993
+ export { evaluatePermissionDecision as $, explainAccess as A, anyOf as B, requireGrant as C, collectPublicSurface as D, PermissionRequirement as E, createDynamicPermissionMatrix as F, requireOwnership as G, denyAll as H, createOrgPermissions as I, roles as J, requirePlatformRole as K, allOf as L, DynamicPermissionMatrix as M, DynamicPermissionMatrixConfig as N, describePermission as O, PermissionEventBus as P, applyAuthorizationDecision as Q, allow as R, modeSatisfies as S, AccessExplanation as T, not as U, deny as V, requireAuth as W, scopeOf as X, when as Y, PermissionCheckReturn as Z, createRoleHierarchy as _, permissionMatrix as a, requireMandate as at, GrantResolution as b, publicReadAdminWrite as c, requireOrgMembership as d, normalizeToDecision as et, requireOrgRole as f, RoleHierarchy as g, requireTeamMembership as h, ownerWithAdminBypass as i, requireDPoP as it, ConnectEventsOptions as j, describePermissionMap as k, readOnly as l, requireServiceScope as m, authenticated as n, RequireMandateOptions as nt, presets_d_exports as o, requireScopeContext as p, requireRoles as q, fullPublic as r, requireAgentScope as rt, publicRead as s, adminOnly as t, RequireAgentScopeOptions as tt, requireOrgInScope as u, GRANT_MODES as v, conjoinPolicyFilters as w, RequireGrantOptions as x, GrantMode as y, allowPublic as z };