@classytic/arc 2.38.0 → 2.41.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 (196) hide show
  1. package/dist/{BaseController-CYaDvmOB.mjs → BaseController-DYJRZ0EJ.mjs} +114 -24
  2. package/dist/{EventTransport-Cx60_s-6.d.mts → EventTransport-CbUKDzZZ.d.mts} +33 -0
  3. package/dist/{EventTransport-Gq7JWbWw.mjs → EventTransport-n7qO5Cz3.mjs} +22 -2
  4. package/dist/{HookSystem-C0ikzqQf.mjs → HookSystem-CxvZBo77.mjs} +2 -2
  5. package/dist/{ResourceRegistry-DPcX--zk.mjs → ResourceRegistry-Cu7uTJp9.mjs} +2 -2
  6. package/dist/{actionPermissions-jlFZ1it4.mjs → actionPermissions-DPwPWPOV.mjs} +7 -6
  7. package/dist/audit/index.d.mts +2 -2
  8. package/dist/audit/index.mjs +10 -3
  9. package/dist/auth/audit.mjs +1 -1
  10. package/dist/auth/index.d.mts +2 -2
  11. package/dist/auth/index.mjs +12 -6
  12. package/dist/auth/redis-session.mjs +1 -1
  13. package/dist/{authorizationDecision-BP8GHtjc.mjs → authorizationDecision-2YY_Kaj1.mjs} +2 -2
  14. package/dist/{base-C-NL2fTi.d.mts → base-CxrV1LmG.d.mts} +10 -0
  15. package/dist/{buildHandler-DjXOqIvX.mjs → buildHandler-CUhjGHGZ.mjs} +4 -4
  16. package/dist/cache/index.d.mts +4 -2
  17. package/dist/cache/index.mjs +4 -4
  18. package/dist/{caching-a3ZEcJJs.mjs → caching-DsWDjIxx.mjs} +2 -2
  19. package/dist/cleanup/index.d.mts +2 -2
  20. package/dist/cleanup/index.mjs +21 -5
  21. package/dist/cli/commands/describe.d.mts +1 -1
  22. package/dist/cli/commands/describe.mjs +3 -3
  23. package/dist/cli/commands/docs.mjs +3 -3
  24. package/dist/cli/commands/doctor.mjs +1 -1
  25. package/dist/cli/commands/generate.mjs +2 -2
  26. package/dist/cli/commands/init.mjs +2 -2
  27. package/dist/cli/commands/introspect.mjs +2 -2
  28. package/dist/cli/index.mjs +3 -3
  29. package/dist/{constants-BONghE1Y.mjs → constants-BxLgNFF7.mjs} +1 -1
  30. package/dist/context/index.d.mts +34 -6
  31. package/dist/context/index.mjs +42 -24
  32. package/dist/core/index.d.mts +2 -2
  33. package/dist/core/index.mjs +7 -7
  34. package/dist/{core-8She7FgF.mjs → core-iNGqYerO.mjs} +3 -3
  35. package/dist/{createActionRouter-Bqi6Bhhx.mjs → createActionRouter-BBlbPs3k.mjs} +7 -7
  36. package/dist/{createAggregationRouter-BsYO7ktd.mjs → createAggregationRouter-Dv5SuK2x.mjs} +7 -7
  37. package/dist/createMcpServer-CbDWkZ1T.d.mts +48 -0
  38. package/dist/{defineAggregation-0KBvqEEC.mjs → defineAggregation-UyeurGkp.mjs} +1 -1
  39. package/dist/{defineResource-BMdyRelW.mjs → defineResource-DzGT-2LP.mjs} +20 -22
  40. package/dist/discovery/index.mjs +1 -1
  41. package/dist/docs/index.d.mts +1 -1
  42. package/dist/docs/index.mjs +3 -3
  43. package/dist/{elevation-C6woysGC.mjs → elevation-BF-vhGxY.mjs} +4 -4
  44. package/dist/encryption/index.mjs +3 -3
  45. package/dist/{errorHandler-DI5AN2b5.d.mts → errorHandler--4rSMMvq.d.mts} +7 -1
  46. package/dist/{errorHandler-BdmIWPba.mjs → errorHandler-CIMkCOWm.mjs} +3 -3
  47. package/dist/{errors-2ExmOgIJ.mjs → errors-C_YhELhe.mjs} +1 -1
  48. package/dist/{eventPlugin-DFvHa4Nf.d.mts → eventPlugin-B52abJ8W.d.mts} +1 -1
  49. package/dist/{eventPlugin-DJwpGMzx.mjs → eventPlugin-CmXaPWLv.mjs} +5 -5
  50. package/dist/events/index.d.mts +4 -4
  51. package/dist/events/index.mjs +5 -5
  52. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  53. package/dist/events/transports/redis-stream-entry.mjs +34 -24
  54. package/dist/events/transports/redis.d.mts +1 -1
  55. package/dist/events/transports/redis.mjs +11 -8
  56. package/dist/factory/index.d.mts +5 -5
  57. package/dist/factory/index.mjs +5 -5
  58. package/dist/{fastify-augmentation-jYA2oHyL.d.mts → fastify-augmentation-Cq2nHVaW.d.mts} +3 -3
  59. package/dist/{fields-Cha2QCKH.mjs → fields-BTyPLHK0.mjs} +1 -1
  60. package/dist/{generate-BUP4Oydg.mjs → generate-D_YmiCNf.mjs} +4 -3
  61. package/dist/{headers-DeXNifVj.mjs → headers-CNECDE6q.mjs} +2 -2
  62. package/dist/{health-Bh0N_FLk.mjs → health-CxQzbJmr.mjs} +10 -2
  63. package/dist/hooks/index.d.mts +1 -1
  64. package/dist/hooks/index.mjs +2 -2
  65. package/dist/idempotency/index.d.mts +1 -1
  66. package/dist/idempotency/index.mjs +4 -4
  67. package/dist/idempotency/redis.d.mts +1 -1
  68. package/dist/idempotency/redis.mjs +1 -1
  69. package/dist/{index-BtYoMip1.d.mts → index-BHdZD8zK.d.mts} +10 -2
  70. package/dist/{index-D2uIUSQk.d.mts → index-CFfLKMH4.d.mts} +2 -2
  71. package/dist/{index-eyg5WEcy.d.mts → index-CbJiYrfv.d.mts} +1 -1
  72. package/dist/{index-BRoDtjek.d.mts → index-D4u76eQW.d.mts} +3 -3
  73. package/dist/{index-B78WZom8.d.mts → index-DHbyPo5j.d.mts} +52 -12
  74. package/dist/index.d.mts +5 -5
  75. package/dist/index.mjs +11 -11
  76. package/dist/{init-Dg_Am2o_.mjs → init-Y2MlSN9n.mjs} +9 -9
  77. package/dist/integrations/event-gateway.d.mts +1 -1
  78. package/dist/integrations/event-gateway.mjs +2 -2
  79. package/dist/integrations/index.d.mts +2 -2
  80. package/dist/integrations/index.mjs +1 -1
  81. package/dist/integrations/jobs/index.d.mts +1 -1
  82. package/dist/integrations/jobs/index.mjs +2 -2
  83. package/dist/integrations/mcp/index.d.mts +4 -47
  84. package/dist/integrations/mcp/index.mjs +2 -2
  85. package/dist/integrations/mcp/testing.d.mts +22 -2
  86. package/dist/integrations/mcp/testing.mjs +55 -33
  87. package/dist/integrations/streamline.mjs +3 -3
  88. package/dist/integrations/webhooks.d.mts +2 -2
  89. package/dist/integrations/webhooks.mjs +3 -3
  90. package/dist/integrations/websocket-pushref-redis.d.mts +1 -1
  91. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  92. package/dist/integrations/websocket-redis.mjs +1 -1
  93. package/dist/integrations/websocket.mjs +24 -6
  94. package/dist/{interface-DYPVscCU.mjs → interface-BIpgzbZl.mjs} +1 -1
  95. package/dist/{jsonBody-DVui0uJl.mjs → jsonBody-Cq9KYl2Z.mjs} +2 -2
  96. package/dist/{keys-BSuxGS-B.mjs → keys-Cmv4cBRa.mjs} +1 -1
  97. package/dist/{loadResources-CNd1DWnK.mjs → loadResources-CblF7xt2.mjs} +2 -2
  98. package/dist/{loadResourcesFromEntry-DNj8cpiY.mjs → loadResourcesFromEntry-99fIMC3p.mjs} +2 -2
  99. package/dist/logger/index.mjs +1 -1
  100. package/dist/{mcpPlugin-KWsezMx7.mjs → mcpPlugin-xF3Gw-HW.mjs} +75 -31
  101. package/dist/{memory-BiPVaCPg.mjs → memory-CpDZ9NPw.mjs} +2 -2
  102. package/dist/{metrics-CsWaIVTa.mjs → metrics-BaKnq8ag.mjs} +2 -2
  103. package/dist/middleware/index.d.mts +1 -1
  104. package/dist/middleware/index.mjs +3 -3
  105. package/dist/migrations/index.mjs +2 -2
  106. package/dist/{module-BQXHxMEk.mjs → module-BkQEesNQ.mjs} +1 -1
  107. package/dist/{multipartBody-u6VrS_iH.mjs → multipartBody-C92aJ8am.mjs} +1 -1
  108. package/dist/{openapi-Dxc8RLy_.mjs → openapi-C3LFRzPq.mjs} +6 -6
  109. package/dist/outbox-admin/index.d.mts +2 -2
  110. package/dist/outbox-admin/index.mjs +4 -4
  111. package/dist/{outbox-module-CQXu_O6o.d.mts → outbox-module-BHdUnuuK.d.mts} +15 -2
  112. package/dist/{outbox-module-DyIqA5vo.mjs → outbox-module-dsCyLxXH.mjs} +43 -21
  113. package/dist/permissions/index.d.mts +2 -2
  114. package/dist/permissions/index.mjs +5 -5
  115. package/dist/{permissions-H7Zcb82Z.mjs → permissions-DiHXy8Ck.mjs} +12 -6
  116. package/dist/{pipe-SunhEaZ6.mjs → pipe-CBVmUJ-j.mjs} +2 -2
  117. package/dist/pipeline/index.d.mts +1 -1
  118. package/dist/pipeline/index.mjs +2 -2
  119. package/dist/plugins/index.d.mts +7 -37
  120. package/dist/plugins/index.mjs +34 -22
  121. package/dist/plugins/response-cache.mjs +9 -2
  122. package/dist/plugins/tracing-entry.mjs +2 -2
  123. package/dist/{pluralize-Da7IT_qJ.mjs → pluralize-2_U6QZQg.mjs} +1 -1
  124. package/dist/{preloadResources-DlhH81py.mjs → preloadResources-Bbp4QJ8V.mjs} +82 -26
  125. package/dist/{preloadResources-BbBkNkqK.d.mts → preloadResources-CjS2OfpU.d.mts} +14 -9
  126. package/dist/presets/filesUpload.d.mts +2 -2
  127. package/dist/presets/filesUpload.mjs +5 -5
  128. package/dist/presets/index.d.mts +2 -2
  129. package/dist/presets/index.mjs +2 -2
  130. package/dist/presets/multiTenant.d.mts +38 -1
  131. package/dist/presets/multiTenant.mjs +24 -6
  132. package/dist/presets/search.d.mts +2 -2
  133. package/dist/presets/search.mjs +2 -2
  134. package/dist/{presets-CNyfaxGL.mjs → presets-BdlugYTc.mjs} +4 -4
  135. package/dist/{projection-DSfEoooA.mjs → projection-Uvgp-EEj.mjs} +2 -2
  136. package/dist/{queryCachePlugin-oTsmVyEQ.mjs → queryCachePlugin-B5F09bYr.mjs} +11 -5
  137. package/dist/rateLimitKey-CK-EU2L8.mjs +41 -0
  138. package/dist/{realtime-CPmjjgqd.mjs → realtime-FnnD0n3Z.mjs} +9 -9
  139. package/dist/{redis-CduhKsJi.d.mts → redis-Bzi1y3F9.d.mts} +10 -2
  140. package/dist/{redis-stream-eh0eOtjh.d.mts → redis-stream-BPKscsTB.d.mts} +12 -7
  141. package/dist/{registerRoute-XvcI_3sh.mjs → registerRoute-DRsSHPSM.mjs} +6 -6
  142. package/dist/registry/index.d.mts +2 -2
  143. package/dist/registry/index.mjs +3 -3
  144. package/dist/{registry-UFEJQN8R.mjs → registry-D3y8VEJ1.mjs} +2 -2
  145. package/dist/{renewingLease-DuRGVOMe.mjs → renewingLease-B3VYh5aU.mjs} +1 -1
  146. package/dist/{replyHelpers-BHebarf0.mjs → replyHelpers-DPHsdw-5.mjs} +2 -2
  147. package/dist/{requestContext-DpmntRZy.mjs → requestContext-cSVKnYPk.mjs} +1 -1
  148. package/dist/{rolldown-runtime-Add2L50I.mjs → rolldown-runtime-DjDuyglE.mjs} +1 -1
  149. package/dist/{runtimeCapabilities-D793Pxci.mjs → runtimeCapabilities-DSA_dH1_.mjs} +31 -5
  150. package/dist/{schedules-DthM8Qag.mjs → schedules-BktJb3Y3.mjs} +8 -4
  151. package/dist/{schemaConverter-Db-MMsH6.mjs → schemaConverter-BLCSmNbr.mjs} +1 -1
  152. package/dist/{schemaIR-CIXShch7.mjs → schemaIR-K16Bb5BX.mjs} +2 -2
  153. package/dist/schemas/index.mjs +1 -1
  154. package/dist/scim/index.mjs +2 -2
  155. package/dist/scope/index.mjs +5 -5
  156. package/dist/{scope-D03sk17n.mjs → scope-jSxuBTFM.mjs} +4 -4
  157. package/dist/{simpleEqualityMatcher-B7qVjQBv.mjs → simpleEqualityMatcher-BiOnyflP.mjs} +1 -1
  158. package/dist/{sse-D4MYqkic.mjs → sse-CH7Slxc1.mjs} +5 -5
  159. package/dist/{sseStream-BuMNPR6r.mjs → sseStream-CN-Lh1Tu.mjs} +2 -2
  160. package/dist/{store-helpers-CIF4RG8s.mjs → store-helpers-9DX9-1j_.mjs} +1 -1
  161. package/dist/{streaming-DkpW1HwJ.mjs → streaming-dvppnxsr.mjs} +1 -1
  162. package/dist/{subscribe-helpers-CBZOi6pk.mjs → subscribe-helpers-AVYPgqTl.mjs} +2 -2
  163. package/dist/sync/changelog.mjs +1 -1
  164. package/dist/testing/cleanupStoreContract.mjs +1 -1
  165. package/dist/testing/index.d.mts +5 -5
  166. package/dist/testing/index.mjs +10 -10
  167. package/dist/testing/outboxStoreContract.mjs +14 -3
  168. package/dist/testing/storageContract.mjs +1 -1
  169. package/dist/{transactionContext-DMmvcfdo.mjs → transactionContext-DCWMI6hV.mjs} +1 -1
  170. package/dist/{typeGuards-DHTnEs5X.mjs → typeGuards-D7tHFdH6.mjs} +1 -1
  171. package/dist/types/index.d.mts +2 -2
  172. package/dist/types/index.mjs +1 -1
  173. package/dist/types/storage.mjs +1 -1
  174. package/dist/{types-BqLyyH0o.mjs → types-CDy3-zw1.mjs} +4 -4
  175. package/dist/{types-LQFwC37d.d.mts → types-CWQn9-IC.d.mts} +46 -1
  176. package/dist/{types-BRU-Kd3t.d.mts → types-DfVDvkdP.d.mts} +20 -2
  177. package/dist/usage/index.d.mts +58 -2
  178. package/dist/usage/index.mjs +0 -0
  179. package/dist/{userHelpers-CXySQFRg.mjs → userHelpers-DDMOZ_Pm.mjs} +1 -1
  180. package/dist/utils/index.d.mts +110 -8
  181. package/dist/utils/index.mjs +12 -12
  182. package/dist/{utils-BbGG8XNT.mjs → utils-B-zj_b__.mjs} +61 -12
  183. package/dist/{validate-CidSeUrx.mjs → validate-R0G_JrnK.mjs} +2 -2
  184. package/dist/{versioning-B843jOYX.d.mts → versioning-D6JIK8Tk.d.mts} +58 -2
  185. package/dist/{versioning-C2r0eOZ4.mjs → versioning-DuVWcu-F.mjs} +3 -3
  186. package/dist/workScope-BhsWde4k.mjs +41 -0
  187. package/package.json +574 -565
  188. package/skills/arc/SKILL.md +8 -4
  189. package/skills/arc/references/mcp.md +20 -0
  190. package/skills/arc/references/production.md +94 -9
  191. package/skills/arc/references/testing.md +0 -12
  192. package/skills/arc-code-review/references/anti-patterns.md +1 -1
  193. package/skills/arc-code-review/references/migration-recipes.md +0 -60
  194. package/skills/arc-code-review/references/mongokit-migration.md +0 -27
  195. package/skills/arc-module-publishing/references/package-manifest.md +3 -1
  196. package/dist/rateLimitKey-CewdR-m6.mjs +0 -15
@@ -1,5 +1,7 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { r as workSeedFromEvent, t as runWorkScope } from "../../workScope-BhsWde4k.mjs";
2
3
  import sjson from "secure-json-parse";
4
+ import { matchEventPattern } from "@classytic/primitives/events";
3
5
  //#region src/events/transports/redis-stream.ts
4
6
  /**
5
7
  * Redis Stream Event Transport — Durable Event Delivery
@@ -183,7 +185,7 @@ var RedisStreamTransport = class {
183
185
  this.generation++;
184
186
  this.handlers.clear();
185
187
  this.failureContext.clear();
186
- if (this.pollPromise) {
188
+ if (this.pollPromise !== null) {
187
189
  if (await Promise.race([this.pollPromise.then(() => "drained"), this.sleep(this.closeTimeoutMs).then(() => "timeout")]) === "timeout") {
188
190
  if (!this.externalLifecycle) {
189
191
  if (typeof this.redis.disconnect === "function") this.redis.disconnect();
@@ -232,14 +234,23 @@ var RedisStreamTransport = class {
232
234
  * still sequential inside `processEntry`.
233
235
  */
234
236
  async processEntries(entries) {
237
+ const live = [];
238
+ const ghostIds = [];
239
+ for (const [messageId, fields] of entries) if (fields) live.push([messageId, fields]);
240
+ else ghostIds.push(messageId);
241
+ if (ghostIds.length > 0) try {
242
+ await this.redis.xack(this.stream, this.group, ...ghostIds);
243
+ } catch (err) {
244
+ this.logger.error(`[RedisStreamTransport] Failed to ack ${ghostIds.length} trimmed entr(ies):`, err);
245
+ }
235
246
  if (this.processingConcurrency <= 1) {
236
- for (const [messageId, fields] of entries) await this.processEntry(messageId, fields);
247
+ for (const [messageId, fields] of live) await this.processEntry(messageId, fields);
237
248
  return;
238
249
  }
239
250
  let next = 0;
240
- const workers = Array.from({ length: Math.min(this.processingConcurrency, entries.length) }, async () => {
241
- while (next < entries.length) {
242
- const entry = entries[next++];
251
+ const workers = Array.from({ length: Math.min(this.processingConcurrency, live.length) }, async () => {
252
+ while (next < live.length) {
253
+ const entry = live[next++];
243
254
  if (entry) await this.processEntry(entry[0], entry[1]);
244
255
  }
245
256
  });
@@ -278,14 +289,16 @@ var RedisStreamTransport = class {
278
289
  let allSucceeded = true;
279
290
  let lastError;
280
291
  let lastHandlerName;
281
- for (const handler of matchingHandlers) try {
282
- await handler(event);
283
- } catch (err) {
284
- allSucceeded = false;
285
- lastError = err instanceof Error ? err : new Error(String(err));
286
- lastHandlerName = handler.name || lastHandlerName;
287
- this.logger.error(`[RedisStreamTransport] Handler error for ${event.type}:`, err);
288
- }
292
+ await runWorkScope(workSeedFromEvent(event), async () => {
293
+ for (const handler of matchingHandlers) try {
294
+ await handler(event);
295
+ } catch (err) {
296
+ allSucceeded = false;
297
+ lastError = err instanceof Error ? err : new Error(String(err));
298
+ lastHandlerName = handler.name || lastHandlerName;
299
+ this.logger.error(`[RedisStreamTransport] Handler error for ${event.type}:`, err);
300
+ }
301
+ });
289
302
  if (allSucceeded) {
290
303
  await this.redis.xack(this.stream, this.group, messageId);
291
304
  this.failureContext.delete(messageId);
@@ -306,20 +319,17 @@ var RedisStreamTransport = class {
306
319
  if (oldest !== void 0) this.failureContext.delete(oldest);
307
320
  }
308
321
  }
322
+ /**
323
+ * The canonical matcher from primitives — the SAME glob rules the memory
324
+ * transport speaks. A private matcher here once accepted `prefix.*` but not
325
+ * `prefix:*`, so an `order:*` subscription that worked in-process received
326
+ * nothing after a move to the stream, with no error.
327
+ */
309
328
  getMatchingHandlers(eventType) {
310
329
  const matched = [];
311
- for (const [pattern, handlers] of this.handlers) if (this.matchesPattern(pattern, eventType)) for (const h of handlers) matched.push(h);
330
+ for (const [pattern, handlers] of this.handlers) if (matchEventPattern(pattern, eventType)) for (const h of handlers) matched.push(h);
312
331
  return matched;
313
332
  }
314
- matchesPattern(pattern, eventType) {
315
- if (pattern === "*") return true;
316
- if (pattern === eventType) return true;
317
- if (pattern.endsWith(".*")) {
318
- const prefix = pattern.slice(0, -2);
319
- return eventType.startsWith(`${prefix}.`);
320
- }
321
- return false;
322
- }
323
333
  async moveToDlq(ids) {
324
334
  if (this.deadLetterStream === false) {
325
335
  for (const id of ids) {
@@ -1,5 +1,5 @@
1
1
 
2
- import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "../../EventTransport-Cx60_s-6.mjs";
2
+ import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "../../EventTransport-CbUKDzZZ.mjs";
3
3
  //#region src/events/transports/redis.d.ts
4
4
  interface RedisLike {
5
5
  publish(channel: string, message: string): Promise<number>;
@@ -1,4 +1,5 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { r as workSeedFromEvent, t as runWorkScope } from "../../workScope-BhsWde4k.mjs";
2
3
  import sjson from "secure-json-parse";
3
4
  //#region src/events/transports/redis.ts
4
5
  /**
@@ -107,14 +108,16 @@ var RedisEventTransport = class {
107
108
  } catch {
108
109
  return;
109
110
  }
110
- for (const handler of handlers) try {
111
- const result = handler(event);
112
- if (result && typeof result === "object" && "catch" in result) result.catch((err) => {
111
+ runWorkScope(workSeedFromEvent(event), () => {
112
+ for (const handler of handlers) try {
113
+ const result = handler(event);
114
+ if (result && typeof result === "object" && "catch" in result) result.catch((err) => {
115
+ this.logger.error(`[RedisEventTransport] Handler error for ${event.type}:`, err);
116
+ });
117
+ } catch (err) {
113
118
  this.logger.error(`[RedisEventTransport] Handler error for ${event.type}:`, err);
114
- });
115
- } catch (err) {
116
- this.logger.error(`[RedisEventTransport] Handler error for ${event.type}:`, err);
117
- }
119
+ }
120
+ });
118
121
  }
119
122
  /**
120
123
  * Convert an Arc event pattern to a Redis channel/pattern string.
@@ -1,8 +1,8 @@
1
1
 
2
- import { _ as HealthCheck, a as ModuleContribution, c as LoadResourcesOptions, d as loadResources, i as EventHandlerDefinition, l as ResourceLike, n as ArcModuleInput, o as ModuleDisposer, r as ArcModuleRegistry, s as ModuleSetupContext, t as ArcModule, u as ResourceModule } from "../types-BRU-Kd3t.mjs";
3
- import { _ as collectModuleScheduledJobs, a as lazyModuleExports, c as getModuleState, d as resolveModule, f as orderModules, g as collectModuleHealthChecks, h as extendModule, i as hasModuleExports, l as hasModule, m as ModuleExtension, n as getModuleExports, o as lazyRequiredModuleExports, p as subscribeModuleEventHandlers, r as getOptionalModuleExports, s as ModuleState, t as defineModule, u as resolveContribution, v as collectModuleWorkflows } from "../index-D2uIUSQk.mjs";
4
- import { c as ResolvedResourceDescriptor, l as describeResolvedModule, o as ResolvedModuleDescriptor, s as ResolvedModuleLifecycle } from "../fastify-augmentation-jYA2oHyL.mjs";
5
- import { a as RawBodyOptions, c as BetterAuthOption, d as JwtAuthOption, i as MultipartOptions, l as CustomAuthenticatorOption, n as preloadResourcesAsync, o as UnderPressureOptions, r as CreateAppOptions, s as AuthOption, t as preloadResources, u as CustomPluginAuthOption } from "../preloadResources-BbBkNkqK.mjs";
2
+ import { _ as HealthCheck, a as ModuleContribution, c as LoadResourcesOptions, d as loadResources, i as EventHandlerDefinition, l as ResourceLike, n as ArcModuleInput, o as ModuleDisposer, r as ArcModuleRegistry, s as ModuleSetupContext, t as ArcModule, u as ResourceModule } from "../types-DfVDvkdP.mjs";
3
+ import { _ as collectModuleScheduledJobs, a as lazyModuleExports, c as getModuleState, d as resolveModule, f as orderModules, g as collectModuleHealthChecks, h as extendModule, i as hasModuleExports, l as hasModule, m as ModuleExtension, n as getModuleExports, o as lazyRequiredModuleExports, p as subscribeModuleEventHandlers, r as getOptionalModuleExports, s as ModuleState, t as defineModule, u as resolveContribution, v as collectModuleWorkflows } from "../index-CFfLKMH4.mjs";
4
+ import { c as ResolvedResourceDescriptor, l as describeResolvedModule, o as ResolvedModuleDescriptor, s as ResolvedModuleLifecycle } from "../fastify-augmentation-Cq2nHVaW.mjs";
5
+ import { a as RawBodyOptions, c as BetterAuthOption, d as JwtAuthOption, i as MultipartOptions, l as CustomAuthenticatorOption, n as preloadResourcesAsync, o as UnderPressureOptions, r as CreateAppOptions, s as AuthOption, t as preloadResources, u as CustomPluginAuthOption } from "../preloadResources-CjS2OfpU.mjs";
6
6
  import { FastifyInstance, FastifyServerOptions } from "fastify";
7
7
  //#region src/factory/createApp.d.ts
8
8
  /**
@@ -19,7 +19,7 @@ import { FastifyInstance, FastifyServerOptions } from "fastify";
19
19
  * their own `redact` and arc steps aside — this default never overrides
20
20
  * an explicit setting.
21
21
  */
22
- declare const DEFAULT_LOGGER_REDACT_PATHS: readonly ["req.headers.authorization", 'req.headers["x-api-key"]', 'req.headers["x-internal-api-key"]', "req.headers.cookie", 'req.headers["set-cookie"]', 'res.headers["set-cookie"]', "*.password", "*.passwordHash", "*.token", "*.accessToken", "*.refreshToken", "*.secret", "*.apiKey"];
22
+ declare const DEFAULT_LOGGER_REDACT_PATHS: readonly ["req.headers.authorization", 'req.headers["x-api-key"]', 'req.headers["x-internal-api-key"]', 'req.headers["x-device-token"]', "req.headers.cookie", 'req.headers["set-cookie"]', 'res.headers["set-cookie"]', "*.password", "*.passwordHash", "*.token", "*.accessToken", "*.refreshToken", "*.secret", "*.apiKey"];
23
23
  /**
24
24
  * Create a production-ready Fastify application with Arc framework.
25
25
  *
@@ -1,8 +1,8 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
2
- import { r as mergeHealthChecks, t as healthPlugin } from "../health-Bh0N_FLk.mjs";
3
- import { S as resolveModule, _ as describeResolvedModule, a as createApp, b as collectModuleWorkflows, c as edgePreset, d as testingPreset, f as workerPreset, g as subscribeModuleEventHandlers, h as orderModules, i as DEFAULT_LOGGER_REDACT_PATHS, l as getPreset, m as hasModule, n as preloadResourcesAsync, p as getModuleState, r as ArcFactory, s as developmentPreset, t as preloadResources, u as productionPreset, v as collectModuleHealthChecks, x as resolveContribution, y as collectModuleScheduledJobs } from "../preloadResources-DlhH81py.mjs";
4
- import { a as lazyModuleExports, i as hasModuleExports, n as getModuleExports, o as lazyRequiredModuleExports, r as getOptionalModuleExports, t as defineModule } from "../module-BQXHxMEk.mjs";
5
- import { t as loadResources } from "../loadResources-CNd1DWnK.mjs";
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { r as mergeHealthChecks, t as healthPlugin } from "../health-CxQzbJmr.mjs";
3
+ import { S as resolveModule, _ as describeResolvedModule, a as createApp, b as collectModuleWorkflows, c as edgePreset, d as testingPreset, f as workerPreset, g as subscribeModuleEventHandlers, h as orderModules, i as DEFAULT_LOGGER_REDACT_PATHS, l as getPreset, m as hasModule, n as preloadResourcesAsync, p as getModuleState, r as ArcFactory, s as developmentPreset, t as preloadResources, u as productionPreset, v as collectModuleHealthChecks, x as resolveContribution, y as collectModuleScheduledJobs } from "../preloadResources-Bbp4QJ8V.mjs";
4
+ import { a as lazyModuleExports, i as hasModuleExports, n as getModuleExports, o as lazyRequiredModuleExports, r as getOptionalModuleExports, t as defineModule } from "../module-BkQEesNQ.mjs";
5
+ import { t as loadResources } from "../loadResources-CblF7xt2.mjs";
6
6
  //#region src/factory/module/extend.ts
7
7
  /** Concatenate two contributions, resolving factories only when arc asks. */
8
8
  function mergeContribution(own, extra) {
@@ -1,8 +1,8 @@
1
1
 
2
- import { on as HookSystem, z as ResourceRegistry } from "./index-B78WZom8.mjs";
2
+ import { on as HookSystem, z as ResourceRegistry } from "./index-DHbyPo5j.mjs";
3
3
  import { t as ExternalOpenApiPaths } from "./externalPaths-CmGOxOtD.mjs";
4
- import { _ as HealthCheck, f as ScheduleDefinition, r as ArcModuleRegistry, t as ArcModule } from "./types-BRU-Kd3t.mjs";
5
- import { s as ModuleState } from "./index-D2uIUSQk.mjs";
4
+ import { _ as HealthCheck, f as ScheduleDefinition, r as ArcModuleRegistry, t as ArcModule } from "./types-DfVDvkdP.mjs";
5
+ import { s as ModuleState } from "./index-CFfLKMH4.mjs";
6
6
  import { FastifyPluginAsync } from "fastify";
7
7
  //#region src/factory/module/descriptor.d.ts
8
8
  /**
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
2
  //#region src/permissions/fields.ts
3
3
  /**
4
4
  * Field-Level Permissions
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
2
- import { t as pluralize } from "./pluralize-Da7IT_qJ.mjs";
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { t as pluralize } from "./pluralize-2_U6QZQg.mjs";
3
3
  import { join } from "node:path";
4
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
5
  //#region src/cli/commands/generate/name-helpers.ts
@@ -470,7 +470,8 @@ export default ${camel}Resource;
470
470
  */
471
471
 
472
472
  import { defineTool } from '@classytic/arc/mcp';
473
- ${ts ? "import { z } from 'zod';\n" : "const { z } = require('zod');\n"}
473
+ import { z } from 'zod';
474
+
474
475
  // Example: domain-specific action tool
475
476
  // export const activate${name}Tool = defineTool('activate_${fileName}', {
476
477
  // description: 'Activate a ${name.toLowerCase()} by ID',
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
2
- import { u as ValidationError } from "./errors-2ExmOgIJ.mjs";
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { u as ValidationError } from "./errors-C_YhELhe.mjs";
3
3
  //#region src/utils/headers.ts
4
4
  /**
5
5
  * Canonical header typing + accessor.
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
2
  import { randomUUID } from "node:crypto";
3
3
  import fp from "fastify-plugin";
4
4
  //#region src/plugins/requestId.ts
@@ -252,7 +252,7 @@ const healthPlugin = async (fastify, opts = {}) => {
252
252
  properties: {
253
253
  status: {
254
254
  type: "string",
255
- enum: ["not_ready"]
255
+ enum: ["not_ready", "draining"]
256
256
  },
257
257
  timestamp: { type: "string" },
258
258
  checks: { type: "array" }
@@ -260,6 +260,14 @@ const healthPlugin = async (fastify, opts = {}) => {
260
260
  }
261
261
  }
262
262
  } }, async (_, reply) => {
263
+ if (fastify.hasDecorator("shutdownState") && fastify.shutdownState.draining) {
264
+ reply.code(503);
265
+ return {
266
+ status: "draining",
267
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
268
+ checks: []
269
+ };
270
+ }
263
271
  const results = await runChecks(readinessChecks);
264
272
  const criticalFailed = results.some((result, index) => !result.healthy && (readinessChecks[index]?.critical ?? true));
265
273
  const response = {
@@ -1,3 +1,3 @@
1
1
 
2
- import { an as HookRegistration, cn as afterCreate, dn as beforeCreate, en as DefineHookOptions, fn as beforeDelete, hn as defineHook, in as HookPhase, ln as afterDelete, mn as createHookSystem, nn as HookHandler, on as HookSystem, pn as beforeUpdate, rn as HookOperation, sn as HookSystemOptions, tn as HookContext, un as afterUpdate } from "../index-B78WZom8.mjs";
2
+ import { an as HookRegistration, cn as afterCreate, dn as beforeCreate, en as DefineHookOptions, fn as beforeDelete, hn as defineHook, in as HookPhase, ln as afterDelete, mn as createHookSystem, nn as HookHandler, on as HookSystem, pn as beforeUpdate, rn as HookOperation, sn as HookSystemOptions, tn as HookContext, un as afterUpdate } from "../index-DHbyPo5j.mjs";
3
3
  export { type DefineHookOptions, type HookContext, type HookHandler, type HookOperation, type HookPhase, type HookRegistration, HookSystem, type HookSystemOptions, afterCreate, afterDelete, afterUpdate, beforeCreate, beforeDelete, beforeUpdate, createHookSystem, defineHook };
@@ -1,3 +1,3 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
2
- import { a as beforeCreate, c as createHookSystem, i as afterUpdate, l as defineHook, n as afterCreate, o as beforeDelete, r as afterDelete, s as beforeUpdate, t as HookSystem } from "../HookSystem-C0ikzqQf.mjs";
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { a as beforeCreate, c as createHookSystem, i as afterUpdate, l as defineHook, n as afterCreate, o as beforeDelete, r as afterDelete, s as beforeUpdate, t as HookSystem } from "../HookSystem-CxvZBo77.mjs";
3
3
  export { HookSystem, afterCreate, afterDelete, afterUpdate, beforeCreate, beforeDelete, beforeUpdate, createHookSystem, defineHook };
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-DEWNOMza.mjs";
3
- import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-CduhKsJi.mjs";
3
+ import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-Bzi1y3F9.mjs";
4
4
  import { FastifyPluginAsync } from "fastify";
5
5
  import { RepositoryLike } from "@classytic/repo-core/adapter";
6
6
  //#region src/idempotency/idempotencyPlugin.d.ts
@@ -1,7 +1,7 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
2
- import { n as requireSingleHeaderValue } from "../headers-DeXNifVj.mjs";
3
- import { n as createSafeGetOne, t as createIsDuplicateKeyError } from "../store-helpers-CIF4RG8s.mjs";
4
- import { t as createIdempotencyResult } from "../interface-DYPVscCU.mjs";
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { n as requireSingleHeaderValue } from "../headers-CNECDE6q.mjs";
3
+ import { n as createSafeGetOne, t as createIsDuplicateKeyError } from "../store-helpers-9DX9-1j_.mjs";
4
+ import { t as createIdempotencyResult } from "../interface-BIpgzbZl.mjs";
5
5
  import { and, eq, exists, gt, lt, or, startsWith } from "@classytic/repo-core/filter";
6
6
  import { createHash } from "node:crypto";
7
7
  import fp from "fastify-plugin";
@@ -1,3 +1,3 @@
1
1
 
2
- import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-CduhKsJi.mjs";
2
+ import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-Bzi1y3F9.mjs";
3
3
  export { type IoredisLike, type RedisClient, RedisIdempotencyStore, type RedisIdempotencyStoreOptions, type UpstashRedisLike, ioredisAsIdempotencyClient, upstashAsIdempotencyClient };
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
2
  //#region src/idempotency/stores/redis.ts
3
3
  var RedisIdempotencyStore = class {
4
4
  name = "redis";
@@ -1,8 +1,8 @@
1
1
 
2
2
  import { i as RequestScope, n as Mandate } from "./types-Ddl9OjmE.mjs";
3
- import { l as PermissionCheck, s as AuthorizationDecision, u as PermissionContext } from "./base-C-NL2fTi.mjs";
3
+ import { l as PermissionCheck, s as AuthorizationDecision, u as PermissionContext } from "./base-CxrV1LmG.mjs";
4
4
  import { r as CacheStore, t as CacheLogger } from "./interface-BOk3YnTz.mjs";
5
- import { FastifyReply, FastifyRequest } from "fastify";
5
+ import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
6
6
  //#region src/permissions/agent.d.ts
7
7
  /**
8
8
  * Require a sender-constrained credential — the inbound token MUST carry a
@@ -441,6 +441,14 @@ interface DynamicPermissionMatrixConfig {
441
441
  /** Hard entry cap for internal memory store (default: 1000) */
442
442
  maxEntries?: number;
443
443
  };
444
+ /**
445
+ * App to declare the cache to (`declareRuntimeCapability`). This is a pure
446
+ * factory with no Fastify handle of its own, so without it the internal
447
+ * memory cache is invisible to the `runtime: 'distributed'` audit — a
448
+ * revocation on one replica then leaves the others honouring the old
449
+ * roles until TTL. Pass the instance whenever one exists at construction.
450
+ */
451
+ fastify?: FastifyInstance;
444
452
  }
445
453
  /** Minimal publish/subscribe interface for cross-node cache invalidation. */
446
454
  interface PermissionEventBus {
@@ -1,5 +1,5 @@
1
1
 
2
- import { _ as HealthCheck, a as ModuleContribution, f as ScheduleDefinition, n as ArcModuleInput, r as ArcModuleRegistry, s as ModuleSetupContext, t as ArcModule } from "./types-BRU-Kd3t.mjs";
2
+ import { _ as HealthCheck, a as ModuleContribution, f as ScheduleDefinition, n as ArcModuleInput, r as ArcModuleRegistry, s as ModuleSetupContext, t as ArcModule } from "./types-DfVDvkdP.mjs";
3
3
  import { FastifyInstance } from "fastify";
4
4
  //#region src/factory/module/contributions.d.ts
5
5
  /**
@@ -201,7 +201,7 @@ declare function getModuleExports<TExports = unknown>(fastify: FastifyInstance,
201
201
  * spelling that question as
202
202
  *
203
203
  * ```ts
204
- * (fastify as unknown as { arc?: { modules?: Record<string, unknown> } })
204
+ * (fastify as { arc?: { modules?: Record<string, unknown> } })
205
205
  * .arc?.modules?.inventory;
206
206
  * ```
207
207
  *
@@ -1,5 +1,5 @@
1
1
 
2
- import { l as PermissionCheck } from "./base-C-NL2fTi.mjs";
2
+ import { l as PermissionCheck } from "./base-CxrV1LmG.mjs";
3
3
  import { FastifyPluginAsync } from "fastify";
4
4
  //#region src/integrations/jobs/execution.d.ts
5
5
  /**
@@ -1,8 +1,8 @@
1
1
 
2
2
  import { i as RequestScope } from "./types-Ddl9OjmE.mjs";
3
- import { l as PermissionCheck, t as AnyRecord } from "./base-C-NL2fTi.mjs";
4
- import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, Fn as IControllerResponse, H as CrudController, In as IRequestContext, L as RequestWithExtras, Pn as IController, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig } from "./index-B78WZom8.mjs";
5
- import "./fastify-augmentation-jYA2oHyL.mjs";
3
+ import { l as PermissionCheck, t as AnyRecord } from "./base-CxrV1LmG.mjs";
4
+ import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, Fn as IControllerResponse, H as CrudController, In as IRequestContext, L as RequestWithExtras, Pn as IController, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig } from "./index-DHbyPo5j.mjs";
5
+ import "./fastify-augmentation-Cq2nHVaW.mjs";
6
6
  import { Filter } from "@classytic/repo-core/filter";
7
7
  import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
8
8
  import { z } from "zod";
@@ -1,11 +1,11 @@
1
1
 
2
2
  import { P as ArcHeaders, i as RequestScope } from "./types-Ddl9OjmE.mjs";
3
- import { d as UserBase, l as PermissionCheck, t as AnyRecord } from "./base-C-NL2fTi.mjs";
3
+ import { d as UserBase, l as PermissionCheck, t as AnyRecord } from "./base-CxrV1LmG.mjs";
4
4
  import { a as QueryCacheConfig } from "./QueryCache-DFA-QrU9.mjs";
5
5
  import "./elevation-BXCfVcNG.mjs";
6
6
  import { n as FieldPermissionMap } from "./fields-I_EeRWND.mjs";
7
7
  import { n as EncryptionDirective } from "./types-ByHn9rEO.mjs";
8
- import { n as DomainEvent } from "./EventTransport-Cx60_s-6.mjs";
8
+ import { n as DomainEvent } from "./EventTransport-CbUKDzZZ.mjs";
9
9
  import { Filter } from "@classytic/repo-core/filter";
10
10
  import { AggDateBucket, AggMeasure, AggTopN, QueryOptions, StandardRepo, TenantPurgeStrategy, TransactionHandle } from "@classytic/repo-core/repository";
11
11
  import { KeysetPaginationResult, OffsetPaginationResult } from "@classytic/repo-core/pagination";
@@ -516,6 +516,17 @@ type ArcControllerLike = {
516
516
  update: (...args: never[]) => unknown;
517
517
  delete: (...args: never[]) => unknown;
518
518
  };
519
+ /**
520
+ * Constructor constraint for the four preset mixins (`BulkMixin`, `SlugMixin`,
521
+ * `SoftDeleteMixin`, `TreeMixin`).
522
+ *
523
+ * This is the ONE place `any[]` is unavoidable: TypeScript requires a mixin's
524
+ * base-class constraint to be `new (...args: any[]) => T` — `unknown[]` and
525
+ * `never[]` are both rejected with "A mixin class must have a constructor with
526
+ * a single rest parameter of type 'any[]'". Each mixin used to carry its own
527
+ * copy of this line and its own lint waiver; one definition, one waiver.
528
+ */
529
+ type MixinConstructor<T> = new (...args: any[]) => T;
519
530
  /**
520
531
  * Return type of the controller's `list` method.
521
532
  *
@@ -1104,6 +1115,33 @@ declare class QueryResolver {
1104
1115
  * doesn't gate visibility — see `core/fieldRulePredicates.ts`.
1105
1116
  */
1106
1117
  private getBlockedFields;
1118
+ /**
1119
+ * Is this projection path blocked — by its own name, or by a hidden ANCESTOR?
1120
+ *
1121
+ * `hidden: { secret: true }` hides the object, and an exact-name match left its children
1122
+ * reachable: `?select=secret.value` projected the very field the rule exists to withhold.
1123
+ * A rule on a parent covers everything under it, which is what "hidden" already means to
1124
+ * whoever wrote it.
1125
+ */
1126
+ private isBlockedProjection;
1127
+ /**
1128
+ * Refuse a read that FILTERS or SORTS on a `hidden` field.
1129
+ *
1130
+ * `hidden` was enforced on the surfaces that RETURN a value — the response, `select=`,
1131
+ * `_distinct`, aggregations — but a filter key never returns the field, it INTERROGATES it:
1132
+ * `?passwordHash[like]=^ab` narrows the result set, so the row count answers a question about
1133
+ * a value the caller may not read. A resource with no `allowedFilterFields` was a blind
1134
+ * existence oracle over every hidden field it declared.
1135
+ *
1136
+ * Rejected rather than dropped, unlike `select`. Dropping a projection narrows what comes
1137
+ * back; dropping a filter WIDENS the rows, which is the silent-permissive shape this
1138
+ * framework fails loudly on everywhere else.
1139
+ *
1140
+ * Compound keys (`$or`, `$and`) are walked, because the offending key can be nested inside
1141
+ * one. A dotted path is blocked by its own name or by a hidden ancestor, so a rule on
1142
+ * `secret` also covers `secret.value`.
1143
+ */
1144
+ private assertNoBlockedReadKeys;
1107
1145
  }
1108
1146
  //#endregion
1109
1147
  //#region src/core/BaseCrudController.d.ts
@@ -1392,7 +1430,9 @@ declare class BaseCrudController<TDoc = AnyRecord, TRepository extends Repositor
1392
1430
  count: number;
1393
1431
  }>>;
1394
1432
  /** `?_distinct=field` → `repo.distinct(field, filter)` */
1395
- protected dispatchDistinct(req: IRequestContext, field: string): Promise<IControllerResponse<unknown[]>>;
1433
+ protected dispatchDistinct(req: IRequestContext, field: string): Promise<IControllerResponse<{
1434
+ values: unknown[];
1435
+ }>>;
1396
1436
  /** `?_exists=true` → `repo.exists(filter)` */
1397
1437
  protected dispatchExists(req: IRequestContext): Promise<IControllerResponse<{
1398
1438
  exists: boolean;
@@ -1425,7 +1465,6 @@ declare class BaseCrudController<TDoc = AnyRecord, TRepository extends Repositor
1425
1465
  }
1426
1466
  //#endregion
1427
1467
  //#region src/core/mixins/bulk.d.ts
1428
- type Constructor$3<T> = new (...args: any[]) => T;
1429
1468
  /** Public surface contributed by BulkMixin. */
1430
1469
  interface BulkExt {
1431
1470
  bulkCreate(req: IRequestContext): Promise<IControllerResponse<AnyRecord[]>>;
@@ -1437,33 +1476,30 @@ interface BulkExt {
1437
1476
  deletedCount: number;
1438
1477
  }>>;
1439
1478
  }
1440
- declare function BulkMixin<TBase extends Constructor$3<BaseCrudController>>(Base: TBase): TBase & Constructor$3<BulkExt>;
1479
+ declare function BulkMixin<TBase extends MixinConstructor<BaseCrudController>>(Base: TBase): TBase & MixinConstructor<BulkExt>;
1441
1480
  //#endregion
1442
1481
  //#region src/core/mixins/slug.d.ts
1443
- type Constructor$2<T> = new (...args: any[]) => T;
1444
1482
  /** Public surface contributed by SlugMixin. */
1445
1483
  interface SlugExt {
1446
1484
  getBySlug(req: IRequestContext): Promise<IControllerResponse<AnyRecord>>;
1447
1485
  }
1448
- declare function SlugMixin<TBase extends Constructor$2<BaseCrudController>>(Base: TBase): TBase & Constructor$2<SlugExt>;
1486
+ declare function SlugMixin<TBase extends MixinConstructor<BaseCrudController>>(Base: TBase): TBase & MixinConstructor<SlugExt>;
1449
1487
  //#endregion
1450
1488
  //#region src/core/mixins/tree.d.ts
1451
- type Constructor$1<T> = new (...args: any[]) => T;
1452
1489
  /** Public surface contributed by TreeMixin. */
1453
1490
  interface TreeExt {
1454
1491
  getTree(req: IRequestContext): Promise<IControllerResponse<AnyRecord[]>>;
1455
1492
  getChildren(req: IRequestContext): Promise<IControllerResponse<AnyRecord[]>>;
1456
1493
  }
1457
- declare function TreeMixin<TBase extends Constructor$1<BaseCrudController>>(Base: TBase): TBase & Constructor$1<TreeExt>;
1494
+ declare function TreeMixin<TBase extends MixinConstructor<BaseCrudController>>(Base: TBase): TBase & MixinConstructor<TreeExt>;
1458
1495
  //#endregion
1459
1496
  //#region src/core/mixins/softDelete.d.ts
1460
- type Constructor<T> = new (...args: any[]) => T;
1461
1497
  /** Public surface contributed by SoftDeleteMixin. */
1462
1498
  interface SoftDeleteExt {
1463
1499
  getDeleted(req: IRequestContext): Promise<IControllerResponse<PaginationResult<AnyRecord>>>;
1464
1500
  restore(req: IRequestContext): Promise<IControllerResponse<AnyRecord>>;
1465
1501
  }
1466
- declare function SoftDeleteMixin<TBase extends Constructor<BaseCrudController>>(Base: TBase): TBase & Constructor<SoftDeleteExt>;
1502
+ declare function SoftDeleteMixin<TBase extends MixinConstructor<BaseCrudController>>(Base: TBase): TBase & MixinConstructor<SoftDeleteExt>;
1467
1503
  //#endregion
1468
1504
  //#region src/core/BaseController.d.ts
1469
1505
  /**
@@ -1531,7 +1567,7 @@ interface BaseController<TDoc extends AnyRecord = AnyRecord, _TRepository extend
1531
1567
  deletedCount: number;
1532
1568
  }>>;
1533
1569
  }
1534
- declare const BaseController_base: (new (repository: any, options?: BaseControllerOptions) => BaseCrudController<AnyRecord, any>) & (new (...args: any[]) => BulkExt) & (new (...args: any[]) => SlugExt) & (new (...args: any[]) => TreeExt) & (new (...args: any[]) => SoftDeleteExt);
1570
+ declare const BaseController_base: (new (repository: any, options?: BaseControllerOptions) => BaseCrudController<AnyRecord, any>) & MixinConstructor<BulkExt> & MixinConstructor<SlugExt> & MixinConstructor<TreeExt> & MixinConstructor<SoftDeleteExt>;
1535
1571
  /**
1536
1572
  * Fully-composed controller: `BaseCrudController` + SoftDelete + Tree +
1537
1573
  * Slug + Bulk. Drop-in replacement for the pre-2.11 god class. The
@@ -4035,6 +4071,8 @@ interface GracefulShutdownOptions {
4035
4071
  onShutdown?: () => Promise<void> | void;
4036
4072
  signals?: NodeJS.Signals[];
4037
4073
  logEvents?: boolean;
4074
+ /** Lame-duck window (ms) between failing readiness and closing. Default 0. */
4075
+ drainDelayMs?: number;
4038
4076
  }
4039
4077
  interface RequestIdOptions {
4040
4078
  headerName?: string;
@@ -4133,6 +4171,8 @@ interface ArcInternalMetadata extends RequestContext {
4133
4171
  _policyFilters?: Record<string, unknown>;
4134
4172
  /** Request scope from scope resolution */
4135
4173
  _scope?: RequestScope;
4174
+ /** This read is deliberately unscoped by tenant — see `_crossTenantRead` on FastifyRequest. */
4175
+ _crossTenantRead?: boolean;
4136
4176
  /** Ownership check config from ownedByUser preset */
4137
4177
  _ownershipCheck?: {
4138
4178
  field: string;
package/dist/index.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
 
2
- import { c as DataPolicy, d as UserBase, l as PermissionCheck, n as ArcRequest, o as UserOrganization, r as JWTPayload, s as AuthorizationDecision, t as AnyRecord, u as PermissionContext } from "./base-C-NL2fTi.mjs";
3
- import { A as RequestIdOptions, An as WriteVerbKey, B as defineResource, Bt as BaseController, C as RequestContext, Cn as ControllerConstructionOptions, D as HealthCheck, Dn as MutationWriteContext, E as GracefulShutdownOptions, F as FastifyWithDecorators, Fn as IControllerResponse, Ft as AuthPluginOptions, Gt as SlugExt, H as CrudController, Ht as SoftDeleteMixin, In as IRequestContext, Jt as BulkMixin, Kt as SlugMixin, L as RequestWithExtras, Ln as RawRouteHandler, Mn as ControllerLike, N as FastifyRequestExtras, Nt as RateLimitConfig, O as HealthOptions, On as ResourceWrites, P as FastifyWithAuth, Pn as IController, Q as MiddlewareConfig, Rn as RouteHandler, S as QueryParserInterface, Sn as ControllerConfigurableOptions, T as CrudRouterOptions, U as ResourceConfig, Ut as TreeExt, V as ResourceDefinition, Vt as SoftDeleteExt, Wt as TreeMixin, X as CrudRouteKey, Y as PresetResult, Yt as BaseCrudController, Z as CrudSchemas, _n as ArcDeleteResult, a as InferAdapterDoc, bn as ArcUpdateResult, c as TypedController, ct as AggMeasureShorthand, d as PaginationResult, dt as AggregationDateRangeRequirement, et as RouteSchemaOptions, f as IntrospectionData, ft as AggregationIndexHint, g as ArcInternalMetadata, gn as ArcCreateResult, gt as AggregationsMap, h as ResourceMetadata, ht as AggregationRateLimit, i as ValidationResult, k as IntrospectionPluginOptions, kn as WriteContext, l as TypedRepository, lt as AggregationCacheConfig, m as RegistryStats, mt as AggregationMaterializedResult, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, pt as AggregationMaterializedContext, q as PresetFunction, qt as BulkExt, r as ValidateOptions, s as InferResourceDoc, st as AggMeasureInput, t as RouteHandlerMethod, u as TypedResourceConfig, ut as AggregationConfig, vn as ArcGetResult, w as ServiceContext, wn as ListResult, xn as BaseControllerOptions, y as OwnershipCheck, yn as ArcListResult } from "./index-B78WZom8.mjs";
2
+ import { c as DataPolicy, d as UserBase, l as PermissionCheck, n as ArcRequest, o as UserOrganization, r as JWTPayload, s as AuthorizationDecision, t as AnyRecord, u as PermissionContext } from "./base-CxrV1LmG.mjs";
3
+ import { A as RequestIdOptions, An as WriteVerbKey, B as defineResource, Bt as BaseController, C as RequestContext, Cn as ControllerConstructionOptions, D as HealthCheck, Dn as MutationWriteContext, E as GracefulShutdownOptions, F as FastifyWithDecorators, Fn as IControllerResponse, Ft as AuthPluginOptions, Gt as SlugExt, H as CrudController, Ht as SoftDeleteMixin, In as IRequestContext, Jt as BulkMixin, Kt as SlugMixin, L as RequestWithExtras, Ln as RawRouteHandler, Mn as ControllerLike, N as FastifyRequestExtras, Nt as RateLimitConfig, O as HealthOptions, On as ResourceWrites, P as FastifyWithAuth, Pn as IController, Q as MiddlewareConfig, Rn as RouteHandler, S as QueryParserInterface, Sn as ControllerConfigurableOptions, T as CrudRouterOptions, U as ResourceConfig, Ut as TreeExt, V as ResourceDefinition, Vt as SoftDeleteExt, Wt as TreeMixin, X as CrudRouteKey, Y as PresetResult, Yt as BaseCrudController, Z as CrudSchemas, _n as ArcDeleteResult, a as InferAdapterDoc, bn as ArcUpdateResult, c as TypedController, ct as AggMeasureShorthand, d as PaginationResult, dt as AggregationDateRangeRequirement, et as RouteSchemaOptions, f as IntrospectionData, ft as AggregationIndexHint, g as ArcInternalMetadata, gn as ArcCreateResult, gt as AggregationsMap, h as ResourceMetadata, ht as AggregationRateLimit, i as ValidationResult, k as IntrospectionPluginOptions, kn as WriteContext, l as TypedRepository, lt as AggregationCacheConfig, m as RegistryStats, mt as AggregationMaterializedResult, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, pt as AggregationMaterializedContext, q as PresetFunction, qt as BulkExt, r as ValidateOptions, s as InferResourceDoc, st as AggMeasureInput, t as RouteHandlerMethod, u as TypedResourceConfig, ut as AggregationConfig, vn as ArcGetResult, w as ServiceContext, wn as ListResult, xn as BaseControllerOptions, y as OwnershipCheck, yn as ArcListResult } from "./index-DHbyPo5j.mjs";
4
4
  import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-I_EeRWND.mjs";
5
- import "./fastify-augmentation-jYA2oHyL.mjs";
6
- import { A as CRUD_OPERATIONS, B as HookOperation, C as SeamedResourceConfig, E as defineAction, F as DEFAULT_SORT, G as MUTATION_OPERATIONS, H as MAX_FILTER_DEPTH, I as DEFAULT_TENANT_FIELD, J as SYSTEM_FIELDS, K as MutationOperation, L as DEFAULT_UPDATE_METHOD, M as DEFAULT_ID_FIELD, N as DEFAULT_LIMIT, P as DEFAULT_MAX_LIMIT, R as HOOK_OPERATIONS, S as ResourceSeams, U as MAX_REGEX_LENGTH, V as HookPhase, W as MAX_SEARCH_LENGTH, b as defineResourceVariants, c as nativePolicyFilter, h as getControllerScope, j as CrudOperation, k as defineAggregation, q as RESERVED_QUERY_PARAMS, s as NativePolicyFilter, w as mergeResourceConfig, x as AdapterLike, z as HOOK_PHASES } from "./index-BRoDtjek.mjs";
7
- import { $ as requireAuth, C as requireServiceScope, G as createOrgPermissions, H as DynamicPermissionMatrixConfig, J as allowPublic, K as allOf, S as requireScopeContext, V as DynamicPermissionMatrix, W as createDynamicPermissionMatrix, Y as anyOf, Z as denyAll, _ as publicReadAdminWrite, b as requireOrgMembership, d as authenticated, et as requireOwnership, f as fullPublic, g as publicRead, h as presets_d_exports, it as when, nt as requireRoles, p as ownerWithAdminBypass, u as adminOnly, v as readOnly, w as requireTeamMembership, x as requireOrgRole, y as requireOrgInScope } from "./index-BtYoMip1.mjs";
5
+ import "./fastify-augmentation-Cq2nHVaW.mjs";
6
+ import { A as CRUD_OPERATIONS, B as HookOperation, C as SeamedResourceConfig, E as defineAction, F as DEFAULT_SORT, G as MUTATION_OPERATIONS, H as MAX_FILTER_DEPTH, I as DEFAULT_TENANT_FIELD, J as SYSTEM_FIELDS, K as MutationOperation, L as DEFAULT_UPDATE_METHOD, M as DEFAULT_ID_FIELD, N as DEFAULT_LIMIT, P as DEFAULT_MAX_LIMIT, R as HOOK_OPERATIONS, S as ResourceSeams, U as MAX_REGEX_LENGTH, V as HookPhase, W as MAX_SEARCH_LENGTH, b as defineResourceVariants, c as nativePolicyFilter, h as getControllerScope, j as CrudOperation, k as defineAggregation, q as RESERVED_QUERY_PARAMS, s as NativePolicyFilter, w as mergeResourceConfig, x as AdapterLike, z as HOOK_PHASES } from "./index-D4u76eQW.mjs";
7
+ import { $ as requireAuth, C as requireServiceScope, G as createOrgPermissions, H as DynamicPermissionMatrixConfig, J as allowPublic, K as allOf, S as requireScopeContext, V as DynamicPermissionMatrix, W as createDynamicPermissionMatrix, Y as anyOf, Z as denyAll, _ as publicReadAdminWrite, b as requireOrgMembership, d as authenticated, et as requireOwnership, f as fullPublic, g as publicRead, h as presets_d_exports, it as when, nt as requireRoles, p as ownerWithAdminBypass, u as adminOnly, v as readOnly, w as requireTeamMembership, x as requireOrgRole, y as requireOrgInScope } from "./index-BHdZD8zK.mjs";
8
8
  import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-BGdVwP25.mjs";
9
9
  //#region src/index.d.ts
10
10
  declare const version: string;
package/dist/index.mjs CHANGED
@@ -1,14 +1,14 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
2
- import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "./constants-BONghE1Y.mjs";
3
- import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-2ExmOgIJ.mjs";
4
- import { a as BulkMixin, h as nativePolicyFilter, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-CYaDvmOB.mjs";
5
- import { t as defineAggregation } from "./defineAggregation-0KBvqEEC.mjs";
6
- import { i as fields, n as applyFieldWritePermissions, t as applyFieldReadPermissions } from "./fields-Cha2QCKH.mjs";
7
- import { l as getControllerScope } from "./actionPermissions-jlFZ1it4.mjs";
8
- import { a as ResourceDefinition, t as defineResource } from "./defineResource-BMdyRelW.mjs";
9
- import { a as mergeResourceConfig, i as defineResourceVariants, o as defineAction } from "./core-8She7FgF.mjs";
10
- import { B as requireAuth, C as createOrgPermissions, D as requireScopeContext, E as requireOrgRole, F as allowPublic, G as when, I as anyOf, N as allOf, O as requireServiceScope, R as denyAll, S as createDynamicPermissionMatrix, T as requireOrgMembership, U as requireRoles, V as requireOwnership, a as adminOnly, c as ownerWithAdminBypass, d as publicRead, f as publicReadAdminWrite, k as requireTeamMembership, o as authenticated, p as readOnly, s as fullPublic, u as presets_exports, w as requireOrgInScope } from "./permissions-H7Zcb82Z.mjs";
1
+ /*! @classytic/arc v2.41.0 | MIT | https://classytic.com */
2
+ import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "./constants-BxLgNFF7.mjs";
3
+ import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-C_YhELhe.mjs";
4
+ import { a as BulkMixin, h as nativePolicyFilter, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-DYJRZ0EJ.mjs";
5
+ import { t as defineAggregation } from "./defineAggregation-UyeurGkp.mjs";
6
+ import { i as fields, n as applyFieldWritePermissions, t as applyFieldReadPermissions } from "./fields-BTyPLHK0.mjs";
7
+ import { l as getControllerScope } from "./actionPermissions-DPwPWPOV.mjs";
8
+ import { a as ResourceDefinition, t as defineResource } from "./defineResource-DzGT-2LP.mjs";
9
+ import { a as mergeResourceConfig, i as defineResourceVariants, o as defineAction } from "./core-iNGqYerO.mjs";
10
+ import { B as requireAuth, C as createOrgPermissions, D as requireScopeContext, E as requireOrgRole, F as allowPublic, G as when, I as anyOf, N as allOf, O as requireServiceScope, R as denyAll, S as createDynamicPermissionMatrix, T as requireOrgMembership, U as requireRoles, V as requireOwnership, a as adminOnly, c as ownerWithAdminBypass, d as publicRead, f as publicReadAdminWrite, k as requireTeamMembership, o as authenticated, p as readOnly, s as fullPublic, u as presets_exports, w as requireOrgInScope } from "./permissions-DiHXy8Ck.mjs";
11
11
  //#region src/index.ts
12
- const version = "2.38.0";
12
+ const version = "2.41.0";
13
13
  //#endregion
14
14
  export { ArcError, BaseController, BaseCrudController, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, ForbiddenError, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, NotFoundError, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, mergeResourceConfig, nativePolicyFilter, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };