@classytic/arc 2.30.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-B5DwufbB.mjs → BaseController-De7GqHck.mjs} +16 -17
  5. package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
  6. package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-9mlTgqzE.mjs} +1 -0
  7. package/dist/{HookSystem-WkIougo6.mjs → HookSystem-BcmPyq5I.mjs} +2 -1
  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 +2 -1
  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/{applyPermissionResult-Cf6zUCvb.mjs → authorizationDecision-ChvUQGG1.mjs} +19 -10
  20. package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-CDrCJzmB.mjs} +4 -3
  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 -6
  45. package/dist/{core-poalJLvp.mjs → core-BGpIxINN.mjs} +3 -2
  46. package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-CDXEdasl.mjs} +8 -7
  47. package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-KrQDzx-k.mjs} +7 -6
  48. package/dist/{createApp-CXrKFciH.mjs → createApp-Df89BEni.mjs} +484 -209
  49. package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-DbPPS8RI.mjs} +1 -0
  50. package/dist/{defineResource-CxWqDCAy.mjs → defineResource-Bv6EtN1x.mjs} +63 -38
  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-D2NNR4py.mjs → eventPlugin-CkffEihm.mjs} +5 -4
  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 +16 -4
  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-0WhPnUH7.d.mts → fastify-augmentation-zh0_AYHa.d.mts} +13 -4
  75. package/dist/{fields-CQ_7KQWw.mjs → fields-CB5Cuzk9.mjs} +1 -0
  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 +4 -3
  85. package/dist/idempotency/redis.d.mts +2 -1
  86. package/dist/idempotency/redis.mjs +1 -0
  87. package/dist/{index-Cx7bro4R.d.mts → index-Bc2ox8_U.d.mts} +5 -4
  88. package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
  89. package/dist/{index-Ch16aAah.d.mts → index-CEJNZFtX.d.mts} +53 -15
  90. package/dist/index-CFThn1K9.d.mts +224 -0
  91. package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
  92. package/dist/index.d.mts +9 -8
  93. package/dist/index.mjs +11 -10
  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 +6 -6
  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-nRzm5g2s.mjs → mcpPlugin-B_es0hiF.mjs} +22 -23
  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 -0
  131. package/dist/migrations/index.mjs +2 -1
  132. package/dist/module-0pFJA6YW.mjs +78 -0
  133. package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-wOgj_fnj.mjs} +1 -0
  134. package/dist/{openapi-B8Vkbxbn.mjs → openapi-B2L4js1v.mjs} +6 -5
  135. package/dist/permissions/index.d.mts +5 -4
  136. package/dist/permissions/index.mjs +6 -5
  137. package/dist/{permissions-Bfu_8y1U.mjs → permissions-L--QDAir.mjs} +214 -41
  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-BJnpkY9i.mjs → pipeline-UPQFatit.mjs} +6 -5
  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-DCfa2egz.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 +3 -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-CJOEXLuk.mjs → presets-C4-g4_4P.mjs} +4 -3
  160. package/dist/{projection-UBDgfMwu.mjs → projection-BHw6xlOQ.mjs} +2 -1
  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-B9nmIY5V.mjs → realtime-C5NoxWFY.mjs} +20 -9
  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-JkxIEBJq.mjs → registerRoute-CBN84fc7.mjs} +4 -3
  170. package/dist/registry/index.d.mts +3 -2
  171. package/dist/registry/index.mjs +3 -2
  172. package/dist/{registry-BYXUUg21.mjs → registry-4213U4zb.mjs} +2 -1
  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-Dz8k3S4P.mjs → repositoryFilter-f9eAfq_l.mjs} +1 -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-DfzsivM6.mjs → subscribe-helpers-C0Tb2aUp.mjs} +2 -1
  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 +139 -12
  201. package/dist/testing/index.mjs +230 -16
  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-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
  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-D_n8L6VY.d.mts → types-CBgvkp8O.d.mts} +51 -12
  217. package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
  218. package/dist/{types-Bmmn-fO0.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 -7
  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 +547 -539
  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-CCzVR-N3.d.mts +0 -107
  239. package/dist/module-_-M7C5ES.mjs +0 -29
@@ -1,3 +1,5 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { n as evaluateAndApplyPermission } from "../../authorizationDecision-ChvUQGG1.mjs";
1
3
  import fp from "fastify-plugin";
2
4
  //#region src/integrations/jobs/execution.ts
3
5
  async function executeTimedHandler(options) {
@@ -149,6 +151,49 @@ const jobsPluginImpl = async (fastify, options) => {
149
151
  const dlqQueues = /* @__PURE__ */ new Map();
150
152
  const workers = /* @__PURE__ */ new Map();
151
153
  const throttledJobs = /* @__PURE__ */ new Map();
154
+ const seenNames = /* @__PURE__ */ new Set();
155
+ for (const job of jobs) {
156
+ if (typeof job.name !== "string" || job.name.trim() === "") throw new Error("[arc/jobs] a job definition has an empty name — names are the queue key.");
157
+ if (seenNames.has(job.name)) throw new Error(`[arc/jobs] duplicate job name "${job.name}". A name is the queue key, so two definitions sharing one would leave an untracked worker consuming the same queue after shutdown. Rename one, or register it in a single definition.`);
158
+ seenNames.add(job.name);
159
+ const positiveInt = (v, field) => {
160
+ if (v === void 0) return;
161
+ if (typeof v !== "number" || !Number.isInteger(v) || v <= 0) throw new Error(`[arc/jobs] Job '${job.name}' has ${field}=${String(v)} — must be a positive integer.`);
162
+ };
163
+ const nonNegativeInt = (v, field) => {
164
+ if (v === void 0) return;
165
+ if (typeof v !== "number" || !Number.isInteger(v) || v < 0) throw new Error(`[arc/jobs] Job '${job.name}' has ${field}=${String(v)} — must be a non-negative integer.`);
166
+ };
167
+ positiveInt(job.maxConcurrent, "maxConcurrent");
168
+ positiveInt(job.concurrency, "concurrency");
169
+ positiveInt(job.timeout, "timeout");
170
+ nonNegativeInt(job.retries, "retries");
171
+ nonNegativeInt(job.cancelGraceMs, "cancelGraceMs");
172
+ if (job.rateLimit) {
173
+ positiveInt(job.rateLimit.max, "rateLimit.max");
174
+ positiveInt(job.rateLimit.duration, "rateLimit.duration");
175
+ }
176
+ if (job.backoff) nonNegativeInt(job.backoff.delay, "backoff.delay");
177
+ if (job.repeat) {
178
+ positiveInt(job.repeat.every, "repeat.every");
179
+ positiveInt(job.repeat.limit, "repeat.limit");
180
+ if (job.repeat.pattern !== void 0 && job.repeat.pattern.trim() === "") throw new Error(`[arc/jobs] Job '${job.name}' has an empty repeat.pattern.`);
181
+ }
182
+ }
183
+ if (defaults) {
184
+ const d = defaults;
185
+ const defaultPositiveInt = (v, field) => {
186
+ if (v === void 0) return;
187
+ if (typeof v !== "number" || !Number.isInteger(v) || v <= 0) throw new Error(`[arc/jobs] defaults.${field}=${String(v)} — must be a positive integer.`);
188
+ };
189
+ const defaultNonNegativeInt = (v, field) => {
190
+ if (v === void 0) return;
191
+ if (typeof v !== "number" || !Number.isInteger(v) || v < 0) throw new Error(`[arc/jobs] defaults.${field}=${String(v)} — must be a non-negative integer.`);
192
+ };
193
+ defaultNonNegativeInt(d.retries, "retries");
194
+ defaultPositiveInt(d.timeout, "timeout");
195
+ if (d.backoff) defaultNonNegativeInt(d.backoff.delay, "backoff.delay");
196
+ }
152
197
  for (const job of jobs) {
153
198
  if (!job.repeat) continue;
154
199
  const { pattern, every, tz } = job.repeat;
@@ -296,19 +341,22 @@ const jobsPluginImpl = async (fastify, options) => {
296
341
  }, `[arc/jobs] Large job payload — prefer passing IDs and reloading in the handler`);
297
342
  } catch {}
298
343
  const jobDef = jobDefsByName.get(name);
299
- return { jobId: (await queue.add(name, data, {
300
- delay: opts.delay,
301
- priority: opts.priority,
302
- jobId: opts.jobId,
303
- removeOnComplete: opts.removeOnComplete ?? defaults.removeOnComplete ?? 100,
304
- removeOnFail: opts.removeOnFail ?? defaults.removeOnFail ?? 500,
305
- attempts: jobDef?.retries ?? defaults.retries ?? 3,
306
- backoff: jobDef?.backoff ?? defaults.backoff ?? {
307
- type: "exponential",
308
- delay: 1e3
309
- },
310
- repeat: jobDef?.repeat ?? opts.repeat
311
- })).id };
344
+ return {
345
+ queue: name,
346
+ jobId: (await queue.add(name, data, {
347
+ delay: opts.delay,
348
+ priority: opts.priority,
349
+ jobId: opts.jobId,
350
+ removeOnComplete: opts.removeOnComplete ?? defaults.removeOnComplete ?? 100,
351
+ removeOnFail: opts.removeOnFail ?? defaults.removeOnFail ?? 500,
352
+ attempts: jobDef?.retries ?? defaults.retries ?? 3,
353
+ backoff: jobDef?.backoff ?? defaults.backoff ?? {
354
+ type: "exponential",
355
+ delay: 1e3
356
+ },
357
+ repeat: jobDef?.repeat ?? opts.repeat
358
+ })).id
359
+ };
312
360
  },
313
361
  getQueue(name) {
314
362
  return queues.get(name) ?? null;
@@ -327,10 +375,12 @@ const jobsPluginImpl = async (fastify, options) => {
327
375
  }
328
376
  return stats;
329
377
  },
330
- async getStatus(jobId) {
331
- for (const [name, queue] of queues) {
378
+ async getStatus(queueName, jobId) {
379
+ const queue = queues.get(queueName);
380
+ if (queue) {
381
+ const name = queueName;
332
382
  const job = await queue.getJob(jobId);
333
- if (!job) continue;
383
+ if (!job) return null;
334
384
  const state = typeof job.getState === "function" ? await job.getState() : "unknown";
335
385
  const throttled = throttledJobs.get(name)?.has(jobId) || void 0;
336
386
  return {
@@ -358,24 +408,50 @@ const jobsPluginImpl = async (fastify, options) => {
358
408
  }
359
409
  };
360
410
  if (!fastify.hasDecorator("jobs")) fastify.decorate("jobs", dispatcher);
361
- fastify.get(`${prefix}/stats`, async () => {
362
- return {
363
- success: true,
364
- data: await dispatcher.getStats()
411
+ const management = options.managementRoutes;
412
+ if (management) {
413
+ const gate = management.operatorPermission;
414
+ if (!gate._platformOnly && !management.allowUnverifiedOperatorPermission) throw new Error("[arc/jobs] managementRoutes.operatorPermission must be platform-only. These routes are global (jobs carry no tenant identity), so an org-role gate would let a member of one organization read another's jobs. Use requirePlatformRole('platform-ops') — or requireRoles([...], { includeOrgRoles: false }) with allowUnverifiedOperatorPermission: true if you have verified the check yourself.");
415
+ const guard = async (req, reply) => {
416
+ if (!await evaluateAndApplyPermission(gate, {
417
+ user: req.user ?? null,
418
+ request: req,
419
+ resource: "jobs",
420
+ action: "read"
421
+ }, req, reply)) return false;
422
+ const policy = req._policyFilters;
423
+ if (policy && Object.keys(policy).length > 0) {
424
+ fastify.log.error("[arc/jobs] managementRoutes.operatorPermission returned a row-level policy, which this surface cannot apply — jobs carry no tenant identity. Gate it on an operator role (e.g. requireRoles(['platform-ops'])) and serve tenant-facing job status from a resource that owns its own row policy.");
425
+ await reply.status(403).send({
426
+ code: "arc.jobs.policy_unsupported",
427
+ message: "Job management routes are an operator surface and cannot apply a row-level policy.",
428
+ status: 403
429
+ });
430
+ return false;
431
+ }
432
+ return true;
365
433
  };
366
- });
367
- fastify.get(`${prefix}/:id/status`, async (req, reply) => {
368
- const { id } = req.params;
369
- const status = await dispatcher.getStatus(id);
370
- if (!status) return reply.status(404).send({
371
- success: false,
372
- error: "Job not found"
434
+ fastify.get(`${prefix}/stats`, async (req, reply) => {
435
+ if (!await guard(req, reply)) return reply;
436
+ return { stats: await dispatcher.getStats() };
373
437
  });
374
- return {
375
- success: true,
376
- data: status
377
- };
378
- });
438
+ fastify.get(`${prefix}/:queue/:id/status`, async (req, reply) => {
439
+ if (!await guard(req, reply)) return reply;
440
+ const { queue, id } = req.params;
441
+ const status = await dispatcher.getStatus(queue, id);
442
+ if (!status) return reply.status(404).send({
443
+ code: "arc.not_found",
444
+ message: "Job not found",
445
+ status: 404
446
+ });
447
+ const { returnValue, failedReason, ...safe } = status;
448
+ return {
449
+ ...safe,
450
+ ...management.exposeResult ? { returnValue } : {},
451
+ ...management.exposeFailureReason ? { failedReason } : {}
452
+ };
453
+ });
454
+ }
379
455
  fastify.addHook("onClose", async () => {
380
456
  await dispatcher.close();
381
457
  });
@@ -1,8 +1,9 @@
1
- import { Rt as IControllerResponse, V as ResourceDefinition, Vt as ServerAccessor, zt as IRequestContext } from "../../index-Q5gzEIWY.mjs";
2
- import { i as RequestScope } from "../../types-DjC-KUCz.mjs";
3
- import { r as PermissionCheck } from "../../types-ChvvVNP8.mjs";
4
- import { n as FieldPermissionMap } from "../../fields-D3lhgzhD.mjs";
5
- import { _ as ToolDefinition, a as CrudDescriptionOverride, c as McpAuthResult, d as McpResourceConfig, f as PromptDefinition, g as ToolContext, h as ToolAnnotations, i as CrudDescriptionMeta, l as McpExecutionWiring, m as SessionEntry, n as CallToolResult, o as CrudOperation, p as PromptResult, r as CreateMcpServerConfig, s as McpAuthResolver, t as BetterAuthHandler, u as McpPluginOptions } from "../../types-Bmmn-fO0.mjs";
1
+
2
+ import { Ht as ServerAccessor, Rt as IControllerResponse, V as ResourceDefinition, zt as IRequestContext } from "../../index-CpzxqePp.mjs";
3
+ import { i as RequestScope } from "../../types-ChuShpCP.mjs";
4
+ import { r as PermissionCheck } from "../../types-B7XeLEgK.mjs";
5
+ import { n as FieldPermissionMap } from "../../fields-I_EeRWND.mjs";
6
+ import { _ as ToolDefinition, a as CrudDescriptionOverride, c as McpAuthResult, d as McpResourceConfig, f as PromptDefinition, g as ToolContext, h as ToolAnnotations, i as CrudDescriptionMeta, l as McpExecutionWiring, m as SessionEntry, n as CallToolResult, o as CrudOperation, p as PromptResult, r as CreateMcpServerConfig, s as McpAuthResolver, t as BetterAuthHandler, u as McpPluginOptions } from "../../types-CwcUQ610.mjs";
6
7
  import { ErrorContract } from "@classytic/repo-core/errors";
7
8
  import { FastifyPluginAsync } from "fastify";
8
9
  import { z } from "zod";
@@ -529,7 +530,6 @@ declare module "fastify" {
529
530
  }
530
531
  interface ResourceFilterInputs {
531
532
  readonly expose?: readonly string[];
532
- readonly include?: readonly string[];
533
533
  readonly exclude?: readonly string[];
534
534
  }
535
535
  /**
@@ -1,4 +1,5 @@
1
- import { a as defaultCrudDescription, c as mcpHandlerAdapter, d as toCallToolResult, f as toCallToolSuccess, h as resolveToolCollisions, i as fieldRulesToZod, l as permissionDeniedResult, m as createMcpServer, n as mcpPlugin, o as resolveCrudDescription, p as buildRequestContext, r as resourceToTools, s as invokeController, t as filterResourcesForMcp, u as toCallToolError } from "../../mcpPlugin-nRzm5g2s.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { a as defaultCrudDescription, c as mcpHandlerAdapter, d as toCallToolResult, f as toCallToolSuccess, h as resolveToolCollisions, i as fieldRulesToZod, l as permissionDeniedResult, m as createMcpServer, n as mcpPlugin, o as resolveCrudDescription, p as buildRequestContext, r as resourceToTools, s as invokeController, t as filterResourcesForMcp, u as toCallToolError } from "../../mcpPlugin-B_es0hiF.mjs";
2
3
  //#region src/integrations/mcp/defineTool.ts
3
4
  /**
4
5
  * Define a type-safe MCP tool.
@@ -1,8 +1,9 @@
1
- import { c as McpAuthResult, u as McpPluginOptions } from "../../types-Bmmn-fO0.mjs";
1
+
2
+ import { c as McpAuthResult, u as McpPluginOptions } from "../../types-CwcUQ610.mjs";
2
3
  //#region src/integrations/mcp/testing.d.ts
3
4
  interface TestMcpClientOptions {
4
5
  /** MCP plugin options (resources, overrides, etc.) — same as mcpPlugin config */
5
- pluginOptions?: Pick<McpPluginOptions, "resources" | "overrides" | "expose" | "include" | "exclude" | "toolNamePrefix" | "extraTools" | "extraPrompts" | "instructions">;
6
+ pluginOptions?: Pick<McpPluginOptions, "resources" | "overrides" | "expose" | "exclude" | "toolNamePrefix" | "extraTools" | "extraPrompts" | "instructions">;
6
7
  /** Auth identity for the test session */
7
8
  auth?: McpAuthResult | null;
8
9
  /** Server name (default: 'test-mcp') */
@@ -1,4 +1,5 @@
1
- import { m as createMcpServer, r as resourceToTools, t as filterResourcesForMcp } from "../../mcpPlugin-nRzm5g2s.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { m as createMcpServer, r as resourceToTools, t as filterResourcesForMcp } from "../../mcpPlugin-B_es0hiF.mjs";
2
3
  //#region src/integrations/mcp/testing.ts
3
4
  /**
4
5
  * @classytic/arc/mcp/testing — MCP Test Utilities
@@ -54,7 +55,6 @@ async function createTestMcpClient(options = {}) {
54
55
  const overrides = pluginOpts.overrides ?? {};
55
56
  const tools = filterResourcesForMcp(pluginOpts.resources ?? [], {
56
57
  expose: pluginOpts.expose,
57
- include: pluginOpts.include,
58
58
  exclude: pluginOpts.exclude
59
59
  }).flatMap((r) => {
60
60
  const resOverrides = overrides[r.name] ?? {};
@@ -1,3 +1,4 @@
1
+
1
2
  import { FastifyPluginAsync, FastifyRequest } from "fastify";
2
3
  //#region src/integrations/streamline.d.ts
3
4
  /**
@@ -1,5 +1,6 @@
1
- import { f as createError, i as NotFoundError, r as ForbiddenError } from "../errors-DkO8Nk6-.mjs";
2
- import { a as promoteStreamTokenToHeader, n as forwardedStreamHeaders } from "../streaming-BQcW6_Kq.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { f as createError, i as NotFoundError, r as ForbiddenError } from "../errors-Cj42AntO.mjs";
3
+ import { a as promoteStreamTokenToHeader, n as forwardedStreamHeaders } from "../streaming-PSZwi8JV.mjs";
3
4
  import fp from "fastify-plugin";
4
5
  //#region src/integrations/streamline.ts
5
6
  /**
@@ -1,3 +1,4 @@
1
+
1
2
  import { FastifyPluginAsync } from "fastify";
2
3
  //#region src/integrations/webhooks.d.ts
3
4
  interface WebhookSubscription {
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  import { createHmac, timingSafeEqual } from "node:crypto";
2
3
  import fp from "fastify-plugin";
3
4
  //#region src/integrations/webhooks.ts
@@ -1,4 +1,5 @@
1
- import { c as SerializedEntry, i as Principal, n as FencedWriteOutcome, s as PushRefStore, t as EnvelopeSnapshot } from "../pushref-registry-BbcnpNTm.mjs";
1
+
2
+ import { c as SerializedEntry, i as Principal, n as FencedWriteOutcome, s as PushRefStore, t as EnvelopeSnapshot } from "../pushref-registry-Dov9l4qE.mjs";
2
3
  //#region src/integrations/websocket-pushref-redis.d.ts
3
4
  /**
4
5
  * Minimal `ioredis` shape — typed structurally so this file doesn't
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/integrations/websocket-pushref-redis.ts
2
3
  /**
3
4
  * Lua script for atomic claim. Runs server-side, single-roundtrip.
@@ -1,4 +1,5 @@
1
- import { f as WebSocketAdapter } from "../websocket-_Pd0CgR0.mjs";
1
+
2
+ import { f as WebSocketAdapter } from "../websocket-BOXVggMf.mjs";
2
3
  //#region src/integrations/websocket-redis.d.ts
3
4
  interface RedisLike {
4
5
  publish(channel: string, message: string): Promise<number>;
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/integrations/websocket-redis.ts
2
3
  /**
3
4
  * Redis Pub/Sub adapter for cross-instance WebSocket broadcast.
@@ -1,3 +1,4 @@
1
- import { a as GeoRoomOptions, c as WebSocketClient, d as LocalWebSocketAdapter, f as WebSocketAdapter, i as GeoRoom, l as WebSocketMessage, n as GeoPoint, o as RoomManager, r as GeoPublishOpts, s as AuthResult, t as websocketPlugin, u as WebSocketPluginOptions } from "../websocket-_Pd0CgR0.mjs";
2
- import { a as PushRefRegistry, c as SerializedEntry, i as Principal, o as PushRefRegistryOptions, r as MemoryPushRefStore, s as PushRefStore } from "../pushref-registry-BbcnpNTm.mjs";
1
+
2
+ import { a as GeoRoomOptions, c as WebSocketClient, d as LocalWebSocketAdapter, f as WebSocketAdapter, i as GeoRoom, l as WebSocketMessage, n as GeoPoint, o as RoomManager, r as GeoPublishOpts, s as AuthResult, t as websocketPlugin, u as WebSocketPluginOptions } from "../websocket-BOXVggMf.mjs";
3
+ import { a as PushRefRegistry, c as SerializedEntry, i as Principal, o as PushRefRegistryOptions, r as MemoryPushRefStore, s as PushRefStore } from "../pushref-registry-Dov9l4qE.mjs";
3
4
  export { type AuthResult, type GeoPoint, type GeoPublishOpts, GeoRoom, type GeoRoomOptions, LocalWebSocketAdapter, MemoryPushRefStore, type Principal, PushRefRegistry, type PushRefRegistryOptions, type PushRefStore, RoomManager, type SerializedEntry, type WebSocketAdapter, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, websocketPlugin };
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  import { randomUUID } from "node:crypto";
2
3
  import sjson from "secure-json-parse";
3
4
  import fp from "fastify-plugin";
@@ -1,3 +1,4 @@
1
+
1
2
  import { CacheAdapter } from "@classytic/repo-core/cache";
2
3
  //#region src/cache/interface.d.ts
3
4
  interface CacheLogger {
@@ -1,3 +1,4 @@
1
+
1
2
  //#region src/idempotency/stores/interface.d.ts
2
3
  /**
3
4
  * Idempotency Store Interface
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/idempotency/stores/interface.ts
2
3
  /**
3
4
  * Helper to create a result object
@@ -1,4 +1,5 @@
1
- import { t as ArcError } from "./errors-DkO8Nk6-.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as ArcError } from "./errors-Cj42AntO.mjs";
2
3
  import sjson from "secure-json-parse";
3
4
  //#region src/utils/jsonBody.ts
4
5
  /**
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/cache/keys.ts
2
3
  /**
3
4
  * Cache Key Utilities
@@ -1,4 +1,5 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
2
3
  import { arcLog } from "./logger/index.mjs";
3
4
  import { readdir } from "node:fs/promises";
4
5
  import { dirname, join, resolve } from "node:path";
@@ -1,4 +1,5 @@
1
- import { t as ResourceRegistry } from "./ResourceRegistry-y9Hnypus.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as ResourceRegistry } from "./ResourceRegistry-qq0mn2s9.mjs";
2
3
  import { resolve } from "node:path";
3
4
  import { pathToFileURL } from "node:url";
4
5
  //#region src/cli/utils/loadResourcesFromEntry.ts
@@ -1,3 +1,4 @@
1
+
1
2
  //#region src/logger/index.d.ts
2
3
  /**
3
4
  * Arc Logger — Centralized debug & warning system
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/logger/index.ts
2
3
  let globalOptions = {};
3
4
  /**
@@ -1,18 +1,19 @@
1
- import { p as isArcError, t as ArcError } from "./errors-DkO8Nk6-.mjs";
2
- import { n as requireSingleHeaderValue } from "./headers-BvlQSDMB.mjs";
3
- import { b as isElevated, c as getOrgId, g as getUserId, x as isMember } from "./types-CSyCxl2V.mjs";
4
- import { t as BaseController } from "./BaseController-B5DwufbB.mjs";
5
- import { i as evaluatePermissionDecision } from "./applyPermissionResult-Cf6zUCvb.mjs";
6
- import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-CQ_7KQWw.mjs";
7
- import { t as executePipeline } from "./pipe-BOLmGIxa.mjs";
8
- import { t as buildRequestScopeProjection } from "./projection-UBDgfMwu.mjs";
9
- import { r as resolvePipelineSteps } from "./pipeline-BJnpkY9i.mjs";
10
- import { n as validateAggregations } from "./validate-Bk44F2yT.mjs";
11
- import { n as executeAggregation } from "./buildHandler-BYS3Vkfz.mjs";
12
- import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
13
- import { t as resolveActionPermission } from "./actionPermissions-CAphcmUG.mjs";
14
- import { t as createIdempotencyResult } from "./interface-n5hpKg1d.mjs";
15
- import { r as shouldRejectAdditionalProperties, t as normalizeSchemaIR } from "./schemaIR-Ca7ySNPx.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { r as evaluatePermissionDecision } from "./authorizationDecision-ChvUQGG1.mjs";
3
+ import { p as isArcError, t as ArcError } from "./errors-Cj42AntO.mjs";
4
+ import { n as requireSingleHeaderValue } from "./headers-3zvE0rM3.mjs";
5
+ import { b as isElevated, c as getOrgId, g as getUserId, x as isMember } from "./types-Cys0ko9Z.mjs";
6
+ import { t as BaseController } from "./BaseController-De7GqHck.mjs";
7
+ import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-CB5Cuzk9.mjs";
8
+ import { t as executePipeline } from "./pipe-DRDNsI2T.mjs";
9
+ import { t as buildRequestScopeProjection } from "./projection-BHw6xlOQ.mjs";
10
+ import { r as resolvePipelineSteps } from "./pipeline-UPQFatit.mjs";
11
+ import { n as validateAggregations } from "./validate-_KbifpHF.mjs";
12
+ import { n as executeAggregation } from "./buildHandler-CDrCJzmB.mjs";
13
+ import { t as pluralize } from "./pluralize-O0FZgESl.mjs";
14
+ import { t as resolveActionPermission } from "./actionPermissions-BE5NwaQk.mjs";
15
+ import { t as createIdempotencyResult } from "./interface-DYzM0q-u.mjs";
16
+ import { r as shouldRejectAdditionalProperties, t as normalizeSchemaIR } from "./schemaIR-Bm2enbnh.mjs";
16
17
  import { isHttpError, toErrorContract } from "@classytic/repo-core/errors";
17
18
  import { createHash, randomUUID } from "node:crypto";
18
19
  import fp from "fastify-plugin";
@@ -1634,7 +1635,7 @@ function mapJsonSchemaTypeToArcType(jsonType) {
1634
1635
  *
1635
1636
  * 1. `mcpHandler` (full bypass) — caller-supplied function owns the whole
1636
1637
  * tool result; pipeline is not invoked.
1637
- * 2. Function handler with `raw: false/undefined` — arc's pipeline wrapper
1638
+ * 2. Function in `handler` (the arc pipeline) — arc's pipeline wrapper
1638
1639
  * runs normally, and the envelope is serialized into the tool result.
1639
1640
  * 3. String handler — looks up a method on the controller by name.
1640
1641
  */
@@ -1872,10 +1873,10 @@ function resourceToTools(resource, config = {}) {
1872
1873
  for (const route of resource.routes ?? []) {
1873
1874
  if (route.mcp === false) continue;
1874
1875
  const mcpHandler = route.mcpHandler;
1875
- if (!!route.raw && !mcpHandler) continue;
1876
+ if (!(route.rawHandler === void 0) && !mcpHandler) continue;
1876
1877
  if (!mcpHandler && typeof route.handler === "string" && !controller) continue;
1877
1878
  const routeWithRef = route;
1878
- let resolvedRouteHandler = route.handler;
1879
+ let resolvedRouteHandler = route.handler ?? route.rawHandler;
1879
1880
  if (typeof routeWithRef.controllerMethod === "function" && !resolvedRouteHandler) {
1880
1881
  if (!controller) continue;
1881
1882
  const referenced = routeWithRef.controllerMethod(controller);
@@ -2190,7 +2191,6 @@ const mcpPluginImpl = async (fastify, options) => {
2190
2191
  }
2191
2192
  const enabledResources = filterResourcesForMcp(options.resources, {
2192
2193
  expose: options.expose,
2193
- include: options.include,
2194
2194
  exclude: options.exclude
2195
2195
  });
2196
2196
  const fastifyAny = fastify;
@@ -2465,11 +2465,10 @@ function registerStatefulRoutes(fastify, prefix, options, cache, createServer, T
2465
2465
  * same precedence rules without duplicating them.
2466
2466
  */
2467
2467
  function filterResourcesForMcp(resources, inputs) {
2468
- const { expose, include, exclude } = inputs;
2469
- if (expose && include) throw new Error("mcpPlugin: pass either `expose` (preferred) or `include` (legacy alias), not both.");
2470
- if (expose && exclude) throw new Error("mcpPlugin: `expose` is default-deny — `exclude` is redundant. Drop `exclude` or switch to `include`/`exclude` for default-allow semantics.");
2468
+ const { expose, exclude } = inputs;
2469
+ if (expose && exclude) throw new Error("mcpPlugin: `expose` is default-deny (an allowlist) — `exclude` is redundant alongside it. Use `expose` to name what to surface, OR `exclude` to drop specific resources from the default-allow set. Not both.");
2471
2470
  const eligible = resources.filter((r) => r.mcp !== false);
2472
- const allow = expose ?? include;
2471
+ const allow = expose;
2473
2472
  if (allow) {
2474
2473
  const allowSet = new Set(allow);
2475
2474
  return eligible.filter((r) => allowSet.has(r.name));
@@ -1,4 +1,5 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
2
3
  //#region src/cache/memory.ts
3
4
  var memory_exports = /* @__PURE__ */ __exportAll({ MemoryCacheStore: () => MemoryCacheStore });
4
5
  /**
@@ -1,4 +1,5 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
2
3
  import fp from "fastify-plugin";
3
4
  //#region src/plugins/metrics.ts
4
5
  var metrics_exports = /* @__PURE__ */ __exportAll({
@@ -1,4 +1,5 @@
1
- import { I as MiddlewareHandler, L as RequestWithExtras, Q as MiddlewareConfig } from "../index-Q5gzEIWY.mjs";
1
+
2
+ import { I as MiddlewareHandler, L as RequestWithExtras, Q as MiddlewareConfig } from "../index-CpzxqePp.mjs";
2
3
  import { RouteHandlerMethod } from "fastify";
3
4
  //#region src/middleware/middleware.d.ts
4
5
  interface NamedMiddleware {
@@ -1,5 +1,6 @@
1
- import { t as CRUD_OPERATIONS } from "../constants-DNre0wRg.mjs";
2
- import { t as multipartBody } from "../multipartBody-D0eBvkeq.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as CRUD_OPERATIONS } from "../constants-D3Dv4LAV.mjs";
3
+ import { t as multipartBody } from "../multipartBody-wOgj_fnj.mjs";
3
4
  //#region src/middleware/middleware.ts
4
5
  /**
5
6
  * Named Middleware — Priority-based, conditional middleware execution.
@@ -1,3 +1,4 @@
1
+
1
2
  import { LockAdapter } from "@classytic/repo-core/lock";
2
3
  //#region src/migrations/index.d.ts
3
4
  interface Migration {
@@ -1,4 +1,5 @@
1
- import { t as startRenewingLease } from "../renewingLease-3cuQH7h8.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as startRenewingLease } from "../renewingLease-Dll8mGgc.mjs";
2
3
  import { createHash, randomUUID } from "node:crypto";
3
4
  //#region src/migrations/index.ts
4
5
  /**
@@ -0,0 +1,78 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ //#region src/factory/module/index.ts
3
+ /**
4
+ * Identity helper for authoring a typed module — mirrors `defineResource`.
5
+ * Gives inference + a single obvious construction site; does no work.
6
+ *
7
+ * `TExports` is inferred from the `bootstrap` return value, so a module
8
+ * author gets a typed public export for free:
9
+ *
10
+ * ```ts
11
+ * export const accountingModule = (deps: Deps) =>
12
+ * defineModule({
13
+ * name: "accounting",
14
+ * bootstrap: async () => createAccountingEngine(deps), // TExports inferred
15
+ * });
16
+ * ```
17
+ */
18
+ function defineModule(module) {
19
+ return module;
20
+ }
21
+ function getModuleExports(fastify, name) {
22
+ const recorded = readModuleExports(fastify, name);
23
+ if (recorded === ABSENT) {
24
+ const available = fastify.arc?.modules ? Object.keys(fastify.arc.modules) : [];
25
+ throw new Error(`[arc] no public export recorded for module "${name}".\nA module's export is its bootstrap() return value; it is readable only AFTER that module's bootstrap ran (dependsOn / list order = init order).\nModules with recorded exports: ${available.length ? available.join(", ") : "(none)"}.`);
26
+ }
27
+ return recorded;
28
+ }
29
+ /**
30
+ * Sentinel for "no entry recorded", distinct from a recorded `undefined`.
31
+ *
32
+ * registerResources never records an `undefined` export, so today the two
33
+ * cannot both happen — but encoding absence as `undefined` would make the
34
+ * optional/required accessors disagree the day that changes, and a required
35
+ * accessor that stops throwing is exactly the silent-null class of bug these
36
+ * helpers exist to remove.
37
+ */
38
+ const ABSENT = Symbol("arc.module.absent");
39
+ /** The one honest read of the module-export map, shared by every accessor. */
40
+ function readModuleExports(fastify, name) {
41
+ const modules = fastify.arc?.modules;
42
+ if (!modules || !Object.hasOwn(modules, name)) return ABSENT;
43
+ return modules[name];
44
+ }
45
+ function getOptionalModuleExports(fastify, name) {
46
+ const recorded = readModuleExports(fastify, name);
47
+ return recorded === ABSENT ? void 0 : recorded;
48
+ }
49
+ /**
50
+ * Is a module's public export recorded yet? The predicate form of
51
+ * `getOptionalModuleExports`, for readiness gates (`ready: () => ...`) that
52
+ * should not have to reason about falsy-but-present exports.
53
+ */
54
+ function hasModuleExports(fastify, name) {
55
+ return readModuleExports(fastify, name) !== ABSENT;
56
+ }
57
+ function lazyModuleExports(fastify, name) {
58
+ let resolved = ABSENT;
59
+ return () => {
60
+ if (resolved === ABSENT) resolved = readModuleExports(fastify, name);
61
+ return resolved === ABSENT ? void 0 : resolved;
62
+ };
63
+ }
64
+ function lazyRequiredModuleExports(fastify, name) {
65
+ const states = fastify.arc?.moduleStates;
66
+ if (states !== void 0 && !Object.hasOwn(states, name)) {
67
+ const composed = Object.keys(states);
68
+ throw new Error(`[arc] lazyRequiredModuleExports("${name}"): module "${name}" is not in the composed module graph. A lazily-required module is still a HARD dependency — compose it (and declare it in the consumer's \`dependsOn\`), or use lazyModuleExports() if the integration is genuinely optional.
69
+ Composed modules: ${composed.length ? composed.join(", ") : "(none)"}.`);
70
+ }
71
+ let resolved = ABSENT;
72
+ return () => {
73
+ if (resolved === ABSENT) resolved = getModuleExports(fastify, name);
74
+ return resolved;
75
+ };
76
+ }
77
+ //#endregion
78
+ export { lazyModuleExports as a, hasModuleExports as i, getModuleExports as n, lazyRequiredModuleExports as o, getOptionalModuleExports as r, defineModule as t };
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  import sjson from "secure-json-parse";
2
3
  //#region src/middleware/multipartBody.ts
3
4
  const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
@@ -1,8 +1,9 @@
1
- import { n as getUserRoles } from "./userHelpers-Cg_y3fBz.mjs";
2
- import { n as convertRouteSchema } from "./schemaConverter-DJvodiHj.mjs";
3
- import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
4
- import { t as resolveActionPermission } from "./actionPermissions-CAphcmUG.mjs";
5
- import { t as buildActionBodySchema } from "./createActionRouter-BxuywVRB.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { n as getUserRoles } from "./userHelpers-ChYJ6CdK.mjs";
3
+ import { n as convertRouteSchema } from "./schemaConverter-D--wdJM-.mjs";
4
+ import { t as pluralize } from "./pluralize-O0FZgESl.mjs";
5
+ import { t as resolveActionPermission } from "./actionPermissions-BE5NwaQk.mjs";
6
+ import { t as buildActionBodySchema } from "./createActionRouter-CDXEdasl.mjs";
6
7
  import fp from "fastify-plugin";
7
8
  //#region src/docs/openapi/canonical-schemas.ts
8
9
  /**