@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,3 +1,4 @@
1
+
1
2
  import { OutboxStore } from "@classytic/primitives/outbox";
2
3
  //#region src/testing/outboxStoreContract.d.ts
3
4
  interface OutboxStoreContractSetupResult {
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  import { OutboxOwnershipError } from "@classytic/primitives/outbox";
2
3
  import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
4
  //#region src/testing/outboxStoreContract.ts
@@ -1,4 +1,5 @@
1
- import { t as Storage } from "../storage-DLUZ04kK.mjs";
1
+
2
+ import { t as Storage } from "../storage-Cx9Sz3Ou.mjs";
2
3
  //#region src/testing/storageContract.d.ts
3
4
  interface StorageContractSetupResult {
4
5
  storage: Storage;
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  import { afterAll, beforeAll, describe, expect, it } from "vitest";
2
3
  //#region src/testing/storageContract.ts
3
4
  /**
@@ -1,3 +1,4 @@
1
+
1
2
  import { FastifyInstance, FastifyRequest } from "fastify";
2
3
  import { Span, Tracer } from "@opentelemetry/api";
3
4
  //#region src/plugins/tracing.d.ts
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  import { AsyncLocalStorage } from "node:async_hooks";
2
3
  //#region src/context/transactionContext.ts
3
4
  /**
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/utils/typeGuards.ts
2
3
  /** Check if fastify has the events plugin registered */
3
4
  function hasEvents(instance) {
@@ -1,5 +1,6 @@
1
- import { $ as OpenApiSchemas, A as RequestIdOptions, At as RouteDefinition, Bt as RouteHandler, C as RequestContext, D as HealthCheck, Dt as ActionEntry, E as GracefulShutdownOptions, Et as ActionDefinition, F as FastifyWithDecorators, Ft as ControllerLike, G as OnTenantDeleteConfig, Gt as AuthenticatorContext, H as CrudController, Ht as AuthHelpers, I as MiddlewareHandler, It as FastifyHandler, J as PresetHook, K as ResolvedTenantPurge, Kt as JwtContext, L as RequestWithExtras, Lt as IController, M as EventsDecorator, Mt as RouteMethod, N as FastifyRequestExtras, Nt as RateLimitConfig, O as HealthOptions, Ot as ActionHandlerFn, P as FastifyWithAuth, Pt as ControllerHandler, Q as MiddlewareConfig, Rt as IControllerResponse, S as QueryParserInterface, T as CrudRouterOptions, Tt as ResourceCacheConfig, U as ResourceConfig, Ut as AuthPluginOptions, W as ResourcePermissions, Wt as Authenticator, X as CrudRouteKey, Y as PresetResult, Z as CrudSchemas, _ as ControllerQueryOptions, a as InferAdapterDoc, at as ResourceExtensions, b as ParsedQuery, c as TypedController, d as PaginationResult, et as RouteSchemaOptions, f as IntrospectionData, g as ArcInternalMetadata, h as ResourceMetadata, i as ValidationResult, it as ResourceHooks, j as ArcDecorator, jt as RouteMcpConfig, k as IntrospectionPluginOptions, kn as BaseControllerOptions, kt as ActionsMap, l as TypedRepository, m as RegistryStats, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, q as PresetFunction, qt as TokenPair, r as ValidateOptions, rt as ResourceHookContext, s as InferResourceDoc, t as RouteHandlerMethod, tt as ArcFieldRule, u as TypedResourceConfig, v as LookupOption, w as ServiceContext, x as PopulateOption, y as OwnershipCheck, zt as IRequestContext } from "../index-DPRH0Cme.mjs";
2
- import { i as RequestScope } from "../types-DjC-KUCz.mjs";
3
- import { c as AnyRecord, d as ObjectId, f as UserLike, i as UserBase, l as ArcRequest, n as PermissionContext, p as UserOrganization, r as PermissionResult, t as PermissionCheck, u as JWTPayload } from "../types-Dmw-6Qeo.mjs";
4
- import { n as ElevationOptions, t as ElevationEvent } from "../elevation-C9s5hFP_.mjs";
5
- export type { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, ResourceCacheConfig, ResourceConfig, ResourceExtensions, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult };
1
+
2
+ import { $ as OpenApiSchemas, A as RequestIdOptions, An as BaseControllerOptions, At as RouteDefinition, Bt as RawRouteHandler, C as RequestContext, D as HealthCheck, Dt as ActionEntry, E as GracefulShutdownOptions, Et as ActionDefinition, F as FastifyWithDecorators, Ft as ControllerLike, G as OnTenantDeleteConfig, Gt as Authenticator, H as CrudController, I as MiddlewareHandler, It as FastifyHandler, J as PresetHook, Jt as TokenPair, K as ResolvedTenantPurge, Kt as AuthenticatorContext, L as RequestWithExtras, Lt as IController, M as EventsDecorator, Mt as RouteMethod, N as FastifyRequestExtras, Nt as RateLimitConfig, O as HealthOptions, Ot as ActionHandlerFn, P as FastifyWithAuth, Pt as ControllerHandler, Q as MiddlewareConfig, Rt as IControllerResponse, S as QueryParserInterface, T as CrudRouterOptions, Tt as ResourceCacheConfig, U as ResourceConfig, Ut as AuthHelpers, Vt as RouteHandler, W as ResourcePermissions, Wt as AuthPluginOptions, X as CrudRouteKey, Y as PresetResult, Z as CrudSchemas, _ as ControllerQueryOptions, a as InferAdapterDoc, at as ResourceExtensions, b as ParsedQuery, c as TypedController, d as PaginationResult, et as RouteSchemaOptions, f as IntrospectionData, g as ArcInternalMetadata, h as ResourceMetadata, i as ValidationResult, it as ResourceHooks, j as ArcDecorator, jt as RouteMcpConfig, k as IntrospectionPluginOptions, kt as ActionsMap, l as TypedRepository, m as RegistryStats, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, q as PresetFunction, qt as JwtContext, r as ValidateOptions, rt as ResourceHookContext, s as InferResourceDoc, t as RouteHandlerMethod, tt as ArcFieldRule, u as TypedResourceConfig, v as LookupOption, w as ServiceContext, x as PopulateOption, y as OwnershipCheck, zt as IRequestContext } from "../index-CpzxqePp.mjs";
3
+ import { i as RequestScope } from "../types-ChuShpCP.mjs";
4
+ import { a as UserBase, d as JWTPayload, f as ObjectId, i as PermissionContext, l as AnyRecord, m as UserOrganization, n as DataPolicy, p as UserLike, r as PermissionCheck, t as AuthorizationDecision, u as ArcRequest } from "../types-B7XeLEgK.mjs";
5
+ import { n as ElevationOptions, t as ElevationEvent } from "../elevation-BXCfVcNG.mjs";
6
+ export type { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, AuthorizationDecision, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, DataPolicy, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RawRouteHandler, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, ResourceCacheConfig, ResourceConfig, ResourceExtensions, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult };
@@ -1 +1,2 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  export {};
@@ -1,2 +1,3 @@
1
- import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-DLUZ04kK.mjs";
1
+
2
+ import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-Cx9Sz3Ou.mjs";
2
3
  export { Storage, StorageContext, StorageFile, StorageReadRange, StorageReadResult, StorageUploadInput };
@@ -1 +1,2 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  export {};
@@ -1,4 +1,5 @@
1
- import { i as RequestScope } from "./types-DjC-KUCz.mjs";
1
+
2
+ import { i as RequestScope } from "./types-ChuShpCP.mjs";
2
3
  import { FastifyRequest } from "fastify";
3
4
  //#region src/types/base.d.ts
4
5
  declare module "fastify" {
@@ -53,7 +54,7 @@ interface JWTPayload {
53
54
  [key: string]: unknown;
54
55
  }
55
56
  /**
56
- * Typed Fastify request with Arc decorations. Use in `raw: true` handlers
57
+ * Typed Fastify request with Arc decorations. Use in `rawHandler` routes
57
58
  * instead of `(req as any).user`.
58
59
  *
59
60
  * @example
@@ -95,6 +96,56 @@ declare function getUserRoles(user: {
95
96
  } | null | undefined): string[];
96
97
  //#endregion
97
98
  //#region src/permissions/types.d.ts
99
+ /**
100
+ * Row-level data policy — the constraint every returned/queried row must
101
+ * satisfy. This is arc's **Mongo-style record dialect** (`{ ownerId }`,
102
+ * `{ $or: [...] }`, `{ status: { $ne: "archived" } }`), the ONE canonical
103
+ * internal representation every permission helper emits and every enforcement
104
+ * seam composes (`conjoinPolicyFilters`).
105
+ *
106
+ * It is compiled to the portable repo-core `Filter` IR at the repository
107
+ * boundary (`core/repositoryFilter.ts` → `policyRecordToFilter`) so it runs
108
+ * identically on Mongo / SQL / any kit — arc's answer to oso-style "data
109
+ * filtering" + Postgres RLS, but datastore-portable and in-process. The IR is a
110
+ * boundary/compile concern, NOT the decision surface: keeping the decision in
111
+ * one record dialect means composition (`allOf`/`anyOf`/`conjoin`) has a single
112
+ * well-defined shape instead of a `Filter | Record` union the composer can't
113
+ * honor.
114
+ */
115
+ type DataPolicy = Record<string, unknown>;
116
+ /**
117
+ * The canonical authorization decision (arc 2.30). A single typed value that
118
+ * cleanly separates the concerns a permission check expresses:
119
+ *
120
+ * - `effect` — allow / deny (Cedar / XACML decision)
121
+ * - `reason` — human-readable diagnostic for the denial (explainability)
122
+ * - `policy` — row-level {@link DataPolicy} to enforce at the repository
123
+ * - `scope` — identity/context to install on the request (PIP)
124
+ *
125
+ * Build one with the `allow()` / `deny()` constructors. A check may also return
126
+ * a bare `boolean` (terse allow/deny), normalized via `normalizeToDecision`.
127
+ *
128
+ * NOTE: arc deliberately does NOT model XACML-style "obligations" on the
129
+ * decision. Audit and field redaction are first-class arc subsystems already
130
+ * (`audit: true` on a resource; field-level read/write permissions), so an
131
+ * obligations channel would be a second, unenforced way to ask for the same
132
+ * effects. If a future need arises it will ship WITH a dispatcher that every
133
+ * enforcement surface runs — never as a declared-but-ignored contract.
134
+ */
135
+ interface AuthorizationDecision {
136
+ /** Allow or deny. */
137
+ effect: "allow" | "deny";
138
+ /** Human-readable denial reason (surfaced in error messages / explain). */
139
+ reason?: string;
140
+ /** Row-level data policy to enforce at the repository layer. */
141
+ policy?: DataPolicy;
142
+ /**
143
+ * Scope to install on `request.scope` when allowed — flows to
144
+ * `metadata._scope` for tenant-field filtering. The clean integration point
145
+ * for custom auth (API keys, service accounts, gateway headers).
146
+ */
147
+ scope?: RequestScope;
148
+ }
98
149
  /**
99
150
  * User base interface - minimal shape Arc expects
100
151
  * Your actual User can have any additional fields
@@ -107,25 +158,33 @@ interface UserBase {
107
158
  [key: string]: unknown;
108
159
  }
109
160
  /**
110
- * Extract normalized roles from a user object.
161
+ * Context passed to permission check functions.
111
162
  *
112
- * Reads `user.role` which can be:
113
- * - A comma-separated string: `"superadmin,user"` (Better Auth admin plugin)
114
- * - A string array: `["admin", "user"]` (JWT / custom auth)
115
- * - A single string: `"admin"`
116
- */
117
- /**
118
- * Normalize a raw role value (string, comma-separated string, or array) into a string[].
119
- * Shared low-level helper used by both getUserRoles() and the Better Auth adapter.
120
- */
121
- /**
122
- * Context passed to permission check functions
163
+ * arc 2.30: checks read FACTS off this context — never off a raw request. Use
164
+ * `scopeOf(ctx)` (from `./context.js`) to read the scope; it prefers the
165
+ * first-class {@link PermissionContext.scope} and lets combinators thread an
166
+ * updated scope to child checks WITHOUT mutating the request. `request` is a
167
+ * transport escape hatch (present for HTTP; absent for MCP/jobs/ws) and is being
168
+ * retired as the primary channel.
123
169
  */
124
170
  interface PermissionContext<TDoc = Record<string, unknown>> {
125
171
  /** Authenticated user or null if unauthenticated */
126
172
  user: UserBase | null;
127
- /** Fastify request object */
128
- request: FastifyRequest;
173
+ /**
174
+ * Resolved request scope (identity + tenant/org context). First-class so
175
+ * combinators can thread an accumulated scope purely and non-HTTP transports
176
+ * need no request. Read via `scopeOf(ctx)`.
177
+ */
178
+ scope?: RequestScope;
179
+ /**
180
+ * Raw Fastify request — transport escape hatch, present ONLY on the HTTP
181
+ * surface. It is `undefined` for MCP, jobs, and any non-Fastify transport, so
182
+ * a permission check must NOT depend on it: read identity via `scopeOf(ctx)`,
183
+ * inputs via `ctx.data` / `ctx.params`, and host facts via `ctx.attributes`.
184
+ * Kept solely for genuinely HTTP-coupled checks (e.g. a usage meter on
185
+ * `request.server`) which are inherently transport-specific.
186
+ */
187
+ request?: FastifyRequest;
129
188
  /** Resource name being accessed */
130
189
  resource: string;
131
190
  /** Action being performed (list, get, create, update, delete, or custom operation name) */
@@ -136,93 +195,40 @@ interface PermissionContext<TDoc = Record<string, unknown>> {
136
195
  params?: Record<string, string>;
137
196
  /** Request body data */
138
197
  data?: Partial<TDoc> | Record<string, unknown>;
139
- }
140
- /**
141
- * Result from a permission check.
142
- *
143
- * Permission checks can do three things:
144
- * 1. **Grant or deny** access (`granted`, `reason`)
145
- * 2. **Attach row-level filters** (`filters`) — these merge into `_policyFilters`
146
- * and narrow subsequent queries (e.g. `{ userId: ctx.user.id }` for ownership)
147
- * 3. **Install the request scope** (`scope`) — when a custom authenticator wants
148
- * to set tenant/identity context directly from the permission layer, without
149
- * relying on a separate auth plugin
150
- *
151
- * The `scope` field is the clean integration point for custom auth strategies
152
- * (API keys, service accounts, gateway headers). When present, Arc writes it to
153
- * `request.scope` which then flows through the normal tenant-filtering pipeline
154
- * (QueryResolver + AccessControl). This is the idiomatic way to wire non-Better-Auth
155
- * identity providers into Arc's multi-tenancy without touching the auth plugin layer.
156
- *
157
- * @example
158
- * ```typescript
159
- * // Custom API-key auth — grant access AND install a service scope in one step
160
- * export function requireApiKey(): PermissionCheck {
161
- * return async ({ request }) => {
162
- * const apiKey = request.headers['x-api-key'] as string | undefined;
163
- * if (!apiKey) return { granted: false, reason: 'Missing API key' };
164
- *
165
- * const client = await ClientModel.findOne({ apiKey });
166
- * if (!client) return { granted: false, reason: 'Invalid API key' };
167
- *
168
- * return {
169
- * granted: true,
170
- * // Install service scope — Arc writes this to request.scope automatically,
171
- * // and tenantField filtering picks it up via metadata._scope
172
- * scope: {
173
- * kind: 'service',
174
- * clientId: String(client._id),
175
- * organizationId: String(client.companyId),
176
- * scopes: client.allowedScopes,
177
- * },
178
- * // Optional row-level narrowing (e.g. per-project API keys)
179
- * filters: client.projectId ? { projectId: client.projectId } : undefined,
180
- * };
181
- * };
182
- * }
183
- * ```
184
- */
185
- interface PermissionResult {
186
- /** Whether access is granted */
187
- granted: boolean;
188
- /** Reason for denial (for error messages) */
189
- reason?: string;
190
- /** Query filters to apply (for ownership / row-level security patterns) */
191
- filters?: Record<string, unknown>;
192
198
  /**
193
- * Install this scope on `request.scope` when granted. Flows through to
194
- * `metadata._scope` and is read by QueryResolver / AccessControl for
195
- * tenant-field filtering. Use this to wire custom auth (API keys, service
196
- * accounts, gateway headers) into Arc's multi-tenancy without a separate
197
- * auth plugin.
199
+ * Transport/host-supplied attributes a check may need for ABAC decisions
200
+ * (headers, claims, feature flags) without reaching into the raw request.
198
201
  */
199
- scope?: RequestScope;
202
+ attributes?: Readonly<Record<string, unknown>>;
200
203
  }
201
204
  /**
202
- * Permission Check Function
205
+ * Permission Check Function — THE way to define permissions in Arc.
203
206
  *
204
- * THE ONLY way to define permissions in Arc.
205
- * Returns boolean, PermissionResult, or Promise of either.
207
+ * Returns a `boolean` (terse allow/deny) or an {@link AuthorizationDecision}
208
+ * (effect + optional data `policy` and `scope`). Build decisions with the
209
+ * `allow()` / `deny()` constructors from `@classytic/arc/permissions`.
206
210
  *
207
211
  * @example
208
212
  * ```typescript
209
- * // Simple boolean return
213
+ * // Simple boolean
210
214
  * const isAdmin: PermissionCheck = (ctx) => getUserRoles(ctx.user).includes('admin');
211
215
  *
212
- * // With filters for ownership
213
- * const ownedByUser: PermissionCheck = (ctx) => ({
214
- * granted: true,
215
- * filters: { userId: ctx.user?.id }
216
- * });
216
+ * // Grant + row-level data policy (ownership)
217
+ * const ownedByUser: PermissionCheck = (ctx) =>
218
+ * allow({ policy: { userId: ctx.user?.id } });
217
219
  *
218
- * // Async check
219
- * const canAccessOrg: PermissionCheck = async (ctx) => {
220
- * const isMember = await checkMembership(ctx.user?.id, ctx.organizationId);
221
- * return { granted: isMember, reason: isMember ? undefined : 'Not a member' };
220
+ * // Custom API-key auth — grant AND install a service scope
221
+ * const requireApiKey: PermissionCheck = async ({ request }) => {
222
+ * const client = await lookup(request.headers['x-api-key']);
223
+ * if (!client) return deny('Invalid API key');
224
+ * return allow({
225
+ * scope: { kind: 'service', clientId: String(client._id), organizationId: String(client.companyId) },
226
+ * ...(client.projectId ? { policy: { projectId: client.projectId } } : {}),
227
+ * });
222
228
  * };
223
229
  * ```
224
230
  */
225
- type PermissionCheck<TDoc = Record<string, unknown>> = ((context: PermissionContext<TDoc>) => boolean | PermissionResult | Promise<boolean | PermissionResult>) & PermissionCheckMeta;
231
+ type PermissionCheck<TDoc = Record<string, unknown>> = ((context: PermissionContext<TDoc>) => boolean | AuthorizationDecision | Promise<boolean | AuthorizationDecision>) & PermissionCheckMeta;
226
232
  /**
227
233
  * Optional metadata attached to permission check functions.
228
234
  * Used for OpenAPI data, introspection, and route-level auth decisions.
@@ -236,8 +242,27 @@ type PermissionCheck<TDoc = Record<string, unknown>> = ((context: PermissionCont
236
242
  interface PermissionCheckMeta {
237
243
  /** Set by allowPublic() — marks the endpoint as publicly accessible */
238
244
  _isPublic?: boolean;
245
+ /**
246
+ * Set by requireAuth() — a pure identity gate (must be signed in) that adds NO
247
+ * row-level or environmental condition. Marked so `allOf` does not mistake it
248
+ * for an opaque runtime branch and needlessly taint the composite `conditional`.
249
+ */
250
+ _requiresAuth?: boolean;
239
251
  /** Set by requireRoles() — the roles required for access */
240
252
  _roles?: readonly string[];
253
+ /**
254
+ * Set by `requirePlatformRole()` — this gate consults PLATFORM roles only and
255
+ * can never be satisfied by an organization role.
256
+ *
257
+ * It exists because that property is otherwise unprovable from outside a
258
+ * check. `requireRoles(["ops"])` accepts an ORG role named `ops` by default,
259
+ * and `requireOrgRole("manager")` grants any org's manager — both return a
260
+ * bare allow with no policy, so a surface that must be platform-wide cannot
261
+ * tell them apart from a genuine operator gate by inspecting the decision.
262
+ * A global surface (see `jobsPlugin`'s `managementRoutes`) requires this
263
+ * marker at boot rather than trusting the caller's intent.
264
+ */
265
+ _platformOnly?: boolean;
241
266
  /** Set by requireOrgMembership() — org-level permission type */
242
267
  _orgPermission?: string;
243
268
  /** Set by requireOrgRole() — the org roles required for access */
@@ -285,6 +310,18 @@ interface PermissionCheckMeta {
285
310
  scopes?: readonly string[];
286
311
  dpop: boolean;
287
312
  };
313
+ /**
314
+ * Set by `allOf(...)` when its surfaced role/scope meta is NECESSARY but NOT
315
+ * SUFFICIENT — the conjunction also contains an opaque runtime branch
316
+ * (ownership / custom / dynamic / flow-mode / quota …) or a contradictory
317
+ * constraint that flat metadata can't capture. `describePermission` propagates
318
+ * it as `conditional: true`, so `explainAccess` reports a role/scope MATCH as
319
+ * `conditional` (server decides) instead of a definitive — and unsound —
320
+ * `allow`. A role/scope MISMATCH is still a definitive `deny` (a necessary
321
+ * condition failed). Without this flag a composed gate could tell a UI "you can"
322
+ * when the runtime check will refuse.
323
+ */
324
+ _conditional?: boolean;
288
325
  }
289
326
  //#endregion
290
- export { getUserId as a, AnyRecord as c, ObjectId as d, UserLike as f, UserBase as i, ArcRequest as l, PermissionContext as n, getUserRoles as o, UserOrganization as p, PermissionResult as r, normalizeRoles as s, PermissionCheck as t, JWTPayload as u };
327
+ export { UserBase as a, normalizeRoles as c, JWTPayload as d, ObjectId as f, PermissionContext as i, AnyRecord as l, UserOrganization as m, DataPolicy as n, getUserId as o, UserLike as p, PermissionCheck as r, getUserRoles as s, AuthorizationDecision as t, ArcRequest as u };
@@ -1,3 +1,4 @@
1
+
1
2
  import { FastifyRequest } from "fastify";
2
3
  //#region src/encryption/types.d.ts
3
4
  /** JWE key-management algorithm — the protected-header `alg`. */
@@ -1,3 +1,4 @@
1
+
1
2
  import { PurgeActor, PurgeEvidence, PurgeResourceResult, PurgeStrategyKind as PurgeStrategyKind$1, PurgeVerificationSummary } from "@classytic/primitives/retention";
2
3
  //#region src/cleanup/types.d.ts
3
4
  /** Ambient context every recipe method receives. Host-injected — never global. */
@@ -1,5 +1,6 @@
1
- import { r as EventHandler } from "./EventTransport-QmY7A258.mjs";
2
- import { n as ErrorMapper } from "./errorHandler-C6yv4ZTW.mjs";
1
+
2
+ import { n as DomainEvent, r as EventHandler } from "./EventTransport-2uVV34WU.mjs";
3
+ import { n as ErrorMapper } from "./errorHandler-CpYUJmPA.mjs";
3
4
  import { FastifyInstance, FastifyPluginAsync } from "fastify";
4
5
  import { LockAdapter } from "@classytic/repo-core/lock";
5
6
  //#region src/plugins/health.d.ts
@@ -343,6 +344,37 @@ interface EventHandlerDefinition {
343
344
  * `inventory.order-created`; Arc does not silently rewrite public names.
344
345
  */
345
346
  name?: string;
347
+ /**
348
+ * Contain handler failures inside an error boundary — arc wraps `handler`
349
+ * with `wrapWithBoundary`, so a throw is logged (through `fastify.log`, with
350
+ * `{ err, event, eventId, handler }`) and swallowed instead of reaching the
351
+ * transport.
352
+ *
353
+ * **Off by default, deliberately.** Reaching the transport is what makes the
354
+ * durable path work: `RedisStreamTransport` leaves the message unacked, so it
355
+ * is redelivered and eventually DLQ'd. Silently swallowing by default would
356
+ * turn every module handler into best-effort delivery.
357
+ *
358
+ * Turn it ON for fire-and-forget work — projections, cache invalidation,
359
+ * notification fan-out — where a failure must not block the ack and a retry
360
+ * would only delay the next event's resync. That is precisely the case where
361
+ * a module author would otherwise abandon this arm for an imperative
362
+ * `subscribeWithBoundary` call in `afterResources` and lose arc's
363
+ * teardown-before-`onClose` guarantee.
364
+ *
365
+ * ```ts
366
+ * defineModule({ name: "search", eventHandlers: [
367
+ * { name: "search.reindex", event: "product:*", handler: reindex, boundary: true },
368
+ * ] })
369
+ * ```
370
+ *
371
+ * The object form adds an `onError` sink (metrics / alerting) in place of the
372
+ * default log; it runs INSIDE the boundary, so a throwing `onError` is itself
373
+ * caught and logged rather than escaping.
374
+ */
375
+ boundary?: boolean | {
376
+ onError?: (error: Error, event: DomainEvent) => void | Promise<void>;
377
+ };
346
378
  }
347
379
  interface ArcModule<TExports = unknown> {
348
380
  /** Stable identifier — appears in boot logs and duplicate-module detection. */
@@ -378,6 +410,13 @@ interface ArcModule<TExports = unknown> {
378
410
  * *importing* a dependent until its dependency is ready. Use a thunk to gate
379
411
  * whether a module is imported at all (region/tier packs); use `dependsOn`
380
412
  * to order modules that are already selected.
413
+ *
414
+ * **Convention: every HARD sibling dependency belongs here** — including
415
+ * ones read lazily. `lazyRequiredModuleExports` defers the export READ to
416
+ * first use (and eagerly validates the module is composed), but only
417
+ * `dependsOn` orders composition so the sibling's engine exists before
418
+ * yours initializes. Omit the edge only for genuinely optional
419
+ * integrations (`lazyModuleExports` / `getOptionalModuleExports`).
381
420
  */
382
421
  readonly dependsOn?: readonly string[];
383
422
  /**
@@ -445,15 +484,21 @@ interface ArcModule<TExports = unknown> {
445
484
  * Semantics:
446
485
  * - Purely a supersede-the-app-fork switch — it filters the *app* resource
447
486
  * list, never the module's own `resources` (those always register).
448
- * - Static + declarative: read at compose time, so it works regardless of
449
- * whether `resources` is an array or a post-bootstrap factory (no early
450
- * factory resolution, no boot-order coupling).
451
- * - Idempotent + tolerant: an `owns` entry with no matching app resource is
452
- * a silent no-op — a module may pre-declare a name before any fork exists.
487
+ * - Idempotent + tolerant on the APP side: an `owns` entry with no matching
488
+ * app resource is a silent no-op — a module may pre-declare a name before
489
+ * any fork exists.
453
490
  * - Collected across ALL modules; the app-side supersession is their union.
454
491
  *
455
- * Contract: if you `owns` a name, PROVIDE it (in this module's `resources`).
456
- * Dropping the app fork without supplying a replacement removes the route.
492
+ * **Contract (ENFORCED at boot): if you `owns` a name, PROVIDE it** — in
493
+ * THIS module's own `resources`. Arc resolves module resources first and
494
+ * fails boot when a claimed name is not among them, naming the module, the
495
+ * unmet names, and what it did supply. Without that check, a typo or a
496
+ * resource deleted without updating `owns` booted "successfully" with the
497
+ * app's route silently removed and nothing serving it.
498
+ *
499
+ * A sibling module supplying the name does NOT satisfy the claim — ownership
500
+ * is local to the module that declares it, which is the colocation this arm
501
+ * exists for.
457
502
  */
458
503
  readonly owns?: readonly string[];
459
504
  /**
@@ -538,9 +583,34 @@ interface ArcModule<TExports = unknown> {
538
583
  */
539
584
  readonly scheduledJobs?: ModuleContribution<ScheduleDefinition>;
540
585
  /**
541
- * Teardown — registered as a Fastify `onClose` hook. Destroy engines, stop
542
- * timers, flush the module's outbox. Modules close in REVERSE list order
543
- * (last composed, first closed), mirroring init.
586
+ * Teardown — destroy engines, stop timers, flush the module's outbox.
587
+ * Modules close in REVERSE composition order (last composed, first closed),
588
+ * mirroring init, BEFORE the app-level `onClose` and before infra plugins'
589
+ * own close hooks (so teardown still sees a live DB/Redis).
590
+ *
591
+ * Boot is transactional: if any phase fails mid-boot — including THIS
592
+ * module's own `plugins`/`bootstrap` — arc immediately closes every module
593
+ * that entered an init phase, this closer included, in reverse order, then
594
+ * rethrows the original boot error. A closer runs AT MOST ONCE across the
595
+ * rollback and shutdown paths, and one throwing closer never blocks the
596
+ * rest (best-effort; failures are logged).
597
+ *
598
+ * Because rollback fires after a PARTIAL init — your `bootstrap` opened a
599
+ * client and threw on the next line, or your `plugins` ran but `bootstrap`
600
+ * never did — write closers defensively. Guard everything init may not have
601
+ * reached: `client?.close()`, not `client.close()`.
602
+ *
603
+ * ```ts
604
+ * let client: Client | undefined;
605
+ * defineModule({
606
+ * name: "billing",
607
+ * bootstrap: async () => {
608
+ * client = await openClient(); // allocated…
609
+ * await migrate(client); // …and this may throw
610
+ * },
611
+ * onClose: async () => { await client?.close(); }, // still runs
612
+ * });
613
+ * ```
544
614
  */
545
615
  onClose?: (fastify: FastifyInstance) => void | Promise<void>;
546
616
  }
@@ -1,3 +1,4 @@
1
+
1
2
  //#region src/utils/headers.d.ts
2
3
  /**
3
4
  * Canonical header typing + accessor.
@@ -1,4 +1,5 @@
1
- import { V as ResourceDefinition } from "./index-DPRH0Cme.mjs";
1
+
2
+ import { V as ResourceDefinition } from "./index-CpzxqePp.mjs";
2
3
  import { z } from "zod";
3
4
  //#region src/integrations/mcp/types.d.ts
4
5
  /** Behavioral hints for MCP clients (tool annotations per MCP spec) */
@@ -306,11 +307,6 @@ interface McpPluginOptions {
306
307
  * ```
307
308
  */
308
309
  expose?: string[];
309
- /**
310
- * @deprecated Use `expose` — same default-deny semantics with a clearer
311
- * verb. Kept for backwards compatibility with pre-2.15.5 hosts.
312
- */
313
- include?: string[];
314
310
  /** Tool name prefix: 'crm' → 'crm_list_products' */
315
311
  toolNamePrefix?: string;
316
312
  /** Per-resource overrides (operations, descriptions, hideFields, names, toolNamePrefix) */
@@ -1,6 +1,7 @@
1
- import { l as UnauthorizedError, o as OrgRequiredError } from "./errors-DkO8Nk6-.mjs";
2
- import { n as requireSingleHeaderValue } from "./headers-BvlQSDMB.mjs";
3
- import { t as getUserId$1 } from "./userHelpers-Cg_y3fBz.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { l as UnauthorizedError, o as OrgRequiredError } from "./errors-Cj42AntO.mjs";
3
+ import { n as requireSingleHeaderValue } from "./headers-3zvE0rM3.mjs";
4
+ import { t as getUserId$1 } from "./userHelpers-ChYJ6CdK.mjs";
4
5
  //#region src/scope/types.ts
5
6
  /**
6
7
  * Request Scope — The One Standard
@@ -1,5 +1,6 @@
1
- import { i as RequestScope } from "../types-DjC-KUCz.mjs";
2
- import { n as PermissionContext, t as PermissionCheck } from "../types-Dmw-6Qeo.mjs";
1
+
2
+ import { i as RequestScope } from "../types-ChuShpCP.mjs";
3
+ import { i as PermissionContext, r as PermissionCheck } from "../types-B7XeLEgK.mjs";
3
4
  import { UsageBucket, UsageStore, usagePeriod } from "@classytic/repo-core/usage";
4
5
  import { FastifyPluginAsync, FastifyRequest } from "fastify";
5
6
  //#region src/usage/requireQuota.d.ts
Binary file
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/utils/userHelpers.ts
2
3
  /**
3
4
  * Extract a user ID from a user object. Accepts `id` or `_id` — returns
@@ -1,8 +1,9 @@
1
- import { $ as OpenApiSchemas, S as QueryParserInterface, b as ParsedQuery } from "../index-DPRH0Cme.mjs";
2
- import { F as getHeader, I as requireSingleHeaderValue, P as ArcHeaders } from "../types-DjC-KUCz.mjs";
3
- import { a as getUserId, c as AnyRecord, o as getUserRoles, s as normalizeRoles } from "../types-Dmw-6Qeo.mjs";
4
- import { n as ErrorMapper } from "../errorHandler-C6yv4ZTW.mjs";
5
- import { a as NotFoundError, c as RateLimitError, d as ValidationError, f as createDomainError, i as ForbiddenError, l as ServiceUnavailableError, m as isArcError, n as ConflictError, o as OrgAccessDeniedError, p as createError, r as ErrorOptions, s as OrgRequiredError, t as ArcError, u as UnauthorizedError } from "../errors-DHcHVAgk.mjs";
1
+
2
+ import { $ as OpenApiSchemas, S as QueryParserInterface, b as ParsedQuery } from "../index-CpzxqePp.mjs";
3
+ import { F as getHeader, I as requireSingleHeaderValue, P as ArcHeaders } from "../types-ChuShpCP.mjs";
4
+ import { c as normalizeRoles, l as AnyRecord, o as getUserId, s as getUserRoles } from "../types-B7XeLEgK.mjs";
5
+ import { n as ErrorMapper } from "../errorHandler-CpYUJmPA.mjs";
6
+ import { a as NotFoundError, c as RateLimitError, d as ValidationError, f as createDomainError, i as ForbiddenError, l as ServiceUnavailableError, m as isArcError, n as ConflictError, o as OrgAccessDeniedError, p as createError, r as ErrorOptions, s as OrgRequiredError, t as ArcError, u as UnauthorizedError } from "../errors-BGdVwP25.mjs";
6
7
  import { errorContractSchema, errorDetailSchema } from "@classytic/repo-core/errors";
7
8
  import { scheduleBackground } from "@classytic/repo-core/cache";
8
9
  import { FastifyInstance, FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
@@ -1113,6 +1114,11 @@ declare function getDefaultCrudSchemas(): Record<string, Record<string, unknown>
1113
1114
  * - `openapi-3.1`: OpenAPI 3.1 document generation
1114
1115
  */
1115
1116
  type JsonSchemaTarget = "draft-7" | "draft-2020-12" | "openapi-3.0" | "openapi-3.1";
1117
+ /**
1118
+ * Which of a Zod schema's two shapes to emit. See the module docblock — this is
1119
+ * the difference between accepting and rejecting a legal request.
1120
+ */
1121
+ type SchemaIo = "input" | "output";
1116
1122
  /**
1117
1123
  * Check if an object is already a plain JSON Schema.
1118
1124
  * Returns true if it has JSON Schema markers (`type`, `properties`, `$ref`,
@@ -1152,8 +1158,11 @@ type UnconvertibleMode = "warn" | "throw";
1152
1158
  * Pass `openapi-3.0`/`openapi-3.1` for OpenAPI document generation.
1153
1159
  * @param mode Failure policy for unconvertible Zod schemas — see
1154
1160
  * {@link UnconvertibleMode}. Defaults to `'warn'`.
1161
+ * @param io Which shape to emit — see {@link SchemaIo} and the module
1162
+ * docblock. Defaults to `'output'`, matching Zod's own default;
1163
+ * arc's request-side call sites pass `'input'` explicitly.
1155
1164
  */
1156
- declare function toJsonSchema(input: unknown, target?: JsonSchemaTarget, mode?: UnconvertibleMode): Record<string, unknown> | undefined;
1165
+ declare function toJsonSchema(input: unknown, target?: JsonSchemaTarget, mode?: UnconvertibleMode, io?: SchemaIo): Record<string, unknown> | undefined;
1157
1166
  /**
1158
1167
  * Convert all schema fields in an OpenApiSchemas object.
1159
1168
  * JSON Schema values pass through unchanged. Only Zod schemas are converted.
@@ -1313,9 +1322,6 @@ interface StateMachine {
1313
1322
  * Record a transition
1314
1323
  */
1315
1324
  recordTransition?(from: string, to: string, action: string, metadata?: Record<string, unknown>): void;
1316
- /**
1317
- * Clear history
1318
- */
1319
1325
  clearHistory?(): void;
1320
1326
  /**
1321
1327
  * Get available actions for current status
@@ -1508,4 +1514,4 @@ declare function hasEvents(instance: FastifyInstance): instance is FastifyInstan
1508
1514
  events: EventsDecorator;
1509
1515
  };
1510
1516
  //#endregion
1511
- export { ArcError, type ArcHeaders, ArcQueryParser, type ArcQueryParserOptions, CircuitBreaker, CircuitBreakerError, type CircuitBreakerOptions, CircuitBreakerRegistry, type CircuitBreakerStats, CircuitState, type CompensationDefinition, type CompensationError, type CompensationHooks, type CompensationResult, type CompensationStep, ConflictError, type ErrorOptions, type EventsDecorator, type FilterDialect, ForbiddenError, type Guard, type GuardConfig, type JsonSchema, type JsonSchemaTarget, MONGO_DIALECT, NEUTRAL_DIALECT, NotFoundError, OrgAccessDeniedError, OrgRequiredError, type PipeUIMessageStreamOptions, RateLimitError, ServiceUnavailableError, type SseStream, type SseStreamOptions, type StateMachine, type TransitionConfig, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, ValidationError, aggregateListResponse, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, forwardedStreamHeaders, getDefaultCrudSchemas, getHeader, getListQueryParams, getUserId, getUserRoles, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, normalizeRoles, offsetListResponse, openSseStream, paginationSchema, pipeUIMessageStreamToReply, promoteStreamTokenToHeader, queryParams, requireSingleHeaderValue, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, withCompensation };
1517
+ export { ArcError, type ArcHeaders, ArcQueryParser, type ArcQueryParserOptions, CircuitBreaker, CircuitBreakerError, type CircuitBreakerOptions, CircuitBreakerRegistry, type CircuitBreakerStats, CircuitState, type CompensationDefinition, type CompensationError, type CompensationHooks, type CompensationResult, type CompensationStep, ConflictError, type ErrorOptions, type EventsDecorator, type FilterDialect, ForbiddenError, type Guard, type GuardConfig, type JsonSchema, type JsonSchemaTarget, MONGO_DIALECT, NEUTRAL_DIALECT, NotFoundError, OrgAccessDeniedError, OrgRequiredError, type PipeUIMessageStreamOptions, RateLimitError, type SchemaIo, ServiceUnavailableError, type SseStream, type SseStreamOptions, type StateMachine, type TransitionConfig, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, ValidationError, aggregateListResponse, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, forwardedStreamHeaders, getDefaultCrudSchemas, getHeader, getListQueryParams, getUserId, getUserRoles, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, normalizeRoles, offsetListResponse, openSseStream, paginationSchema, pipeUIMessageStreamToReply, promoteStreamTokenToHeader, queryParams, requireSingleHeaderValue, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, withCompensation };