@classytic/arc 2.32.0 → 2.33.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 (192) hide show
  1. package/README.md +1 -1
  2. package/bin/arc.js +58 -17
  3. package/dist/{BaseController-Dk34dxhI.mjs → BaseController-CaQC5EXX.mjs} +293 -33
  4. package/dist/{EventTransport-2uVV34WU.d.mts → EventTransport-BEVP50ka.d.mts} +16 -0
  5. package/dist/{EventTransport-BV10D0oG.mjs → EventTransport-tq4CEB-q.mjs} +39 -2
  6. package/dist/{HookSystem-vimw5D7Z.mjs → HookSystem-DqXkMXkB.mjs} +2 -2
  7. package/dist/{ResourceRegistry-BVr7PgA0.mjs → ResourceRegistry-DoALUlOO.mjs} +3 -2
  8. package/dist/{actionPermissions-Dti7ebyv.mjs → actionPermissions-CUeCmpUd.mjs} +1 -1
  9. package/dist/audit/index.d.mts +2 -2
  10. package/dist/audit/index.mjs +2 -2
  11. package/dist/auth/audit.mjs +1 -1
  12. package/dist/auth/index.d.mts +2 -2
  13. package/dist/auth/index.mjs +39 -7
  14. package/dist/auth/redis-session.mjs +1 -1
  15. package/dist/{authorizationDecision-__T3EJDA.mjs → authorizationDecision-B3mP_QTy.mjs} +2 -2
  16. package/dist/{types-B7XeLEgK.d.mts → base-Csjc2oF-.d.mts} +74 -74
  17. package/dist/{buildHandler-Dn7rzUJo.mjs → buildHandler-DLE9xX-V.mjs} +4 -4
  18. package/dist/cache/index.mjs +4 -4
  19. package/dist/{caching-DFJqHyFs.mjs → caching-BcGmvnHh.mjs} +2 -2
  20. package/dist/cleanup/index.d.mts +17 -5
  21. package/dist/cleanup/index.mjs +240 -7
  22. package/dist/cli/commands/describe.d.mts +1 -1
  23. package/dist/cli/commands/describe.mjs +3 -3
  24. package/dist/cli/commands/docs.mjs +3 -3
  25. package/dist/cli/commands/doctor.mjs +1 -1
  26. package/dist/cli/commands/generate.mjs +2 -2
  27. package/dist/cli/commands/init.mjs +2 -2
  28. package/dist/cli/commands/introspect.mjs +2 -2
  29. package/dist/cli/index.mjs +3 -3
  30. package/dist/{constants-J99LGTJI.mjs → constants-BxCoxmiN.mjs} +1 -1
  31. package/dist/context/index.mjs +3 -3
  32. package/dist/core/index.d.mts +2 -2
  33. package/dist/core/index.mjs +7 -7
  34. package/dist/{core-BwwmNSp7.mjs → core-dxhcHhUD.mjs} +3 -3
  35. package/dist/{createActionRouter-DkJZWo0m.mjs → createActionRouter-DVpoA0do.mjs} +8 -8
  36. package/dist/{createAggregationRouter-B1exOVD8.mjs → createAggregationRouter-B_B48JZ-.mjs} +7 -7
  37. package/dist/{createApp-Bv0m-Q6_.mjs → createApp-CLGegqiG.mjs} +128 -24
  38. package/dist/{defineAggregation-gX4No1gt.mjs → defineAggregation-Nv-DwfOf.mjs} +1 -1
  39. package/dist/{defineResource-XFPPUu2c.mjs → defineResource-DR9vsUYy.mjs} +297 -23
  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-DNXXxgjl.mjs → elevation-B0tlY8y1.mjs} +4 -4
  44. package/dist/encryption/index.mjs +3 -3
  45. package/dist/{errorHandler-B2AZUJUj.mjs → errorHandler-C7xBqHsI.mjs} +42 -5
  46. package/dist/{errorHandler-CpYUJmPA.d.mts → errorHandler-DI5AN2b5.d.mts} +14 -3
  47. package/dist/{errors-Bh1KK5ps.mjs → errors-Cd_yy7aW.mjs} +1 -1
  48. package/dist/{eventPlugin-GF5nnBIq.d.mts → eventPlugin-DSNEZWfV.d.mts} +29 -1
  49. package/dist/{eventPlugin-Dk_TyXeE.mjs → eventPlugin-Dar8qRaj.mjs} +65 -9
  50. package/dist/events/index.d.mts +5 -351
  51. package/dist/events/index.mjs +5 -780
  52. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  53. package/dist/events/transports/redis-stream-entry.mjs +1 -1
  54. package/dist/events/transports/redis.d.mts +1 -1
  55. package/dist/events/transports/redis.mjs +1 -1
  56. package/dist/factory/index.d.mts +20 -5
  57. package/dist/factory/index.mjs +7 -7
  58. package/dist/{fastify-augmentation-BppG5bMT.d.mts → fastify-augmentation-DVsTAy6X.d.mts} +3 -3
  59. package/dist/{fields-DEi65pGj.mjs → fields-CojeUkS4.mjs} +1 -1
  60. package/dist/{generate-CRSG0jTv.mjs → generate-DiB0nHPR.mjs} +2 -2
  61. package/dist/{headers-BXjQYbeC.mjs → headers-CveNO9gR.mjs} +2 -2
  62. package/dist/{health-5XnTa2uo.mjs → health-CasG2A28.mjs} +1 -1
  63. package/dist/hooks/index.d.mts +1 -1
  64. package/dist/hooks/index.mjs +2 -2
  65. package/dist/idempotency/index.d.mts +45 -1
  66. package/dist/idempotency/index.mjs +91 -9
  67. package/dist/idempotency/redis.mjs +1 -1
  68. package/dist/{index-zq6VrjaB.d.mts → index-B-DvUzsr.d.mts} +12 -2
  69. package/dist/{index-CpzxqePp.d.mts → index-BcR2bFZQ.d.mts} +707 -373
  70. package/dist/{index-DXlHwvuE.d.mts → index-Brin0ODU.d.mts} +4 -4
  71. package/dist/{index-ZWhLTp_s.d.mts → index-C5NnMEKF.d.mts} +1 -1
  72. package/dist/{index-C-481Zf2.d.mts → index-ugr1tQlW.d.mts} +17 -1
  73. package/dist/index.d.mts +6 -6
  74. package/dist/index.mjs +11 -11
  75. package/dist/{init-BbfP8aky.mjs → init-mdJ-v4Xp.mjs} +18 -12
  76. package/dist/integrations/event-gateway.d.mts +1 -1
  77. package/dist/integrations/event-gateway.mjs +2 -2
  78. package/dist/integrations/index.d.mts +2 -2
  79. package/dist/integrations/index.mjs +1 -1
  80. package/dist/integrations/jobs/index.d.mts +1 -1
  81. package/dist/integrations/jobs/index.mjs +99 -97
  82. package/dist/integrations/mcp/index.d.mts +12 -3
  83. package/dist/integrations/mcp/index.mjs +2 -2
  84. package/dist/integrations/mcp/testing.d.mts +1 -1
  85. package/dist/integrations/mcp/testing.mjs +2 -2
  86. package/dist/integrations/streamline.mjs +3 -3
  87. package/dist/integrations/webhooks.d.mts +124 -1
  88. package/dist/integrations/webhooks.mjs +180 -2
  89. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  90. package/dist/integrations/websocket-redis.mjs +1 -1
  91. package/dist/integrations/websocket.mjs +1 -1
  92. package/dist/{interface-BP4IJCBO.mjs → interface-DznJrm9R.mjs} +1 -1
  93. package/dist/{jsonBody-DDSR2HFl.mjs → jsonBody-CfGH-GxO.mjs} +2 -2
  94. package/dist/{keys-B-HBTGXl.mjs → keys-WeKvY1dE.mjs} +1 -1
  95. package/dist/{loadResources-DisEAmkm.mjs → loadResources-Bj-aSsXi.mjs} +2 -2
  96. package/dist/{loadResourcesFromEntry-D1MJp13f.mjs → loadResourcesFromEntry-DwaxNcE2.mjs} +2 -2
  97. package/dist/logger/index.mjs +1 -1
  98. package/dist/{mcpPlugin-CpfVpKHE.mjs → mcpPlugin-aJg5TqHi.mjs} +60 -21
  99. package/dist/{memory-DsuWnj4T.mjs → memory-qYSB7rMQ.mjs} +2 -2
  100. package/dist/{metrics-DdQL8syd.mjs → metrics-D7uchLjN.mjs} +2 -2
  101. package/dist/middleware/index.d.mts +1 -1
  102. package/dist/middleware/index.mjs +3 -3
  103. package/dist/migrations/index.mjs +2 -2
  104. package/dist/{module-Br81am6m.mjs → module-CwKsgZXp.mjs} +1 -1
  105. package/dist/{multipartBody-BnkBLN7v.mjs → multipartBody-4w-S3-PU.mjs} +1 -1
  106. package/dist/{openapi-DIRzvxC0.mjs → openapi-BN5cQaO2.mjs} +6 -6
  107. package/dist/outbox-admin/index.d.mts +2 -2
  108. package/dist/outbox-admin/index.mjs +4 -4
  109. package/dist/outbox-module-CXB79bvt.mjs +839 -0
  110. package/dist/outbox-module-D-VFq37T.d.mts +368 -0
  111. package/dist/permissions/index.d.mts +2 -2
  112. package/dist/permissions/index.mjs +5 -5
  113. package/dist/{permissions-Dl_m0NCe.mjs → permissions-BAfwgBxc.mjs} +25 -6
  114. package/dist/{pipe-ELHCP3zj.mjs → pipe-BzzoEhHj.mjs} +2 -2
  115. package/dist/pipeline/index.d.mts +1 -1
  116. package/dist/pipeline/index.mjs +2 -2
  117. package/dist/{pipeline-CPA-jx0M.mjs → pipeline-q69DZzgG.mjs} +6 -6
  118. package/dist/plugins/index.d.mts +6 -6
  119. package/dist/plugins/index.mjs +16 -16
  120. package/dist/plugins/response-cache.mjs +2 -2
  121. package/dist/plugins/tracing-entry.mjs +2 -2
  122. package/dist/{pluralize-C2ZkKbsn.mjs → pluralize-B7xf8qZF.mjs} +1 -1
  123. package/dist/{preloadResources-CDs87fTw.mjs → preloadResources-BkyqeTDz.mjs} +1 -1
  124. package/dist/{preloadResources-T1hmlTEZ.d.mts → preloadResources-g07ldtzh.d.mts} +30 -7
  125. package/dist/presets/filesUpload.d.mts +2 -2
  126. package/dist/presets/filesUpload.mjs +5 -5
  127. package/dist/presets/index.d.mts +2 -2
  128. package/dist/presets/index.mjs +2 -2
  129. package/dist/presets/multiTenant.d.mts +1 -1
  130. package/dist/presets/multiTenant.mjs +3 -3
  131. package/dist/presets/search.d.mts +2 -2
  132. package/dist/presets/search.mjs +2 -2
  133. package/dist/{presets-Dntd_pUO.mjs → presets-D-h0uWtP.mjs} +4 -4
  134. package/dist/projection-BKM0Ui-s.mjs +42 -0
  135. package/dist/{queryCachePlugin-Dhps-Ldt.mjs → queryCachePlugin-DhsZ0ZIc.mjs} +49 -7
  136. package/dist/{rateLimit-C7mmAGs3.mjs → rateLimit-D4-ASwsI.mjs} +2 -2
  137. package/dist/{rateLimitKey-CccEFBfk.mjs → rateLimitKey-XngqVNEV.mjs} +1 -1
  138. package/dist/{realtime-DVvVZZFz.mjs → realtime-CTkv3O59.mjs} +9 -9
  139. package/dist/{redis-stream-qN6A-RFv.d.mts → redis-stream-mwLWlfHG.d.mts} +1 -1
  140. package/dist/{registerRoute-B_QrjYZS.mjs → registerRoute-DNnd3vkz.mjs} +4 -4
  141. package/dist/registry/index.d.mts +3 -3
  142. package/dist/registry/index.mjs +3 -3
  143. package/dist/{registry-DqUmzA9W.mjs → registry-CLxCR5LF.mjs} +2 -2
  144. package/dist/{renewingLease-BpP9wwj7.mjs → renewingLease-BnWtbA2U.mjs} +1 -1
  145. package/dist/{replyHelpers-DS-P0b32.mjs → replyHelpers-BSBVCwL3.mjs} +2 -2
  146. package/dist/{repositoryFilter-DotlxG3L.mjs → repositoryFilter-DKny7PDn.mjs} +1 -1
  147. package/dist/{requestContext-B6vQF-sy.mjs → requestContext-uYE35JxI.mjs} +1 -1
  148. package/dist/{rolldown-runtime-BhflRrBs.mjs → rolldown-runtime-DNg-KNCk.mjs} +1 -1
  149. package/dist/runtimeCapabilities-Dm88DaTW.mjs +49 -0
  150. package/dist/{schedules-C2Q3uv2d.mjs → schedules-CAcZgia0.mjs} +3 -3
  151. package/dist/{schemaConverter-Crjvczi_.mjs → schemaConverter-XH1RZRyu.mjs} +1 -1
  152. package/dist/{schemaIR-CnyKK_1j.mjs → schemaIR-CDvclAew.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-afz_Ieek.mjs → scope-BaWcqBvr.mjs} +4 -4
  157. package/dist/{simpleEqualityMatcher-C4KiMWUa.mjs → simpleEqualityMatcher-Se8VrsaP.mjs} +1 -1
  158. package/dist/{sse-B9P4Y-UI.mjs → sse-Cf0jUHsh.mjs} +5 -5
  159. package/dist/{sseStream-B3zb_d1h.mjs → sseStream-Bvpi-UXQ.mjs} +2 -2
  160. package/dist/{store-helpers-DmEMHlPQ.mjs → store-helpers-B88p99Z2.mjs} +1 -1
  161. package/dist/{streaming-DPZdQmDz.mjs → streaming-DsT1B5zJ.mjs} +1 -1
  162. package/dist/{subscribe-helpers-sp5xTDVA.mjs → subscribe-helpers-CLIOHsOK.mjs} +2 -2
  163. package/dist/sync/changelog.mjs +1 -1
  164. package/dist/testing/cleanupStoreContract.d.mts +1 -1
  165. package/dist/testing/cleanupStoreContract.mjs +3 -1
  166. package/dist/testing/index.d.mts +24 -12
  167. package/dist/testing/index.mjs +24 -12
  168. package/dist/testing/outboxStoreContract.mjs +1 -1
  169. package/dist/testing/storageContract.mjs +1 -1
  170. package/dist/{transactionContext-BvLKvOIL.mjs → transactionContext-BYtWnwAS.mjs} +1 -1
  171. package/dist/{typeGuards-B_5-hKjJ.mjs → typeGuards-jjKJDN13.mjs} +1 -1
  172. package/dist/types/index.d.mts +3 -3
  173. package/dist/types/index.mjs +1 -1
  174. package/dist/types/storage.mjs +1 -1
  175. package/dist/{types-CT5vu6M0.d.mts → types-BcTumAz_.d.mts} +41 -7
  176. package/dist/{types-CwcUQ610.d.mts → types-BfC83KsP.d.mts} +15 -1
  177. package/dist/{types-DXYX7dIR.mjs → types-CoqIRrkY.mjs} +4 -4
  178. package/dist/{types-C4QE8qnm.d.mts → types-DVLddu2q.d.mts} +144 -1
  179. package/dist/usage/index.d.mts +1 -1
  180. package/dist/usage/index.mjs +0 -0
  181. package/dist/{userHelpers-BNsOXzOd.mjs → userHelpers-CWF5pbZD.mjs} +1 -1
  182. package/dist/utils/index.d.mts +57 -5
  183. package/dist/utils/index.mjs +12 -11
  184. package/dist/{utils-BtOha_Sp.mjs → utils-h1V_sT-t.mjs} +38 -7
  185. package/dist/{validate-PMCPR9El.mjs → validate-CdQlz52F.mjs} +2 -2
  186. package/dist/{versioning-D_rhHfZm.d.mts → versioning-DEs-_hFi.d.mts} +1 -1
  187. package/dist/{versioning-CKv2jz_U.mjs → versioning-rZbyLVD-.mjs} +3 -3
  188. package/package.json +17 -16
  189. package/skills/arc/SKILL.md +96 -4
  190. package/skills/arc/references/api-reference.md +19 -0
  191. package/skills/arc/references/production.md +2 -2
  192. package/dist/projection-CjHhM5W1.mjs +0 -18
@@ -0,0 +1,368 @@
1
+
2
+ import { a as EventTransport, n as DomainEvent, t as DeadLetteredEvent } from "./EventTransport-BEVP50ka.mjs";
3
+ import { t as ArcModule } from "./types-BcTumAz_.mjs";
4
+ import { FastifyInstance } from "fastify";
5
+ import { MemoryOutboxStore } from "@classytic/primitives/memory-outbox";
6
+ import { OutboxFailurePolicy, OutboxStore, OutboxWriteOptions } from "@classytic/primitives/outbox";
7
+ import { RepositoryLike } from "@classytic/repo-core/adapter";
8
+ //#region src/events/outbox/relay.d.ts
9
+ /** Reason codes passed to {@link EventOutboxOptions.onError}. */
10
+ type OutboxRelayErrorKind = "publish_failed" | "acknowledge_failed" | "fail_failed" | "ownership_mismatch" | "malformed_event";
11
+ /**
12
+ * Rich per-batch outcome returned by {@link EventOutbox.relayBatch}.
13
+ *
14
+ * Useful for operational dashboards, alerting thresholds, and test assertions.
15
+ * The simpler {@link EventOutbox.relay} returns just the `relayed` count for
16
+ * backward compatibility.
17
+ */
18
+ interface RelayResult {
19
+ /** Number of events successfully published AND acknowledged */
20
+ readonly relayed: number;
21
+ /** Number of events claimed and attempted in this batch */
22
+ readonly attempted: number;
23
+ /** Number of publish failures (transport rejected the event) */
24
+ readonly publishFailed: number;
25
+ /** Number of acknowledge failures after successful publish (at-least-once replay risk) */
26
+ readonly ackFailed: number;
27
+ /** Number of ownership mismatches (our lease expired mid-flight) */
28
+ readonly ownershipMismatches: number;
29
+ /** Number of malformed events encountered (aborts the batch) */
30
+ readonly malformed: number;
31
+ /** Number of fail() calls that themselves threw (store bugs / contention) */
32
+ readonly failHookErrors: number;
33
+ /**
34
+ * Number of events moved to dead-letter state this batch via the configured
35
+ * {@link OutboxFailurePolicy}. Zero when no policy is set or no failure
36
+ * tripped the `deadLetter` branch.
37
+ */
38
+ readonly deadLettered: number;
39
+ /** Whether `publishMany` was used (true) or per-event `publish` (false) */
40
+ readonly usedPublishMany: boolean;
41
+ /**
42
+ * Wall-clock ms spent claiming this batch from the store. With the
43
+ * portable repository adapter this is ~2 DB round trips; a persistently
44
+ * high value under low batch sizes points at store latency, not volume.
45
+ */
46
+ readonly claimMs?: number;
47
+ /** Wall-clock ms spent publishing + acknowledging the batch. */
48
+ readonly publishMs?: number;
49
+ }
50
+ /**
51
+ * Called by {@link EventOutbox.relay} when a non-fatal error occurs during
52
+ * a batch. Used for logging and metrics. Must not throw.
53
+ */
54
+ type OutboxRelayErrorHandler = (info: {
55
+ readonly kind: OutboxRelayErrorKind;
56
+ readonly event?: DomainEvent;
57
+ readonly error: Error;
58
+ }) => void;
59
+ interface EventOutboxOptions {
60
+ /**
61
+ * Repository managing the outbox collection. Arc consumes it directly —
62
+ * no wrapper classes. Requires `create`, `getOne`, `findAll`,
63
+ * `deleteMany`, and `findOneAndUpdate` from `RepositoryLike` (mongokit
64
+ * ≥3.8 satisfies all of these). Takes precedence over `store` when both
65
+ * are passed.
66
+ *
67
+ * Use this for the common path where the outbox lives in your primary
68
+ * database. Use `store` for non-repository backends (memory / custom).
69
+ */
70
+ readonly repository?: RepositoryLike;
71
+ /**
72
+ * Non-repository outbox store. Use when your backend isn't a repository
73
+ * (memory for tests, Kafka, DynamoDB, custom). Ignored if `repository`
74
+ * is also passed.
75
+ */
76
+ readonly store?: OutboxStore;
77
+ /** Transport to relay events to (optional — can relay later) */
78
+ readonly transport?: EventTransport;
79
+ /** Max events per relay batch (default: 100) */
80
+ readonly batchSize?: number;
81
+ /**
82
+ * Unique identifier for this relay worker. Used when the store supports
83
+ * `claimPending`/`fail` to enforce lease ownership. Defaults to a random ID.
84
+ */
85
+ readonly consumerId?: string;
86
+ /**
87
+ * Lease duration in ms for claimed events. Only used when the store
88
+ * supports `claimPending`. Default: 30 seconds.
89
+ */
90
+ readonly leaseMs?: number;
91
+ /**
92
+ * Callback for non-fatal errors during relay: publish failures,
93
+ * ownership mismatches, ack/fail errors, malformed events. Use this for
94
+ * logging and metrics. Must not throw — exceptions are swallowed.
95
+ */
96
+ readonly onError?: OutboxRelayErrorHandler;
97
+ /**
98
+ * Enable {@link EventTransport.publishMany} when the transport implements it.
99
+ * Default: `true`. Set to `false` to force per-event `publish()` — useful
100
+ * for transports where strict event-order observability matters more than
101
+ * throughput, or to debug batch-specific issues.
102
+ */
103
+ readonly usePublishMany?: boolean;
104
+ /**
105
+ * Retry/DLQ decision policy. When set, {@link EventOutbox.relayBatch}
106
+ * invokes this on every failure and uses the returned options for
107
+ * `store.fail()`. Centralises the "after N fails, dead-letter" rule so
108
+ * apps don't recompute `exponentialBackoff` + escalation thresholds on
109
+ * every failure site.
110
+ *
111
+ * Without a policy, `fail()` is called with `{}` (immediate re-visibility
112
+ * on next poll) — legacy behaviour, unchanged.
113
+ */
114
+ readonly failurePolicy?: OutboxFailurePolicy;
115
+ /**
116
+ * Unit-of-Work session provider (AsyncLocalStorage integration).
117
+ *
118
+ * When set, `store()` calls this to get the active DB session and uses
119
+ * it as `OutboxWriteOptions.session` — **only when the caller has not
120
+ * already passed an explicit `options.session`**. This eliminates the
121
+ * boilerplate of threading the transaction handle from the controller
122
+ * through every service layer down to the outbox call site.
123
+ *
124
+ * Wire up with arc's `transactionContext`:
125
+ * ```typescript
126
+ * import { transactionContext } from '@classytic/arc/context';
127
+ *
128
+ * const outbox = new EventOutbox({
129
+ * store: myOutboxStore,
130
+ * sessionProvider: () => transactionContext.get(),
131
+ * });
132
+ *
133
+ * // In your service layer — session is auto-picked up:
134
+ * await transactionContext.run(mongooseSession, async () => {
135
+ * await orders.insertOne(order, { session: mongooseSession });
136
+ * await outbox.store(orderCreatedEvent); // no session arg needed
137
+ * });
138
+ * ```
139
+ */
140
+ readonly sessionProvider?: () => unknown;
141
+ /**
142
+ * W3C Trace Context provider.
143
+ *
144
+ * When set, `store()` calls this and merges the returned headers into
145
+ * `OutboxWriteOptions.headers` — only when `traceparent` is not already
146
+ * present in the caller-supplied headers. Downstream relay workers can
147
+ * then forward the headers to the transport, preserving the distributed
148
+ * trace tree across service boundaries.
149
+ *
150
+ * Wire up with arc's `getTraceHeaders`:
151
+ * ```typescript
152
+ * import { getTraceHeaders } from '@classytic/arc/context';
153
+ *
154
+ * const outbox = new EventOutbox({
155
+ * store: myOutboxStore,
156
+ * traceContextProvider: getTraceHeaders,
157
+ * });
158
+ * ```
159
+ */
160
+ readonly traceContextProvider?: () => Record<string, string> | undefined;
161
+ }
162
+ declare class EventOutbox {
163
+ private readonly _store;
164
+ private readonly _transport?;
165
+ private readonly _batchSize;
166
+ private readonly _consumerId;
167
+ private readonly _leaseMs;
168
+ private readonly _onError?;
169
+ private readonly _usePublishMany;
170
+ private readonly _sessionProvider?;
171
+ private readonly _traceContextProvider?;
172
+ private readonly _failurePolicy?;
173
+ /**
174
+ * In-process attempt counter per event id. Accurate within this relay
175
+ * process; resets on restart. Populated as failures occur and cleared on
176
+ * successful ack or dead-letter transition; additionally hard-capped at
177
+ * {@link MAX_TRACKED_ATTEMPTS} (oldest-write evicted first) so events
178
+ * resolved by another relay worker can't accumulate forever. For durable
179
+ * authoritative counts, apps can query the store directly inside
180
+ * {@link OutboxFailurePolicy}.
181
+ */
182
+ private readonly _attempts;
183
+ constructor(opts: EventOutboxOptions);
184
+ /** Unique consumer ID used for lease ownership when the store supports claims */
185
+ get consumerId(): string;
186
+ /**
187
+ * Store event in outbox.
188
+ *
189
+ * Validates that `event.type` and `event.meta.id` are present — throws
190
+ * {@link InvalidOutboxEventError} otherwise, so corrupt rows can never
191
+ * be persisted via this API.
192
+ *
193
+ * Pass `options.session` to participate in a host-managed DB transaction
194
+ * (store must support session-aware writes). Other options (`visibleAt`,
195
+ * `dedupeKey`, `partitionKey`, `headers`) are forwarded to stores that
196
+ * implement them and ignored otherwise.
197
+ */
198
+ store(event: DomainEvent, options?: OutboxWriteOptions): Promise<void>;
199
+ private _reportError;
200
+ /**
201
+ * Relay pending events to transport and return the number of successful
202
+ * publish+acknowledge pairs.
203
+ *
204
+ * For richer observability (per-kind counts, publishMany detection, etc.)
205
+ * use {@link relayBatch} which returns a {@link RelayResult}. This method
206
+ * is the backward-compatible shortcut that returns just the count.
207
+ *
208
+ * @returns Number of successfully published AND acknowledged events
209
+ */
210
+ relay(): Promise<number>;
211
+ /**
212
+ * Relay a batch of pending events to the transport and return a rich
213
+ * {@link RelayResult} describing the outcome of each event.
214
+ *
215
+ * Behavior summary:
216
+ *
217
+ * - **Claim path**: uses {@link OutboxStore.claimPending} when the store
218
+ * supports it (safe for multi-worker relay) or falls back to
219
+ * {@link OutboxStore.getPending} (single-worker only).
220
+ *
221
+ * - **Publish path**: if the transport implements
222
+ * {@link EventTransport.publishMany} and `usePublishMany` is not disabled,
223
+ * the entire batch is sent in one call. Otherwise each event is published
224
+ * individually. Either way, per-event outcomes are tracked.
225
+ *
226
+ * - **Failure path**: if the store implements `fail`, per-event failures
227
+ * are reported via `store.fail(...)` and the batch continues. Without
228
+ * `fail`, the batch stops on the first failure (legacy behavior).
229
+ *
230
+ * - **Malformed events**: events missing `type` or `meta.id` abort the
231
+ * batch — a well-behaved store must never return them (see
232
+ * {@link OutboxStore} semantics #6). The error is reported via `onError`.
233
+ *
234
+ * - **Ownership mismatches**: if `acknowledge`/`fail` throws
235
+ * {@link OutboxOwnershipError} (our lease expired and another worker
236
+ * claimed the event), the event is NOT counted as relayed. The other
237
+ * worker will re-publish — at-least-once semantics preserved.
238
+ *
239
+ * @returns Per-kind outcome counts for the batch
240
+ */
241
+ relayBatch(): Promise<RelayResult>;
242
+ /**
243
+ * Fetch current dead-lettered events as typed {@link DeadLetteredEvent}
244
+ * envelopes. Delegates to {@link OutboxStore.getDeadLettered} — returns
245
+ * `[]` when the store doesn't implement it.
246
+ *
247
+ * Pairs with {@link OutboxFailurePolicy}: apps set a policy that routes to
248
+ * `deadLetter: true` after N attempts, then read back with this to alert,
249
+ * replay, or archive.
250
+ */
251
+ getDeadLettered(limit?: number): Promise<DeadLetteredEvent[]>;
252
+ /**
253
+ * Purge old **delivered** events from the outbox store.
254
+ * Delegates to `store.purge()` if implemented; no-op otherwise.
255
+ * @param olderThanMs - Remove events delivered more than this many ms ago (default: 7 days)
256
+ * @returns Number of purged events, or 0 if store doesn't support purge
257
+ */
258
+ purge(olderThanMs?: number): Promise<number>;
259
+ }
260
+ //#endregion
261
+ //#region src/events/outbox-module.d.ts
262
+ interface OutboxModuleOptions {
263
+ /**
264
+ * The durable store. Supply it directly, or as a factory when it needs the booted app
265
+ * (a mongoose connection decorated by an earlier plugin, for instance).
266
+ */
267
+ store: OutboxStore | ((fastify: FastifyInstance) => OutboxStore);
268
+ /**
269
+ * Where relayed events are published. Omit to use the app's OWN transport — the ordinary case;
270
+ * pass one only when the outbox must publish somewhere else.
271
+ *
272
+ * The default resolves the RAW `EventTransport` the events plugin registered, never the
273
+ * `fastify.events` facade. The facade takes `(type, payload, meta?)` and swallows publish
274
+ * errors under `failOpen` — both fatal here: the first makes every relayed event fail its
275
+ * non-empty-string type guard, the second makes a failure read as success and acknowledges
276
+ * the row. See `ARC_EVENT_TRANSPORT`.
277
+ */
278
+ transport?: EventTransport | ((fastify: FastifyInstance) => EventTransport);
279
+ /** Module name, and therefore the `dependsOn` key. Default `'outbox'`. */
280
+ name?: string;
281
+ /** Relay interval in ms. Default 5000. */
282
+ relayEveryMs?: number;
283
+ /**
284
+ * Rows per relay tick. Left to the store's own default when omitted — a batch size is a
285
+ * throughput tuning decision, not something this module should invent.
286
+ */
287
+ batchSize?: number;
288
+ /** Lease duration for a claimed batch, in ms. */
289
+ leaseMs?: number;
290
+ /**
291
+ * Consumer id recorded on the lease. Default:
292
+ * `<name>:<hostname>:<pid>:<random>` — UNIQUE PER RELAY INSTANCE.
293
+ *
294
+ * The lease is what stops two relays publishing the same event, and it can
295
+ * only do that if they are distinguishable. The pre-2.34 default was the
296
+ * shared literal `'arc-outbox-relay'`, which QUIETLY violated the rule the
297
+ * doc stated: every process — and every co-resident module — was the same
298
+ * logical owner, so a lease that expired and was re-claimed elsewhere looked
299
+ * to the store's ownership check like the original owner never lost it. The
300
+ * stale-owner protection was pinned open.
301
+ *
302
+ * Set this explicitly only to make lease ownership legible in ops tooling
303
+ * (e.g. `billing-relay:pod-7`); whatever you set MUST stay distinct per
304
+ * relay, not merely per deployment.
305
+ */
306
+ consumerId?: string;
307
+ /**
308
+ * Called for every non-fatal relay problem — publish failures, ownership mismatches,
309
+ * acknowledge failures.
310
+ *
311
+ * **Wire this.** Silence here is the failure mode that matters: the relay keeps ticking, rows
312
+ * keep failing, and the only symptom is revenue that never posted.
313
+ */
314
+ onError?: OutboxRelayErrorHandler;
315
+ /**
316
+ * Retry / dead-letter policy for a failed publish — `({ attempts }) => { retryAt } |
317
+ * { deadLetter: true }`.
318
+ *
319
+ * Omitting it takes `EventOutbox`'s default. Exposed because a real host had one and losing it
320
+ * on adoption would be a silent downgrade: without a policy a permanently-failing row either
321
+ * retries forever or dead-letters on the first blip, and both are wrong for money. A typical
322
+ * shape is exponential backoff up to N attempts, then dead-letter.
323
+ */
324
+ failurePolicy?: OutboxFailurePolicy;
325
+ /**
326
+ * Run one relay pass at boot. Default `true` — a process that restarts with a backlog should
327
+ * drain it immediately rather than waiting a full interval, because that backlog is precisely
328
+ * the events the previous process failed to publish.
329
+ */
330
+ runOnStart?: boolean;
331
+ }
332
+ /** What the module exports at `fastify.arc.modules.<name>`. */
333
+ interface OutboxModuleExports {
334
+ /** The store, for consumers that write events transactionally. */
335
+ store: OutboxStore;
336
+ /** The relay, for a host that wants to drain on demand (tests, admin actions). */
337
+ relay: EventOutbox;
338
+ }
339
+ /**
340
+ * Compose the outbox as a module.
341
+ *
342
+ * ```ts
343
+ * // host
344
+ * const model = createOutboxModel(connection, { visibleAtField: 'nextVisibleAt' });
345
+ * createApp({ modules: [
346
+ * createOutboxModule({
347
+ * store: repositoryAsOutboxStore(new Repository(model), { visibleAtField: 'nextVisibleAt' }),
348
+ * onError: (err, ctx) => app.log.error({ err, ...ctx }, 'outbox relay'),
349
+ * }),
350
+ * …
351
+ * ]});
352
+ *
353
+ * // consumer module
354
+ * defineModule({
355
+ * name: 'order',
356
+ * dependsOn: ['outbox'],
357
+ * bootstrap: (f) => createOrder({
358
+ * outbox: getModuleExports<OutboxModuleExports>(f, 'outbox').store,
359
+ * }),
360
+ * });
361
+ * ```
362
+ *
363
+ * `dependsOn` is doing real work there: it both orders the bootstraps and makes a missing outbox a
364
+ * boot error naming the module that needed it.
365
+ */
366
+ declare function createOutboxModule(options: OutboxModuleOptions): ArcModule<OutboxModuleExports>;
367
+ //#endregion
368
+ export { EventOutbox as a, OutboxRelayErrorKind as c, MemoryOutboxStore as i, RelayResult as l, OutboxModuleOptions as n, EventOutboxOptions as o, createOutboxModule as r, OutboxRelayErrorHandler as s, OutboxModuleExports as t };
@@ -1,5 +1,5 @@
1
1
 
2
- import { a as UserBase, c as normalizeRoles, i as PermissionContext, n as DataPolicy, r as PermissionCheck, s as getUserRoles, t as AuthorizationDecision } from "../types-B7XeLEgK.mjs";
2
+ import { c as DataPolicy, d as UserBase, l as PermissionCheck, m as normalizeRoles, p as getUserRoles, s as AuthorizationDecision, u as PermissionContext } from "../base-Csjc2oF-.mjs";
3
3
  import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-I_EeRWND.mjs";
4
- import { $ as requireAuth, A as RequireGrantOptions, B as ConnectEventsOptions, C as requireServiceScope, D as GRANT_MODES, E as createRoleHierarchy, F as PermissionRequirement, G as createOrgPermissions, H as DynamicPermissionMatrixConfig, I as collectPublicSurface, J as allowPublic, K as allOf, L as describePermission, M as requireGrant, N as conjoinPolicyFilters, O as GrantMode, P as AccessExplanation, Q as not, R as describePermissionMap, S as requireScopeContext, T as RoleHierarchy, U as PermissionEventBus, V as DynamicPermissionMatrix, W as createDynamicPermissionMatrix, X as deny, Y as anyOf, Z as denyAll, _ as publicReadAdminWrite, a as PermissionMatrixRegistry, at as scopeOf, b as requireOrgMembership, c as introspectModule, ct as evaluatePermissionDecision, d as authenticated, dt as RequireMandateOptions, et as requireOwnership, f as fullPublic, ft as requireAgentScope, g as publicRead, h as presets_d_exports, i as PermissionMatrixOptions, it as when, j as modeSatisfies, k as GrantResolution, l as introspectRegistry, lt as normalizeToDecision, m as permissionMatrix, mt as requireMandate, n as PermissionEntryType, nt as requireRoles, o as buildPermissionMatrix, ot as PermissionCheckReturn, p as ownerWithAdminBypass, pt as requireDPoP, q as allow, r as PermissionMatrix, rt as roles, s as introspectCheck, st as applyAuthorizationDecision, t as PermissionEntry, tt as requirePlatformRole, u as adminOnly, ut as RequireAgentScopeOptions, v as readOnly, w as requireTeamMembership, x as requireOrgRole, y as requireOrgInScope, z as explainAccess } from "../index-zq6VrjaB.mjs";
4
+ import { $ as requireAuth, A as RequireGrantOptions, B as ConnectEventsOptions, C as requireServiceScope, D as GRANT_MODES, E as createRoleHierarchy, F as PermissionRequirement, G as createOrgPermissions, H as DynamicPermissionMatrixConfig, I as collectPublicSurface, J as allowPublic, K as allOf, L as describePermission, M as requireGrant, N as conjoinPolicyFilters, O as GrantMode, P as AccessExplanation, Q as not, R as describePermissionMap, S as requireScopeContext, T as RoleHierarchy, U as PermissionEventBus, V as DynamicPermissionMatrix, W as createDynamicPermissionMatrix, X as deny, Y as anyOf, Z as denyAll, _ as publicReadAdminWrite, a as PermissionMatrixRegistry, at as scopeOf, b as requireOrgMembership, c as introspectModule, ct as evaluatePermissionDecision, d as authenticated, dt as RequireMandateOptions, et as requireOwnership, f as fullPublic, ft as requireAgentScope, g as publicRead, h as presets_d_exports, i as PermissionMatrixOptions, it as when, j as modeSatisfies, k as GrantResolution, l as introspectRegistry, lt as normalizeToDecision, m as permissionMatrix, mt as requireMandate, n as PermissionEntryType, nt as requireRoles, o as buildPermissionMatrix, ot as PermissionCheckReturn, p as ownerWithAdminBypass, pt as requireDPoP, q as allow, r as PermissionMatrix, rt as roles, s as introspectCheck, st as applyAuthorizationDecision, t as PermissionEntry, tt as requirePlatformRole, u as adminOnly, ut as RequireAgentScopeOptions, v as readOnly, w as requireTeamMembership, x as requireOrgRole, y as requireOrgInScope, z as explainAccess } from "../index-B-DvUzsr.mjs";
5
5
  export { type AccessExplanation, type AuthorizationDecision, type ConnectEventsOptions, type DataPolicy, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type FieldPermission, type FieldPermissionMap, type FieldPermissionType, GRANT_MODES, type GrantMode, type GrantResolution, type PermissionCheck, type PermissionCheckReturn, type PermissionContext, type PermissionEntry, type PermissionEntryType, type PermissionEventBus, type PermissionMatrix, type PermissionMatrixOptions, type PermissionMatrixRegistry, type PermissionRequirement, type RequireAgentScopeOptions, type RequireGrantOptions, type RequireMandateOptions, type RoleHierarchy, type UserBase, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, buildPermissionMatrix, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, introspectCheck, introspectModule, introspectRegistry, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requirePlatformRole, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
- import { a as conjoinPolicyFilters, i as normalizeToDecision, r as evaluatePermissionDecision, t as applyAuthorizationDecision } from "../authorizationDecision-__T3EJDA.mjs";
3
- import { n as getUserRoles, r as normalizeRoles } from "../userHelpers-BNsOXzOd.mjs";
4
- import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-DEi65pGj.mjs";
5
- import { A as requireAgentScope, B as requireAuth, C as createOrgPermissions, D as requireScopeContext, E as requireOrgRole, F as allowPublic, G as when, H as requirePlatformRole, I as anyOf, K as scopeOf, L as deny, M as requireMandate, N as allOf, O as requireServiceScope, P as allow, R as denyAll, S as createDynamicPermissionMatrix, T as requireOrgMembership, U as requireRoles, V as requireOwnership, W as roles, _ as requireGrant, a as adminOnly, b as describePermissionMap, c as ownerWithAdminBypass, d as publicRead, f as publicReadAdminWrite, g as modeSatisfies, h as GRANT_MODES, i as introspectRegistry, j as requireDPoP, k as requireTeamMembership, l as permissionMatrix, m as createRoleHierarchy, n as introspectCheck, o as authenticated, p as readOnly, r as introspectModule, s as fullPublic, t as buildPermissionMatrix, u as presets_exports, v as collectPublicSurface, w as requireOrgInScope, x as explainAccess, y as describePermission, z as not } from "../permissions-Dl_m0NCe.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { a as conjoinPolicyFilters, i as normalizeToDecision, r as evaluatePermissionDecision, t as applyAuthorizationDecision } from "../authorizationDecision-B3mP_QTy.mjs";
3
+ import { n as getUserRoles, r as normalizeRoles } from "../userHelpers-CWF5pbZD.mjs";
4
+ import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-CojeUkS4.mjs";
5
+ import { A as requireAgentScope, B as requireAuth, C as createOrgPermissions, D as requireScopeContext, E as requireOrgRole, F as allowPublic, G as when, H as requirePlatformRole, I as anyOf, K as scopeOf, L as deny, M as requireMandate, N as allOf, O as requireServiceScope, P as allow, R as denyAll, S as createDynamicPermissionMatrix, T as requireOrgMembership, U as requireRoles, V as requireOwnership, W as roles, _ as requireGrant, a as adminOnly, b as describePermissionMap, c as ownerWithAdminBypass, d as publicRead, f as publicReadAdminWrite, g as modeSatisfies, h as GRANT_MODES, i as introspectRegistry, j as requireDPoP, k as requireTeamMembership, l as permissionMatrix, m as createRoleHierarchy, n as introspectCheck, o as authenticated, p as readOnly, r as introspectModule, s as fullPublic, t as buildPermissionMatrix, u as presets_exports, v as collectPublicSurface, w as requireOrgInScope, x as explainAccess, y as describePermission, z as not } from "../permissions-BAfwgBxc.mjs";
6
6
  export { GRANT_MODES, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, buildPermissionMatrix, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, introspectCheck, introspectModule, introspectRegistry, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requirePlatformRole, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
@@ -1,10 +1,10 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
- import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-DNg-KNCk.mjs";
3
3
  import { arcLog } from "./logger/index.mjs";
4
- import { a as conjoinPolicyFilters, i as normalizeToDecision } from "./authorizationDecision-__T3EJDA.mjs";
5
- import { n as getUserRoles } from "./userHelpers-BNsOXzOd.mjs";
6
- import { C as isService, S as isOrgInScope, a as getDPoPJkt, b as isElevated, d as getScopeContext, f as getScopeContextMap, g as getUserId, m as getTeamId, n as PUBLIC_SCOPE, o as getMandate, p as getServiceScopes, u as getRequestScope, v as hasOrgAccess, x as isMember } from "./types-DXYX7dIR.mjs";
7
- import { t as MemoryCacheStore } from "./memory-DsuWnj4T.mjs";
4
+ import { a as conjoinPolicyFilters, i as normalizeToDecision } from "./authorizationDecision-B3mP_QTy.mjs";
5
+ import { n as getUserRoles } from "./userHelpers-CWF5pbZD.mjs";
6
+ import { C as isService, S as isOrgInScope, a as getDPoPJkt, b as isElevated, d as getScopeContext, f as getScopeContextMap, g as getUserId, m as getTeamId, n as PUBLIC_SCOPE, o as getMandate, p as getServiceScopes, u as getRequestScope, v as hasOrgAccess, x as isMember } from "./types-CoqIRrkY.mjs";
7
+ import { t as MemoryCacheStore } from "./memory-qYSB7rMQ.mjs";
8
8
  import { randomUUID } from "node:crypto";
9
9
  //#region src/permissions/context.ts
10
10
  /**
@@ -1614,6 +1614,25 @@ function introspectRegistry(registry) {
1614
1614
  for (const [action, check] of Object.entries(entry.permissions ?? {})) if (typeof check === "function") map[action] = introspectCheck(check);
1615
1615
  for (const a of entry.actions ?? []) if (typeof a.permissions === "function") map[`action:${a.name}`] = introspectCheck(a.permissions);
1616
1616
  for (const agg of entry.aggregations ?? []) if (typeof agg.permissions === "function") map[`agg:${agg.name}`] = introspectCheck(agg.permissions);
1617
+ /**
1618
+ * Custom routes that OPTED IN via `capability`.
1619
+ *
1620
+ * A route has no inherent name — only a method and a path — so it cannot be
1621
+ * keyed automatically, and a path is not an identity. Without this, a
1622
+ * resource whose gates live entirely on `routes[]` published nothing, was
1623
+ * absent from the matrix, and every `can()` against it answered `false`:
1624
+ * a UI gating on it hid the feature from everyone, admins included, and that
1625
+ * reads as broken permissions rather than an unpublished key.
1626
+ *
1627
+ * The key is BARE, alongside `list`/`get`/`create`, so a consumer never has
1628
+ * to know whether a verb is a route, an action or a CRUD slot.
1629
+ */
1630
+ for (const route of entry.customRoutes ?? []) {
1631
+ const key = route.capability;
1632
+ if (key === void 0 || typeof route.permissions !== "function") continue;
1633
+ if (map[key] !== void 0) throw new Error(`[arc] permission-matrix collision on resource "${entry.name}": route ${route.method} ${route.path} declares capability "${key}", which is already published by a CRUD slot, action or another route. Rename the route's \`capability\`.`);
1634
+ map[key] = introspectCheck(route.permissions);
1635
+ }
1617
1636
  if (Object.keys(map).length > 0) modules[entry.name] = map;
1618
1637
  }
1619
1638
  return modules;
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
- import { r as ForbiddenError } from "./errors-Bh1KK5ps.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { r as ForbiddenError } from "./errors-Cd_yy7aW.mjs";
3
3
  //#region src/pipeline/pipe.ts
4
4
  /**
5
5
  * Compose pipeline steps into an ordered array.
@@ -1,5 +1,5 @@
1
1
 
2
- import { Ct as PipelineStep, Rt as IControllerResponse, St as PipelineContext, _t as Guard, bt as OperationFilter, vt as Interceptor, wt as Transform, xt as PipelineConfig, yt as NextFunction } from "../index-CpzxqePp.mjs";
2
+ import { Ct as PipelineStep, Fn as IControllerResponse, St as PipelineContext, _t as Guard, bt as OperationFilter, vt as Interceptor, wt as Transform, xt as PipelineConfig, yt as NextFunction } from "../index-BcR2bFZQ.mjs";
3
3
  //#region src/pipeline/guard.d.ts
4
4
  interface GuardOptions {
5
5
  operations?: OperationFilter;
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
- import { n as pipe, t as executePipeline } from "../pipe-ELHCP3zj.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { n as pipe, t as executePipeline } from "../pipe-BzzoEhHj.mjs";
3
3
  //#region src/pipeline/guard.ts
4
4
  /**
5
5
  * Create a named guard.
@@ -1,9 +1,9 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
- import { n as getUserRoles } from "./userHelpers-BNsOXzOd.mjs";
3
- import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-DXYX7dIR.mjs";
4
- import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-DEi65pGj.mjs";
5
- import { t as executePipeline } from "./pipe-ELHCP3zj.mjs";
6
- import { t as buildRequestScopeProjection } from "./projection-CjHhM5W1.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { n as getUserRoles } from "./userHelpers-CWF5pbZD.mjs";
3
+ import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-CoqIRrkY.mjs";
4
+ import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-CojeUkS4.mjs";
5
+ import { t as executePipeline } from "./pipe-BzzoEhHj.mjs";
6
+ import { t as buildRequestScopeProjection } from "./projection-BKM0Ui-s.mjs";
7
7
  import { isPaginatedResult, toCanonicalList } from "@classytic/repo-core/pagination";
8
8
  //#region src/core/fastifyAdapter.ts
9
9
  /** Type guard for Mongoose-like documents with toObject() */
@@ -1,10 +1,10 @@
1
1
 
2
- import { At as RouteDefinition, J as PresetHook, Q as MiddlewareConfig, et as RouteSchemaOptions } from "../index-CpzxqePp.mjs";
3
- import { l as AnyRecord } from "../types-B7XeLEgK.mjs";
4
- import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-CpYUJmPA.mjs";
5
- import { _ as HealthCheck, b as healthPlugin, f as ScheduleDefinition, g as schedulesPlugin, h as _default$7, m as SchedulesPluginOptions, p as ScheduleStats, v as HealthOptions, y as _default$3 } from "../types-CT5vu6M0.mjs";
6
- import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-BppG5bMT.mjs";
7
- import { _ as CachingRule, a as MetricsCollector, c as metricsPlugin, d as _default$5, f as realtimePlugin, g as CachingOptions, h as ssePlugin, i as MetricEntry, l as ChangeOperation, m as _default$8, n as _default$9, o as MetricsOptions, p as SSEOptions, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as RealtimeOptions, v as _default$1, y as cachingPlugin } from "../versioning-D_rhHfZm.mjs";
2
+ import { t as AnyRecord } from "../base-Csjc2oF-.mjs";
3
+ import { At as RouteDefinition, J as PresetHook, Q as MiddlewareConfig, et as RouteSchemaOptions } from "../index-BcR2bFZQ.mjs";
4
+ import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-DI5AN2b5.mjs";
5
+ import { _ as HealthCheck, b as healthPlugin, f as ScheduleDefinition, g as schedulesPlugin, h as _default$7, m as SchedulesPluginOptions, p as ScheduleStats, v as HealthOptions, y as _default$3 } from "../types-BcTumAz_.mjs";
6
+ import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-DVsTAy6X.mjs";
7
+ import { _ as CachingRule, a as MetricsCollector, c as metricsPlugin, d as _default$5, f as realtimePlugin, g as CachingOptions, h as ssePlugin, i as MetricEntry, l as ChangeOperation, m as _default$8, n as _default$9, o as MetricsOptions, p as SSEOptions, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as RealtimeOptions, v as _default$1, y as cachingPlugin } from "../versioning-DEs-_hFi.mjs";
8
8
  import { t as TracingOptions } from "../tracing-Dro5eH6j.mjs";
9
9
  import { PaginatedResult } from "@classytic/repo-core/pagination";
10
10
  import { FastifyInstance, FastifyPluginAsync } from "fastify";
@@ -1,19 +1,19 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
- import { p as MUTATION_OPERATIONS } from "../constants-J99LGTJI.mjs";
3
- import { c as getOrgId } from "../types-DXYX7dIR.mjs";
4
- import { n as requestContext } from "../requestContext-B6vQF-sy.mjs";
5
- import { t as hasEvents } from "../typeGuards-B_5-hKjJ.mjs";
6
- import { t as HookSystem } from "../HookSystem-vimw5D7Z.mjs";
7
- import { t as ResourceRegistry } from "../ResourceRegistry-BVr7PgA0.mjs";
8
- import { a as requestIdPlugin, i as createRequestIdGenerator, n as health_default, o as requestId_default, s as sanitizeRequestId, t as healthPlugin } from "../health-5XnTa2uo.mjs";
9
- import { n as caching_default, t as cachingPlugin } from "../caching-DFJqHyFs.mjs";
10
- import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-B2AZUJUj.mjs";
11
- import { n as metrics_default, t as metricsPlugin } from "../metrics-DdQL8syd.mjs";
12
- import { n as realtime_default, t as realtimePlugin } from "../realtime-DVvVZZFz.mjs";
13
- import { t as replyHelpersPlugin } from "../replyHelpers-DS-P0b32.mjs";
14
- import { n as schedules_default, t as schedulesPlugin } from "../schedules-C2Q3uv2d.mjs";
15
- import { n as sse_default, t as ssePlugin } from "../sse-B9P4Y-UI.mjs";
16
- import { n as versioning_default, t as versioningPlugin } from "../versioning-CKv2jz_U.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { p as MUTATION_OPERATIONS } from "../constants-BxCoxmiN.mjs";
3
+ import { c as getOrgId } from "../types-CoqIRrkY.mjs";
4
+ import { n as requestContext } from "../requestContext-uYE35JxI.mjs";
5
+ import { t as hasEvents } from "../typeGuards-jjKJDN13.mjs";
6
+ import { t as HookSystem } from "../HookSystem-DqXkMXkB.mjs";
7
+ import { t as ResourceRegistry } from "../ResourceRegistry-DoALUlOO.mjs";
8
+ import { a as requestIdPlugin, i as createRequestIdGenerator, n as health_default, o as requestId_default, s as sanitizeRequestId, t as healthPlugin } from "../health-CasG2A28.mjs";
9
+ import { n as caching_default, t as cachingPlugin } from "../caching-BcGmvnHh.mjs";
10
+ import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-C7xBqHsI.mjs";
11
+ import { n as metrics_default, t as metricsPlugin } from "../metrics-D7uchLjN.mjs";
12
+ import { n as realtime_default, t as realtimePlugin } from "../realtime-CTkv3O59.mjs";
13
+ import { t as replyHelpersPlugin } from "../replyHelpers-BSBVCwL3.mjs";
14
+ import { n as schedules_default, t as schedulesPlugin } from "../schedules-CAcZgia0.mjs";
15
+ import { n as sse_default, t as ssePlugin } from "../sse-Cf0jUHsh.mjs";
16
+ import { n as versioning_default, t as versioningPlugin } from "../versioning-rZbyLVD-.mjs";
17
17
  import fp from "fastify-plugin";
18
18
  //#region src/core/arcCorePlugin.ts
19
19
  const arcCorePlugin = async (fastify, opts = {}) => {
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
- import { t as hasEvents } from "../typeGuards-B_5-hKjJ.mjs";
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
+ import { t as hasEvents } from "../typeGuards-jjKJDN13.mjs";
3
3
  import fp from "fastify-plugin";
4
4
  //#region src/plugins/response-cache.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  import { createRequire } from "node:module";
3
3
  import fp from "fastify-plugin";
4
4
  //#region src/plugins/tracing.ts
@@ -59,7 +59,7 @@ try {
59
59
  function createTracerProvider(options) {
60
60
  if (!isAvailable || !NodeTracerProvider || !BatchSpanProcessor || !OTLPTraceExporter) return null;
61
61
  const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
62
- const resolvedVersion = serviceVersion ?? "2.32.0";
62
+ const resolvedVersion = serviceVersion ?? "2.34.0";
63
63
  const exporter = new OTLPTraceExporter({ url: exporterUrl });
64
64
  const provider = new NodeTracerProvider({ resource: { attributes: {
65
65
  "service.name": serviceName,
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  //#region src/utils/pluralize.ts
3
3
  /**
4
4
  * Lightweight English pluralization for the Arc CLI.
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
2
  //#region src/factory/preloadResources.ts
3
3
  /**
4
4
  * Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
@@ -1,15 +1,15 @@
1
1
 
2
- import { Gt as Authenticator } from "./index-CpzxqePp.mjs";
2
+ import { It as Authenticator } from "./index-BcR2bFZQ.mjs";
3
3
  import { r as CacheStore } from "./interface-BOk3YnTz.mjs";
4
4
  import { n as ElevationOptions } from "./elevation-BXCfVcNG.mjs";
5
- import { a as EventTransport } from "./EventTransport-2uVV34WU.mjs";
5
+ import { a as EventTransport } from "./EventTransport-BEVP50ka.mjs";
6
6
  import { t as ExternalOpenApiPaths } from "./externalPaths-CmGOxOtD.mjs";
7
7
  import { r as QueryCachePluginOptions } from "./queryCachePlugin-BzqxconG.mjs";
8
- import { t as ErrorHandlerOptions } from "./errorHandler-CpYUJmPA.mjs";
9
- import { l as ResourceLike, m as SchedulesPluginOptions, n as ArcModuleInput, v as HealthOptions } from "./types-CT5vu6M0.mjs";
10
- import "./index-ZWhLTp_s.mjs";
11
- import { t as EventPluginOptions } from "./eventPlugin-GF5nnBIq.mjs";
12
- import { g as CachingOptions, o as MetricsOptions, p as SSEOptions, t as VersioningOptions, u as RealtimeOptions } from "./versioning-D_rhHfZm.mjs";
8
+ import { t as ErrorHandlerOptions } from "./errorHandler-DI5AN2b5.mjs";
9
+ import { l as ResourceLike, m as SchedulesPluginOptions, n as ArcModuleInput, v as HealthOptions } from "./types-BcTumAz_.mjs";
10
+ import "./index-C5NnMEKF.mjs";
11
+ import { t as EventPluginOptions } from "./eventPlugin-DSNEZWfV.mjs";
12
+ import { g as CachingOptions, o as MetricsOptions, p as SSEOptions, t as VersioningOptions, u as RealtimeOptions } from "./versioning-DEs-_hFi.mjs";
13
13
  import { r as IdempotencyStore } from "./interface-DEWNOMza.mjs";
14
14
  import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
15
15
  //#region src/factory/types/assets.d.ts
@@ -463,6 +463,29 @@ interface CreateAppOptions {
463
463
  * would be instance-local.
464
464
  */
465
465
  runtime?: "memory" | "distributed";
466
+ /**
467
+ * Deployment ROLE of this process (topology plan, Phase 2). Decides which
468
+ * async machinery mounts; default `'all'` is the single-process case and
469
+ * changes nothing.
470
+ *
471
+ * - `'api'` / `'worker'` — no module schedule arms run here (the outbox
472
+ * relay arm included); a worker fleet or scheduler deployment owns them.
473
+ * Register `jobsPlugin({ mode })` to match ('api' → 'producer').
474
+ * - `'relay'` — ONLY `kind: 'relay'` schedule arms run (the outbox
475
+ * relays); declaring HTTP `resources` is boot-fatal.
476
+ * - `'scheduler'` — every schedule arm runs; HTTP resources boot-fatal.
477
+ * - `'all'` — everything (default).
478
+ *
479
+ * A skipped arm is logged by name at boot so a misdeployed process is
480
+ * legible from its first lines.
481
+ *
482
+ * `createWorker` is the paved road for headless processes and forwards
483
+ * this option untouched — one axis, not two mechanisms. Its default stays
484
+ * `'all'` (its 2.23 contract: the headless process runs everything
485
+ * non-HTTP); pass `role: 'worker'` there when a dedicated scheduler/relay
486
+ * deployment owns the arms.
487
+ */
488
+ role?: "api" | "worker" | "relay" | "scheduler" | "all";
466
489
  /**
467
490
  * Store and transport instances for runtime profile validation.
468
491
  * When `runtime` is `'distributed'`, Arc validates that these are