@classytic/arc 2.41.0 → 2.43.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 (230) hide show
  1. package/dist/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
  2. package/dist/{EventTransport-n7qO5Cz3.mjs → EventTransport-tzA7CAB4.mjs} +22 -17
  3. package/dist/{HookSystem-CxvZBo77.mjs → HookSystem-B6UaKRbF.mjs} +2 -2
  4. package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
  5. package/dist/{ResourceRegistry-Cu7uTJp9.mjs → ResourceRegistry-CuCARu2B.mjs} +44 -13
  6. package/dist/actionPermissions-BotX1YOa.mjs +776 -0
  7. package/dist/audit/index.d.mts +43 -5
  8. package/dist/audit/index.mjs +48 -26
  9. package/dist/auth/audit.mjs +1 -1
  10. package/dist/auth/index.d.mts +43 -13
  11. package/dist/auth/index.mjs +130 -155
  12. package/dist/auth/redis-session.mjs +1 -1
  13. package/dist/{authorizationDecision-2YY_Kaj1.mjs → authorizationDecision-DQYrkl5f.mjs} +7 -102
  14. package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
  15. package/dist/boundedMap-BULzfXYU.mjs +57 -0
  16. package/dist/{buildHandler-CUhjGHGZ.mjs → buildHandler-CRQ8EcX5.mjs} +4 -4
  17. package/dist/cache/index.d.mts +22 -34
  18. package/dist/cache/index.mjs +4 -4
  19. package/dist/{caching-DsWDjIxx.mjs → caching-Cc2M1DwO.mjs} +3 -3
  20. package/dist/claimed-B10RTfkM.mjs +8 -0
  21. package/dist/cleanup/index.d.mts +6 -10
  22. package/dist/cleanup/index.mjs +27 -73
  23. package/dist/cli/commands/describe.d.mts +4 -2
  24. package/dist/cli/commands/describe.mjs +7 -4
  25. package/dist/cli/commands/docs.mjs +3 -3
  26. package/dist/cli/commands/doctor.mjs +1 -1
  27. package/dist/cli/commands/generate.mjs +2 -2
  28. package/dist/cli/commands/init.mjs +2 -2
  29. package/dist/cli/commands/introspect.mjs +2 -2
  30. package/dist/cli/index.mjs +3 -3
  31. package/dist/{constants-BxLgNFF7.mjs → constants-Cu7Mx7_U.mjs} +4 -2
  32. package/dist/context/index.d.mts +2 -5
  33. package/dist/context/index.mjs +18 -38
  34. package/dist/core/index.d.mts +3 -3
  35. package/dist/core/index.mjs +8 -8
  36. package/dist/{core-iNGqYerO.mjs → core-Cb0LjccA.mjs} +5 -4
  37. package/dist/{createActionRouter-BBlbPs3k.mjs → createActionRouter-xjqonMRO.mjs} +87 -39
  38. package/dist/{createAggregationRouter-Dv5SuK2x.mjs → createAggregationRouter-zRYWw_5D.mjs} +11 -8
  39. package/dist/{preloadResources-Bbp4QJ8V.mjs → createApp-D-953ZAq.mjs} +299 -390
  40. package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-C9cxS8zt.d.mts} +1 -1
  41. package/dist/{defineAggregation-UyeurGkp.mjs → defineAggregation-Bm8RjMbq.mjs} +1 -1
  42. package/dist/{defineResource-DzGT-2LP.mjs → defineResource-DIC7JZGU.mjs} +118 -1024
  43. package/dist/discovery/index.mjs +1 -1
  44. package/dist/docs/index.d.mts +10 -4
  45. package/dist/docs/index.mjs +4 -4
  46. package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
  47. package/dist/{elevation-BF-vhGxY.mjs → elevation-DG8SrLN-.mjs} +41 -12
  48. package/dist/encryption/index.mjs +3 -3
  49. package/dist/{errorHandler-CIMkCOWm.mjs → errorHandler-BnfDviL1.mjs} +26 -5
  50. package/dist/{errors-C_YhELhe.mjs → errors-CtrywMHP.mjs} +58 -23
  51. package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
  52. package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
  53. package/dist/{eventPlugin-CmXaPWLv.mjs → eventPlugin-Q6BhzHzs.mjs} +82 -21
  54. package/dist/{subscribe-helpers-AVYPgqTl.mjs → eventTypes-Cdhm6ZlV.mjs} +151 -17
  55. package/dist/events/index.d.mts +33 -8
  56. package/dist/events/index.mjs +49 -53
  57. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  58. package/dist/events/transports/redis-stream-entry.mjs +139 -157
  59. package/dist/events/transports/redis.d.mts +1 -1
  60. package/dist/events/transports/redis.mjs +2 -2
  61. package/dist/factory/index.d.mts +32 -17
  62. package/dist/factory/index.mjs +213 -32
  63. package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DhUJ-mvo.d.mts} +11 -25
  64. package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
  65. package/dist/{fields-BTyPLHK0.mjs → fields-ToPYpMqS.mjs} +1 -1
  66. package/dist/filter-merge-IpGywvym.mjs +99 -0
  67. package/dist/{generate-D_YmiCNf.mjs → generate-DRTkLlIl.mjs} +2 -2
  68. package/dist/{headers-CNECDE6q.mjs → headers-BbkIF6vA.mjs} +2 -2
  69. package/dist/health-D-Ft6JM6.mjs +22 -0
  70. package/dist/{health-CxQzbJmr.mjs → health-DqbsG-_w.mjs} +115 -55
  71. package/dist/hooks/index.d.mts +2 -2
  72. package/dist/hooks/index.mjs +2 -2
  73. package/dist/idempotency/index.d.mts +31 -7
  74. package/dist/idempotency/index.mjs +155 -98
  75. package/dist/idempotency/redis.d.mts +1 -1
  76. package/dist/idempotency/redis.mjs +48 -11
  77. package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
  78. package/dist/{preloadResources-CjS2OfpU.d.mts → index-C8zVGYsk.d.mts} +37 -38
  79. package/dist/{index-D4u76eQW.d.mts → index-CRoPtISf.d.mts} +23 -73
  80. package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
  81. package/dist/index-JdbZAIsm.d.mts +510 -0
  82. package/dist/{index-DHbyPo5j.d.mts → index-mqaqZNpe.d.mts} +253 -254
  83. package/dist/index.d.mts +8 -8
  84. package/dist/index.mjs +11 -11
  85. package/dist/{init-Y2MlSN9n.mjs → init-B_oUYDXI.mjs} +1 -1
  86. package/dist/integrations/event-gateway.d.mts +8 -3
  87. package/dist/integrations/event-gateway.mjs +4 -4
  88. package/dist/integrations/index.d.mts +3 -3
  89. package/dist/integrations/index.mjs +1 -1
  90. package/dist/integrations/jobs/index.d.mts +1 -1
  91. package/dist/integrations/jobs/index.mjs +18 -5
  92. package/dist/integrations/mcp/index.d.mts +72 -59
  93. package/dist/integrations/mcp/index.mjs +19 -4
  94. package/dist/integrations/mcp/testing.d.mts +2 -2
  95. package/dist/integrations/mcp/testing.mjs +2 -2
  96. package/dist/integrations/streamline.d.mts +78 -136
  97. package/dist/integrations/streamline.mjs +116 -54
  98. package/dist/integrations/webhooks.d.mts +60 -120
  99. package/dist/integrations/webhooks.mjs +36 -80
  100. package/dist/integrations/websocket-pushref-redis.d.mts +1 -1
  101. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  102. package/dist/integrations/websocket-redis.d.mts +1 -1
  103. package/dist/integrations/websocket-redis.mjs +1 -1
  104. package/dist/integrations/websocket.d.mts +3 -3
  105. package/dist/integrations/websocket.mjs +2 -2
  106. package/dist/{interface-DEWNOMza.d.mts → interface-C0395yUN.d.mts} +13 -1
  107. package/dist/{jsonBody-Cq9KYl2Z.mjs → jsonBody-B4YVGcql.mjs} +2 -2
  108. package/dist/{keys-Cmv4cBRa.mjs → keys-B2KtgMLJ.mjs} +7 -18
  109. package/dist/{loadResources-CblF7xt2.mjs → loadResources-Dn4lalw2.mjs} +3 -3
  110. package/dist/{loadResourcesFromEntry-99fIMC3p.mjs → loadResourcesFromEntry-3sLYbuse.mjs} +2 -2
  111. package/dist/logger/index.d.mts +1 -8
  112. package/dist/logger/index.mjs +3 -153
  113. package/dist/logger-DXjfIqjV.mjs +160 -0
  114. package/dist/{mcpPlugin-xF3Gw-HW.mjs → mcpPlugin-C08HalN5.mjs} +433 -170
  115. package/dist/{memory-CpDZ9NPw.mjs → memory-9Cp7611C.mjs} +36 -34
  116. package/dist/{metrics-BaKnq8ag.mjs → metrics-CWI11eRu.mjs} +39 -72
  117. package/dist/middleware/index.d.mts +2 -2
  118. package/dist/middleware/index.mjs +3 -3
  119. package/dist/migrations/index.mjs +2 -2
  120. package/dist/{module-BkQEesNQ.mjs → module-BSvOQC7E.mjs} +8 -8
  121. package/dist/multiTenant-cY0FkDiA.d.mts +104 -0
  122. package/dist/{multipartBody-C92aJ8am.mjs → multipartBody-CXM2a-Dy.mjs} +46 -7
  123. package/dist/{openapi-C3LFRzPq.mjs → openapi-DT_G4VhY.mjs} +48 -10
  124. package/dist/outbox-admin/index.d.mts +3 -3
  125. package/dist/outbox-admin/index.mjs +6 -18
  126. package/dist/{outbox-module-dsCyLxXH.mjs → outbox-module-Bjgzl6tg.mjs} +203 -33
  127. package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
  128. package/dist/permissions/index.d.mts +5 -4
  129. package/dist/permissions/index.mjs +8 -6
  130. package/dist/{permissions-DiHXy8Ck.mjs → permissions-Cm0uYHvd.mjs} +149 -33
  131. package/dist/{pipe-CBVmUJ-j.mjs → pipe-BqeGT6UO.mjs} +2 -2
  132. package/dist/pipeline/index.d.mts +2 -2
  133. package/dist/pipeline/index.mjs +2 -2
  134. package/dist/plan-FVR6LP59.mjs +565 -0
  135. package/dist/{BaseController-DYJRZ0EJ.mjs → plugin-BccET1tL.mjs} +1256 -344
  136. package/dist/plugins/index.d.mts +14 -11
  137. package/dist/plugins/index.mjs +44 -22
  138. package/dist/plugins/response-cache.mjs +8 -14
  139. package/dist/plugins/tracing-entry.mjs +2 -2
  140. package/dist/{pluralize-2_U6QZQg.mjs → pluralize-CVIOcgMF.mjs} +1 -1
  141. package/dist/presets/filesUpload.d.mts +2 -2
  142. package/dist/presets/filesUpload.mjs +5 -5
  143. package/dist/presets/index.d.mts +26 -31
  144. package/dist/presets/index.mjs +4 -4
  145. package/dist/presets/multiTenant.d.mts +2 -107
  146. package/dist/presets/multiTenant.mjs +22 -162
  147. package/dist/presets/search.d.mts +2 -2
  148. package/dist/presets/search.mjs +2 -2
  149. package/dist/{presets-BdlugYTc.mjs → presets-Cpvj6fGO.mjs} +99 -107
  150. package/dist/{projection-Uvgp-EEj.mjs → projection-Ce4aQhQk.mjs} +2 -2
  151. package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
  152. package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
  153. package/dist/{queryCachePlugin-B5F09bYr.mjs → queryCachePlugin-CFWNH8aT.mjs} +12 -14
  154. package/dist/{rateLimitKey-CK-EU2L8.mjs → rateLimitKey-C4O-kPm0.mjs} +1 -1
  155. package/dist/{realtime-FnnD0n3Z.mjs → realtime-DmPE9S54.mjs} +25 -21
  156. package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
  157. package/dist/{redis-Bzi1y3F9.d.mts → redis-vLvtcGy_.d.mts} +13 -24
  158. package/dist/redisShapes-CQksY67q.d.mts +55 -0
  159. package/dist/registry/index.d.mts +9 -4
  160. package/dist/registry/index.mjs +4 -4
  161. package/dist/{registry-D3y8VEJ1.mjs → registry-Bcz9G1bh.mjs} +10 -8
  162. package/dist/{renewingLease-B3VYh5aU.mjs → renewingLease-qODa7KJQ.mjs} +1 -1
  163. package/dist/{replyHelpers-DPHsdw-5.mjs → replyHelpers-CG_VtVgS.mjs} +2 -2
  164. package/dist/{requestContext-cSVKnYPk.mjs → requestContext-Dsu9P1bV.mjs} +1 -1
  165. package/dist/requirement-CbiLdQ1n.d.mts +22 -0
  166. package/dist/requirement-KDdoRcOP.mjs +35 -0
  167. package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
  168. package/dist/resourceRateLimit-dSjVr1pk.mjs +180 -0
  169. package/dist/{rolldown-runtime-DjDuyglE.mjs → rolldown-runtime-D1w9Y1VJ.mjs} +1 -1
  170. package/dist/routeValidator-D36SW8qt.mjs +70 -0
  171. package/dist/{runtimeCapabilities-DSA_dH1_.mjs → runtimeCapabilities-0tccjRlj.mjs} +1 -1
  172. package/dist/{schedules-BktJb3Y3.mjs → schedules-C-OpmHBq.mjs} +46 -37
  173. package/dist/{schemaConverter-BLCSmNbr.mjs → schemaConverter-BORek3O-.mjs} +2 -2
  174. package/dist/{schemaIR-K16Bb5BX.mjs → schemaIR-C7Vbp71I.mjs} +2 -2
  175. package/dist/schemas/index.d.mts +10 -0
  176. package/dist/schemas/index.mjs +8 -3
  177. package/dist/scim/index.mjs +2 -2
  178. package/dist/scope/index.d.mts +2 -2
  179. package/dist/scope/index.mjs +6 -6
  180. package/dist/{scope-jSxuBTFM.mjs → scope-DQthe88b.mjs} +4 -4
  181. package/dist/shutdown-MqA81z_P.mjs +59 -0
  182. package/dist/{simpleEqualityMatcher-BiOnyflP.mjs → simpleEqualityMatcher-auW8QjXN.mjs} +1 -1
  183. package/dist/{sse-CH7Slxc1.mjs → sse-CYzQBVFe.mjs} +11 -15
  184. package/dist/{sseStream-CN-Lh1Tu.mjs → sseStream-B5_Afiqn.mjs} +2 -2
  185. package/dist/{store-helpers-9DX9-1j_.mjs → store-helpers-BOzk-CuX.mjs} +1 -1
  186. package/dist/{streaming-dvppnxsr.mjs → streaming-DjTQhZrN.mjs} +1 -1
  187. package/dist/subscriberIdentity-CW39uA8G.mjs +28 -0
  188. package/dist/tenancy--ed9eH_z.mjs +43 -0
  189. package/dist/tenantPreparation-BKon6Yox.mjs +67 -0
  190. package/dist/testing/cleanupStoreContract.mjs +1 -1
  191. package/dist/testing/index.d.mts +193 -175
  192. package/dist/testing/index.mjs +286 -212
  193. package/dist/testing/outboxStoreContract.mjs +137 -2
  194. package/dist/testing/requiredPorts.d.mts +17 -0
  195. package/dist/testing/requiredPorts.mjs +65 -0
  196. package/dist/testing/storageContract.mjs +1 -1
  197. package/dist/timing-qczZ0YC-.mjs +46 -0
  198. package/dist/{transactionContext-DCWMI6hV.mjs → transactionContext-DjFkrNG6.mjs} +1 -1
  199. package/dist/{typeGuards-D7tHFdH6.mjs → typeGuards-CySF12G-.mjs} +1 -1
  200. package/dist/types/index.d.mts +4 -4
  201. package/dist/types/index.mjs +1 -1
  202. package/dist/types/storage.mjs +1 -1
  203. package/dist/{types-CWQn9-IC.d.mts → types-B4Aq4Sdj.d.mts} +22 -9
  204. package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
  205. package/dist/{types-CDy3-zw1.mjs → types-Bk9NOgOC.mjs} +4 -4
  206. package/dist/usage/index.d.mts +2 -3
  207. package/dist/usage/index.mjs +5 -5
  208. package/dist/{userHelpers-DDMOZ_Pm.mjs → userHelpers-aklawRaK.mjs} +1 -1
  209. package/dist/utils/index.d.mts +84 -223
  210. package/dist/utils/index.mjs +13 -12
  211. package/dist/{utils-B-zj_b__.mjs → utils-ec1oTo1n.mjs} +315 -404
  212. package/dist/{validate-R0G_JrnK.mjs → validate-9yzHC1e2.mjs} +6 -14
  213. package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
  214. package/dist/{versioning-DuVWcu-F.mjs → versioning-fhhWHV74.mjs} +4 -4
  215. package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
  216. package/dist/{workScope-BhsWde4k.mjs → workScope-zpPyge4t.mjs} +2 -2
  217. package/package.json +578 -574
  218. package/skills/arc/SKILL.md +13 -4
  219. package/skills/arc/references/auth.md +8 -5
  220. package/skills/arc/references/integrations.md +1 -1
  221. package/skills/arc/references/mcp.md +8 -6
  222. package/skills/arc/references/multi-tenancy.md +19 -14
  223. package/skills/arc/references/production.md +27 -10
  224. package/dist/actionPermissions-DPwPWPOV.mjs +0 -350
  225. package/dist/index-CFfLKMH4.d.mts +0 -290
  226. package/dist/interface-BIpgzbZl.mjs +0 -17
  227. package/dist/redis-stream-BPKscsTB.d.mts +0 -260
  228. package/dist/registerRoute-DRsSHPSM.mjs +0 -364
  229. package/dist/sync/changelog.d.mts +0 -3
  230. package/dist/sync/changelog.mjs +0 -3
@@ -1,7 +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-CxrV1LmG.mjs";
3
+ import { c as DataPolicy, l as PermissionCheck, s as AuthorizationDecision, u as PermissionContext } from "./base-CZyixEQR.mjs";
4
4
  import { r as CacheStore, t as CacheLogger } from "./interface-BOk3YnTz.mjs";
5
+ import "./resourceRateLimit-Wf6d6FL9.mjs";
5
6
  import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
6
7
  //#region src/permissions/agent.d.ts
7
8
  /**
@@ -194,16 +195,6 @@ declare function normalizeToDecision(result: PermissionCheckReturn): Authorizati
194
195
  * nuance lives in {@link evaluateAndApplyPermission}, not here.
195
196
  */
196
197
  declare function evaluatePermissionDecision(check: PermissionCheck, context: PermissionContext): Promise<AuthorizationDecision>;
197
- /**
198
- * Minimal shape of a Fastify request that can receive permission side-effects.
199
- * We avoid depending on the full augmented `FastifyRequest` type here because
200
- * `_policyFilters` / `scope` are declared via ambient module augmentation in
201
- * multiple places and the unaugmented interface is what the core routers see.
202
- */
203
- type RequestSink = FastifyRequest & {
204
- _policyFilters?: Record<string, unknown>;
205
- scope?: RequestScope;
206
- };
207
198
  /**
208
199
  * Apply an allowed {@link AuthorizationDecision} to a Fastify request — conjoins
209
200
  * the decision's row-level `policy` into `_policyFilters` and conditionally
@@ -222,7 +213,7 @@ type RequestSink = FastifyRequest & {
222
213
  * This is the enforcement point (PEP) — the ONE place scope + data policy are
223
214
  * installed (and the obligation seam lives).
224
215
  */
225
- declare function applyAuthorizationDecision(decision: AuthorizationDecision, request: RequestSink): void;
216
+ declare function applyAuthorizationDecision(decision: AuthorizationDecision, req: FastifyRequest): void;
226
217
  //#endregion
227
218
  //#region src/permissions/context.d.ts
228
219
  /**
@@ -251,17 +242,72 @@ declare function allow(extra?: Omit<AuthorizationDecision, "effect">): Authoriza
251
242
  */
252
243
  declare function deny(reason?: string): AuthorizationDecision;
253
244
  /**
254
- * Allow public access (no authentication required).
245
+ * The row policy an `allowPublic` gate applies to the callers it admits: a
246
+ * filter, or a function of the request that returns one.
247
+ *
248
+ * The function form is the scope-aware one — it sees the caller, so anonymous
249
+ * visitors, the row's author and staff can each get a different filter from ONE
250
+ * gate. Return `{}` to admit a caller unrestricted (e.g. staff); returning
251
+ * nothing is treated as a bug, not as "no filter" (see {@link allowPublic}).
252
+ */
253
+ type PublicPolicy<TDoc = Record<string, unknown>> = DataPolicy | ((ctx: PermissionContext<TDoc>) => DataPolicy | Promise<DataPolicy>);
254
+ /** Options for {@link allowPublic}. */
255
+ interface AllowPublicOptions<TDoc = Record<string, unknown>> {
256
+ /**
257
+ * Narrow what anyone admitted by this gate can read or write. Enforced where
258
+ * every other row policy is: ANDed into the repository query for `list`, into
259
+ * the compound lookup for `get` / `update` / `delete`, into aggregations, and
260
+ * per event on realtime feeds. A caller cannot widen it with a query
261
+ * parameter — `?status=hidden` is conjoined with the policy, not substituted
262
+ * for it.
263
+ */
264
+ policy?: PublicPolicy<TDoc>;
265
+ }
266
+ /**
267
+ * Allow public access (no authentication required) — optionally row-filtered.
268
+ *
269
+ * Without options, anyone passes and sees everything the query asks for.
270
+ *
271
+ * With `policy`, anyone still passes, but only the rows the policy admits are
272
+ * readable (or writable). This is the declarative form of a check that returns
273
+ * `allow({ policy })`, and it exists because the hand-written form has a trap:
274
+ * a check function is treated as PROTECTED unless it carries `_isPublic`, so a
275
+ * custom "public, but only published rows" check that forgets to set the flag
276
+ * answers every anonymous visitor with a 401 — the public page silently
277
+ * becomes a login wall. `allowPublic({ policy })` sets it for you.
278
+ *
279
+ * Fail-closed on both ends:
280
+ * - a STATIC policy must be a non-empty object — `{}` filters nothing and is
281
+ * almost certainly a mistake, so it throws at definition time (use
282
+ * `allowPublic()` for an unrestricted gate);
283
+ * - a RESOLVER that returns anything but an object throws per request, which
284
+ * arc answers as a 403 for everyone. A forgotten branch that falls off the
285
+ * end of the function must not quietly mean "no filter". Return `{}` when a
286
+ * caller genuinely should be unrestricted.
287
+ *
288
+ * Composing: inside `anyOf`, the FIRST granting branch wins, and a public
289
+ * branch grants everyone — so `anyOf(allowPublic({ policy }), requireRoles("admin"))`
290
+ * filters admins too. Put the privileged branch first, or use the resolver
291
+ * form and return `{}` for staff.
255
292
  *
256
293
  * @example
257
294
  * ```typescript
258
- * permissions: {
259
- * list: allowPublic(),
260
- * get: allowPublic(),
261
- * }
295
+ * // Strangers see only published reviews, whatever filter they send.
296
+ * list: allowPublic({ policy: { status: { $in: ["published", "flagged"] } } }),
297
+ *
298
+ * // Scope-aware: the author also sees their own pending review; staff see all.
299
+ * list: allowPublic({
300
+ * policy: (ctx) => {
301
+ * const scope = scopeOf(ctx);
302
+ * if (isElevated(scope)) return {};
303
+ * const visible = { status: { $in: ["published", "flagged"] } };
304
+ * const userId = getUserId(scope);
305
+ * return userId ? { $or: [visible, { authorId: userId }] } : visible;
306
+ * },
307
+ * }),
262
308
  * ```
263
309
  */
264
- declare function allowPublic(): PermissionCheck;
310
+ declare function allowPublic<TDoc = Record<string, unknown>>(options?: AllowPublicOptions<TDoc>): PermissionCheck<TDoc>;
265
311
  /**
266
312
  * Require authentication (any authenticated user).
267
313
  *
@@ -549,12 +595,23 @@ declare function createDynamicPermissionMatrix(config: DynamicPermissionMatrixCo
549
595
  * aren't, so a consumer that holds the caller's scope (a FE that knows the
550
596
  * active branch's role) can decide it client-side — the piece a flat `roles`
551
597
  * requirement could not express.
598
+ * - `member` — any MEMBER of the caller's active organization passes
599
+ * (`requireOrgMembership()`), or a holder of one of `roles` when it is an `anyOf`
600
+ * with role branches. Membership is a fact the client holds, so it is decidable.
552
601
  * - `authenticated` — the check reads request-time facts (custom auth, service
553
602
  * scope, ownership, grants) that no static analysis can decide; the definitive
554
603
  * answer is computed per request. Treat as "server decides".
555
604
  */
556
605
  type PermissionRequirement = {
557
606
  readonly kind: "public";
607
+ /**
608
+ * `true` for `allowPublic({ policy })`: anyone passes the gate, but a row
609
+ * policy narrows what they can read or write. Absent for a plain
610
+ * `allowPublic()`, which exposes every row the query asks for. The access
611
+ * DECISION is the same (allow); the exposure is not, and an audit of the
612
+ * public surface needs to tell them apart.
613
+ */
614
+ readonly rowFiltered?: true;
558
615
  } | {
559
616
  readonly kind: "roles";
560
617
  readonly roles: readonly string[];
@@ -573,6 +630,10 @@ type PermissionRequirement = {
573
630
  readonly roles?: readonly string[];
574
631
  /** See `roles.conditional` — the composite also has an opaque/contradictory branch. */
575
632
  readonly conditional?: boolean;
633
+ } | {
634
+ readonly kind: "member";
635
+ /** Roles that ALSO grant without membership (the role branches of an `anyOf`). */
636
+ readonly roles?: readonly string[];
576
637
  } | {
577
638
  readonly kind: "authenticated";
578
639
  } |
@@ -620,6 +681,8 @@ declare function explainAccess(check: PermissionCheck, principal?: {
620
681
  orgRoles?: readonly string[];
621
682
  /** The caller's scope-context values (e.g. `{ branchRole: "head_office" }`) — supply to decide a `scoped` gate. */
622
683
  scope?: Readonly<Record<string, string | undefined>>;
684
+ /** Whether the caller is a member of the active organization — supply to decide a `member` gate. */
685
+ member?: boolean;
623
686
  }): AccessExplanation;
624
687
  /**
625
688
  * Introspect a whole permission map (`{ list, get, create, ... }` or any
@@ -922,7 +985,7 @@ declare function requireOrgInScope<TDoc = Record<string, unknown>>(target: strin
922
985
  */
923
986
  declare function requireTeamMembership<TDoc = Record<string, unknown>>(): PermissionCheck<TDoc>;
924
987
  declare namespace presets_d_exports {
925
- export { adminOnly, authenticated, fullPublic, ownerWithAdminBypass, permissionMatrix, publicRead, publicReadAdminWrite, readOnly };
988
+ export { PermissionOverrides, adminOnly, authenticated, fullPublic, ownerWithAdminBypass, permissionMatrix, publicRead, publicReadAdminWrite, readOnly };
926
989
  }
927
990
  /**
928
991
  * ResourcePermissions shape — matches the type in types/index.ts
@@ -1017,7 +1080,7 @@ declare function readOnly<TDoc = Record<string, unknown>>(overrides?: Permission
1017
1080
  * A CLIENT MUST treat an unrecognised type as DENIED, never as permitted — the
1018
1081
  * next type added here will otherwise read as "allowed" on every older client.
1019
1082
  */
1020
- type PermissionEntryType = "public" | "authenticated" | "roles" | "scoped" | "denied";
1083
+ type PermissionEntryType = "public" | "authenticated" | "roles" | "scoped" | "member" | "denied";
1021
1084
  interface PermissionEntry {
1022
1085
  type: PermissionEntryType;
1023
1086
  roles: string[];
@@ -1095,4 +1158,4 @@ declare function introspectModule(mod: Record<string, unknown>): Record<string,
1095
1158
  declare function introspectRegistry(registry: PermissionMatrixRegistry): Record<string, Record<string, PermissionEntry>>;
1096
1159
  declare function buildPermissionMatrix(options?: PermissionMatrixOptions): PermissionMatrix;
1097
1160
  //#endregion
1098
- export { requireAuth as $, RequireGrantOptions as A, ConnectEventsOptions as B, requireServiceScope as C, GRANT_MODES as D, createRoleHierarchy as E, PermissionRequirement as F, createOrgPermissions as G, DynamicPermissionMatrixConfig as H, collectPublicSurface as I, allowPublic as J, allOf as K, describePermission as L, requireGrant as M, conjoinPolicyFilters as N, GrantMode as O, AccessExplanation as P, not as Q, describePermissionMap as R, requireScopeContext as S, RoleHierarchy as T, PermissionEventBus as U, DynamicPermissionMatrix as V, createDynamicPermissionMatrix as W, deny as X, anyOf as Y, denyAll as Z, publicReadAdminWrite as _, PermissionMatrixRegistry as a, scopeOf as at, requireOrgMembership as b, introspectModule as c, evaluatePermissionDecision as ct, authenticated as d, RequireMandateOptions as dt, requireOwnership as et, fullPublic as f, requireAgentScope as ft, publicRead as g, presets_d_exports as h, PermissionMatrixOptions as i, when as it, modeSatisfies as j, GrantResolution as k, introspectRegistry as l, normalizeToDecision as lt, permissionMatrix as m, requireMandate as mt, PermissionEntryType as n, requireRoles as nt, buildPermissionMatrix as o, PermissionCheckReturn as ot, ownerWithAdminBypass as p, requireDPoP as pt, allow as q, PermissionMatrix as r, roles as rt, introspectCheck as s, applyAuthorizationDecision as st, PermissionEntry as t, requirePlatformRole as tt, adminOnly as u, RequireAgentScopeOptions as ut, readOnly as v, requireTeamMembership as w, requireOrgRole as x, requireOrgInScope as y, explainAccess as z };
1161
+ export { deny as $, GrantResolution as A, explainAccess as B, requireScopeContext as C, createRoleHierarchy as D, RoleHierarchy as E, AccessExplanation as F, createDynamicPermissionMatrix as G, DynamicPermissionMatrix as H, PermissionRequirement as I, PublicPolicy as J, createOrgPermissions as K, collectPublicSurface as L, modeSatisfies as M, requireGrant as N, GRANT_MODES as O, conjoinPolicyFilters as P, anyOf as Q, describePermission as R, requireOrgRole as S, requireTeamMembership as T, DynamicPermissionMatrixConfig as U, ConnectEventsOptions as V, PermissionEventBus as W, allow as X, allOf as Y, allowPublic as Z, publicRead as _, requireMandate as _t, PermissionMatrixRegistry as a, requireRoles as at, requireOrgInScope as b, introspectModule as c, scopeOf as ct, adminOnly as d, evaluatePermissionDecision as dt, denyAll as et, authenticated as f, normalizeToDecision as ft, presets_d_exports as g, requireDPoP as gt, permissionMatrix as h, requireAgentScope as ht, PermissionMatrixOptions as i, requirePlatformRole as it, RequireGrantOptions as j, GrantMode as k, introspectRegistry as l, PermissionCheckReturn as lt, ownerWithAdminBypass as m, RequireMandateOptions as mt, PermissionEntryType as n, requireAuth as nt, buildPermissionMatrix as o, roles as ot, fullPublic as p, RequireAgentScopeOptions as pt, AllowPublicOptions as q, PermissionMatrix as r, requireOwnership as rt, introspectCheck as s, when as st, PermissionEntry as t, not as tt, PermissionOverrides as u, applyAuthorizationDecision as ut, publicReadAdminWrite as v, requireServiceScope as w, requireOrgMembership as x, readOnly as y, describePermissionMap as z };
@@ -1,16 +1,16 @@
1
1
 
2
- import { It as Authenticator } from "./index-DHbyPo5j.mjs";
2
+ import { Mt as Authenticator } from "./index-mqaqZNpe.mjs";
3
3
  import { r as CacheStore } from "./interface-BOk3YnTz.mjs";
4
- import { n as ElevationOptions } from "./elevation-BXCfVcNG.mjs";
5
- import { a as EventTransport } from "./EventTransport-CbUKDzZZ.mjs";
4
+ import { n as ElevationOptions } from "./elevation-BW2J3tNj.mjs";
5
+ import { a as EventTransport } from "./EventTransport-CiicKz2Z.mjs";
6
6
  import { t as ExternalOpenApiPaths } from "./externalPaths-CmGOxOtD.mjs";
7
- import { r as QueryCachePluginOptions } from "./queryCachePlugin-BzqxconG.mjs";
7
+ import { r as QueryCachePluginOptions } from "./queryCachePlugin-C2lZjTxk.mjs";
8
8
  import { t as ErrorHandlerOptions } from "./errorHandler--4rSMMvq.mjs";
9
- import { l as ResourceLike, m as SchedulesPluginOptions, n as ArcModuleInput, v as HealthOptions } from "./types-DfVDvkdP.mjs";
10
- import "./index-CFfLKMH4.mjs";
11
- import { t as EventPluginOptions } from "./eventPlugin-B52abJ8W.mjs";
12
- import { b as GracefulShutdownOptions, g as CachingOptions, o as MetricsOptions, p as SSEOptions, t as VersioningOptions, u as RealtimeOptions } from "./versioning-D6JIK8Tk.mjs";
13
- import { r as IdempotencyStore } from "./interface-DEWNOMza.mjs";
9
+ import { S as SchedulesPluginOptions, T as HealthOptions, _ as ResourceLike, o as ArcPorts, r as ArcModuleInput } from "./types-BJ-2XqVF.mjs";
10
+ import { H as ModuleGraphOptions } from "./index-JdbZAIsm.mjs";
11
+ import { t as EventPluginOptions } from "./eventPlugin-BtmA4-3P.mjs";
12
+ import { a as MetricsOptions, c as RealtimeOptions, f as CachingOptions, h as GracefulShutdownOptions, t as VersioningOptions, u as SSEOptions } from "./versioning-Bsb51gGT.mjs";
13
+ import { r as IdempotencyStore } from "./interface-C0395yUN.mjs";
14
14
  import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
15
15
  //#region src/factory/types/assets.d.ts
16
16
  /**
@@ -399,6 +399,8 @@ interface RateLimitPlanConfig {
399
399
  }
400
400
  //#endregion
401
401
  //#region src/factory/types/app-options.d.ts
402
+ /** Releases what `beforeBoot` acquired — see `CreateAppOptions.beforeBoot`. */
403
+ type BootDisposer = () => void | Promise<void>;
402
404
  /**
403
405
  * Configuration for `createApp()`.
404
406
  *
@@ -425,8 +427,9 @@ interface CreateAppOptions {
425
427
  */
426
428
  mountRoutes?: boolean;
427
429
  /**
428
- * Runtime profile for store backends.
429
- * - 'memory' (default): Uses in-memory stores. Suitable for single-instance deployments.
430
+ * Runtime profile for store backends — the deployment's TOPOLOGY. REQUIRED under
431
+ * `preset: 'production'` (boot fails without it); defaults to 'memory' elsewhere.
432
+ * - 'memory': Uses in-memory stores. Correct for exactly ONE instance.
430
433
  * - 'distributed': Requires durable adapters for events, and for any enabled
431
434
  * shared subsystems such as caching/queryCache/rate limiting.
432
435
  * Idempotency remains per-resource opt-in: memory-backed stores are rejected,
@@ -808,7 +811,7 @@ interface CreateAppOptions {
808
811
  * - `'number'` — LOSSY above `Number.MAX_SAFE_INTEGER` (2^53-1). Only for
809
812
  * an audited, bounded range.
810
813
  */
811
- serializeBigInt?: boolean | "number" | "string";
814
+ serializeBigInt?: false | "number" | "string";
812
815
  /**
813
816
  * Domain modules — one entry per self-contained domain package.
814
817
  *
@@ -819,6 +822,19 @@ interface CreateAppOptions {
819
822
  * always before the app-level entry for that phase. See [[modules]].
820
823
  */
821
824
  modules?: ReadonlyArray<ArcModuleInput>;
825
+ /**
826
+ * Host collaborators modules declare in `requires.ports` (a connection, an outbox, a
827
+ * calendar…). Every `'required'` port of every active module is checked before any module
828
+ * boots — all gaps in one error — and each module's setup phases receive only the ports it
829
+ * declared, as `context.ports`. Nothing is defaulted.
830
+ */
831
+ ports?: ArcPorts;
832
+ /**
833
+ * The module graph check. `events: 'strict'` fails boot when an event has two owners, is
834
+ * published outside its module's namespace, or is consumed with no active publisher and no
835
+ * `externalEvents` entry. Default `'off'`. The graph is always on `fastify.arc.moduleGraph`.
836
+ */
837
+ moduleGraph?: ModuleGraphOptions;
822
838
  /**
823
839
  * Resources to register. An ARRAY is resolved at module import, so every
824
840
  * adapter must be constructible synchronously. A FACTORY (sync or async,
@@ -939,9 +955,15 @@ interface CreateAppOptions {
939
955
  * ```
940
956
  *
941
957
  * Runs after option validation (config bugs fail fast without touching
942
- * the DB). Cleanup stays host-owned — pair with `onClose`.
958
+ * the DB). Return a disposer to hand cleanup to arc: it runs once, on
959
+ * `app.close()` after every plugin's `onClose`, AND on a boot that fails —
960
+ * including one that fails before Fastify exists, where no `onClose` can.
961
+ *
962
+ * ```ts
963
+ * beforeBoot: async () => { await mongoose.connect(uri); return () => mongoose.disconnect(); },
964
+ * ```
943
965
  */
944
- beforeBoot?: () => void | Promise<void>;
966
+ beforeBoot?: () => void | BootDisposer | Promise<void | BootDisposer>;
945
967
  /**
946
968
  * Custom plugin registration — runs after Arc core (security, auth, events)
947
969
  * but before `bootstrap` and `resources`.
@@ -987,27 +1009,4 @@ interface CreateAppOptions {
987
1009
  onClose?: (fastify: FastifyInstance) => void | Promise<void>;
988
1010
  }
989
1011
  //#endregion
990
- //#region src/factory/preloadResources.d.ts
991
- /** Eager glob result: `{ '/path/to/file.ts': resourceModule }` */
992
- type EagerGlobResult = Record<string, unknown>;
993
- /** Lazy glob result: `{ '/path/to/file.ts': () => Promise<unknown> }` */
994
- type LazyGlobResult = Record<string, () => Promise<unknown>>;
995
- /**
996
- * Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
997
- *
998
- * Accepts either:
999
- * - `{ import: 'default' }` form: values are the resource directly
1000
- * - default form: values are the full module — picks first export with `toPlugin()`
1001
- *
1002
- * Throws if any module doesn't yield a valid `ResourceLike`.
1003
- */
1004
- declare function preloadResources(globResult: EagerGlobResult): ResourceLike[];
1005
- /**
1006
- * Normalize a lazy `import.meta.glob` result into a `Promise<ResourceLike[]>`.
1007
- *
1008
- * Use this when resources depend on prior bootstrap (e.g., engine init) and
1009
- * cannot be evaluated at import time of the preload file.
1010
- */
1011
- declare function preloadResourcesAsync(globResult: LazyGlobResult): Promise<ResourceLike[]>;
1012
- //#endregion
1013
- export { RawBodyOptions as a, BetterAuthOption as c, JwtAuthOption as d, MultipartOptions as i, CustomAuthenticatorOption as l, preloadResourcesAsync as n, UnderPressureOptions as o, CreateAppOptions as r, AuthOption as s, preloadResources as t, CustomPluginAuthOption as u };
1012
+ export { UnderPressureOptions as a, CustomAuthenticatorOption as c, RawBodyOptions as i, CustomPluginAuthOption as l, CreateAppOptions as n, AuthOption as o, MultipartOptions as r, BetterAuthOption as s, BootDisposer as t, JwtAuthOption as u };
@@ -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-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";
3
+ import { l as PermissionCheck, t as AnyRecord } from "./base-CZyixEQR.mjs";
4
+ import { A as RequestWithExtras, Dt as RouteMcpConfig, F as ResourceDefinition, I as CrudController, In as IControllerResponse, L as ResourceConfig, Ln as IRequestContext, O as FastifyWithDecorators, St as ActionDefinition, X as RouteSchemaOptions, Z as ArcFieldRule, g as RequestContext, ot as AggregationConfig, v as CrudRouterOptions } from "./index-mqaqZNpe.mjs";
5
+ import "./fastify-augmentation-DhUJ-mvo.mjs";
6
6
  import { Filter } from "@classytic/repo-core/filter";
7
7
  import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
8
8
  import { z } from "zod";
@@ -42,6 +42,8 @@ declare const DEFAULT_ID_FIELD: "_id";
42
42
  declare const DEFAULT_TENANT_FIELD: "organizationId";
43
43
  /** Default HTTP method for update routes */
44
44
  declare const DEFAULT_UPDATE_METHOD: "PATCH";
45
+ /** Default version field under `concurrency: {}` (optimistic concurrency) */
46
+ declare const DEFAULT_VERSION_FIELD: "__v";
45
47
  /** System-managed fields that cannot be set via request body */
46
48
  declare const SYSTEM_FIELDS: readonly ["_id", "__v", "createdAt", "updatedAt", "deletedAt"];
47
49
  /** Maximum regex pattern length (ReDoS mitigation) */
@@ -95,9 +97,8 @@ declare function defineAggregation(config: AggregationConfig): AggregationConfig
95
97
  */
96
98
  declare function createCrudRouter<TDoc = unknown>(fastify: FastifyWithDecorators, controller: CrudController<TDoc> | undefined, options?: CrudRouterOptions): void;
97
99
  /**
98
- * Build a permission middleware from a PermissionCheck — useful when hosts
99
- * register their own routes outside the resource system but still want to
100
- * evaluate permissions through the shared applicator.
100
+ * Build a permission middleware from a PermissionCheck, for host routes
101
+ * registered outside the resource system.
101
102
  */
102
103
  declare function createPermissionMiddleware(permission: PermissionCheck, resourceName: string, action: string): RouteHandlerMethod | null;
103
104
  //#endregion
@@ -123,6 +124,8 @@ interface DefineActionConfig<TSchema extends z.ZodTypeAny | undefined = undefine
123
124
  id?: boolean;
124
125
  /** MCP tool generation flag — `false` to skip, object for explicit overrides. */
125
126
  mcp?: boolean | RouteMcpConfig;
127
+ /** `{ required: true }`: a call of this action needs an idempotency key. See `ActionDefinition`. */
128
+ idempotency?: ActionDefinition["idempotency"];
126
129
  /**
127
130
  * Typed handler. `data` is inferred from `schema` — declare both and
128
131
  * the compiler catches `data.stagId` typos at the use site.
@@ -266,7 +269,7 @@ type VariantsResult<TDoc, V extends VariantsMap<TDoc>> = { [K in keyof V]: Resou
266
269
  * @returns A record where each key from `variants` maps to a real
267
270
  * `ResourceDefinition` ready for `.toPlugin()` registration.
268
271
  */
269
- declare function defineResourceVariants<TDoc extends AnyRecord = AnyRecord, V extends VariantsMap<TDoc> = VariantsMap<TDoc>>(base: Omit<ResourceConfig<TDoc>, "name" | "prefix">, variants: V): VariantsResult<TDoc, V>;
272
+ declare function defineResourceVariants<TDoc extends object = AnyRecord, V extends VariantsMap<TDoc> = VariantsMap<TDoc>>(base: Omit<ResourceConfig<TDoc>, "name" | "prefix">, variants: V): VariantsResult<TDoc, V>;
270
273
  //#endregion
271
274
  //#region src/core/entityHelpers.d.ts
272
275
  /**
@@ -298,58 +301,29 @@ declare function getEntityQuery(req: RequestWithExtras): Record<string, string>;
298
301
  //#endregion
299
302
  //#region src/core/fastifyAdapter.d.ts
300
303
  /**
301
- * Project `FastifyRequest` into the curated `IRequestContext` shape that
302
- * arc's controllers receive. This is a developer-facing facade, not a
303
- * portability boundary — arc is Fastify-only. The projection lifts the
304
- * fields tenant-scoped controllers reach for (`organizationId`,
305
- * `teamId`, `scope`, `context`, server accessor) onto a flat, typed
306
- * surface so handler code doesn't have to dig through Fastify's
307
- * decorator surface or `req.metadata._scope` internals.
304
+ * Project `FastifyRequest` into the `IRequestContext` controllers receive,
305
+ * lifting scope, context, and a server accessor onto a flat, typed surface.
308
306
  */
309
307
  declare function createRequestContext(req: FastifyRequest): IRequestContext;
310
308
  /**
311
- * Get typed auth context from an IRequestContext.
312
- * Use this in controller overrides to access request context.
313
- *
314
- * For org scope, use `getControllerScope(req)` instead.
309
+ * Typed auth context from an IRequestContext, for controller overrides.
310
+ * For org scope, use `getControllerScope(req)`.
315
311
  */
316
312
  declare function getControllerContext(req: IRequestContext): RequestContext;
317
- /**
318
- * Get request scope from an IRequestContext.
319
- * Returns the RequestScope set by auth adapters.
320
- */
313
+ /** The RequestScope set by auth adapters (`PUBLIC_SCOPE` when absent). */
321
314
  declare function getControllerScope(req: IRequestContext): RequestScope;
322
315
  /**
323
- * Send a controller's `IControllerResponse` through Fastify's reply.
324
- *
325
- * The `IControllerResponse<T>` envelope is arc's internal pipeline
326
- * contract — it's how custom `status`, `meta`, `headers`, and field
327
- * permissions thread from a handler through interceptors to the wire
328
- * without each step having to touch `reply` directly. Not a portability
329
- * abstraction (arc is Fastify-only); a pipeline-internal one.
316
+ * Send a controller's `IControllerResponse` envelope (status, meta, headers)
317
+ * through Fastify's reply, applying field masks and field read permissions.
330
318
  *
331
- * **Auto-envelope of bare returns.** Custom route handlers are
332
- * expected to return the envelope shape so this function can apply
333
- * field permissions, attach `fieldCaps`, and flatten paginated lists.
334
- * A handler that returns raw `T` (array, plain object, primitive) used
335
- * to silently produce a broken response — `response.data` was
336
- * `undefined`, the body sent was `undefined`, and any declared
337
- * `fields:` permission map was bypassed (the leak shape mentora
338
- * flagged). 2.17 detects bare returns and wraps them into
339
- * `{ data: response, status: 200 }` before the field-permission
340
- * pipeline runs, so `fields:` applies to ALL custom routes whether the
341
- * handler envelopes its return value or not. The envelope shape is
342
- * still the canonical contract — auto-wrapping is a safety net, not
343
- * an invitation to drop the envelope.
319
+ * A bare return (no `data` key) is wrapped as `{ data, status: 200 }` so
320
+ * `fields:` permissions still apply — otherwise restricted fields would leak.
321
+ * The envelope remains the canonical contract.
344
322
  */
345
323
  declare function sendControllerResponse<T>(reply: FastifyReply, response: IControllerResponse<T>, request?: FastifyRequest): void;
346
324
  /**
347
- * Bridge an `IController` method (`(ctx: IRequestContext) => Promise<IControllerResponse<T>>`)
348
- * into a Fastify route handler. Translates between arc's curated request
349
- * context surface and Fastify's request/reply, and routes the envelope
350
- * through `sendControllerResponse` so the pipeline applies field
351
- * permissions, status, and meta uniformly. Internal plumbing, not a
352
- * portability layer — arc is Fastify-only.
325
+ * Bridge an `IController` method into a Fastify route handler, sending the
326
+ * envelope through `sendControllerResponse`.
353
327
  *
354
328
  * @example
355
329
  * ```typescript
@@ -359,30 +333,6 @@ declare function sendControllerResponse<T>(reply: FastifyReply, response: IContr
359
333
  * ```
360
334
  */
361
335
  declare function createFastifyHandler<T>(controllerMethod: (req: IRequestContext) => Promise<IControllerResponse<T>>): (req: FastifyRequest, reply: FastifyReply) => Promise<FastifyReply>;
362
- /**
363
- * Create Fastify adapters for all CRUD methods of an IController
364
- *
365
- * Returns Fastify-compatible handlers for each CRUD operation
366
- *
367
- * @example
368
- * ```typescript
369
- * const controller = new BaseController(repository);
370
- * const handlers = createCrudHandlers(controller);
371
- *
372
- * fastify.get('/', handlers.list);
373
- * fastify.get('/:id', handlers.get);
374
- * fastify.post('/', handlers.create);
375
- * fastify.patch('/:id', handlers.update);
376
- * fastify.delete('/:id', handlers.delete);
377
- * ```
378
- */
379
- declare function createCrudHandlers<TDoc>(controller: IController<TDoc>): {
380
- list: (req: FastifyRequest, reply: FastifyReply) => Promise<FastifyReply>;
381
- get: (req: FastifyRequest, reply: FastifyReply) => Promise<FastifyReply>;
382
- create: (req: FastifyRequest, reply: FastifyReply) => Promise<FastifyReply>;
383
- update: (req: FastifyRequest, reply: FastifyReply) => Promise<FastifyReply>;
384
- delete: (req: FastifyRequest, reply: FastifyReply) => Promise<FastifyReply>;
385
- };
386
336
  //#endregion
387
337
  //#region src/core/fieldRulePredicates.d.ts
388
338
  /**
@@ -446,4 +396,4 @@ declare function formatValidationErrors(resourceName: string, result: Validation
446
396
  */
447
397
  declare function assertValidConfig(config: ResourceConfig, options?: ValidateOptions): void;
448
398
  //#endregion
449
- export { CRUD_OPERATIONS as A, HookOperation as B, SeamedResourceConfig as C, createCrudRouter as D, defineAction as E, DEFAULT_SORT as F, MUTATION_OPERATIONS as G, MAX_FILTER_DEPTH as H, DEFAULT_TENANT_FIELD as I, SYSTEM_FIELDS as J, MutationOperation as K, DEFAULT_UPDATE_METHOD as L, DEFAULT_ID_FIELD as M, DEFAULT_LIMIT as N, createPermissionMiddleware as O, DEFAULT_MAX_LIMIT as P, HOOK_OPERATIONS as R, ResourceSeams as S, DefineActionConfig as T, MAX_REGEX_LENGTH as U, HookPhase as V, MAX_SEARCH_LENGTH as W, getEntityId as _, formatValidationErrors as a, defineResourceVariants as b, nativePolicyFilter as c, createCrudHandlers as d, createFastifyHandler as f, sendControllerResponse as g, getControllerScope as h, assertValidConfig as i, CrudOperation as j, defineAggregation as k, collectReadBlockedFields as l, getControllerContext as m, ValidateOptions as n, validateResourceConfig as o, createRequestContext as p, RESERVED_QUERY_PARAMS as q, ValidationResult as r, NativePolicyFilter as s, ConfigError as t, isFieldReadable as u, getEntityIdField as v, mergeResourceConfig as w, AdapterLike as x, getEntityQuery as y, HOOK_PHASES as z };
399
+ export { createPermissionMiddleware as A, DEFAULT_VERSION_FIELD as B, AdapterLike as C, DefineActionConfig as D, mergeResourceConfig as E, DEFAULT_LIMIT as F, MAX_FILTER_DEPTH as G, HOOK_PHASES as H, DEFAULT_MAX_LIMIT as I, MUTATION_OPERATIONS as J, MAX_REGEX_LENGTH as K, DEFAULT_SORT as L, CRUD_OPERATIONS as M, CrudOperation as N, defineAction as O, DEFAULT_ID_FIELD as P, DEFAULT_TENANT_FIELD as R, defineResourceVariants as S, SeamedResourceConfig as T, HookOperation as U, HOOK_OPERATIONS as V, HookPhase as W, RESERVED_QUERY_PARAMS as X, MutationOperation as Y, SYSTEM_FIELDS as Z, getEntityIdField as _, formatValidationErrors as a, VariantsMap as b, nativePolicyFilter as c, createFastifyHandler as d, createRequestContext as f, getEntityId as g, sendControllerResponse as h, assertValidConfig as i, defineAggregation as j, createCrudRouter as k, collectReadBlockedFields as l, getControllerScope as m, ValidateOptions as n, validateResourceConfig as o, getControllerContext as p, MAX_SEARCH_LENGTH as q, ValidationResult as r, NativePolicyFilter as s, ConfigError as t, isFieldReadable as u, getEntityQuery as v, ResourceSeams as w, VariantsResult as x, VariantOverride as y, DEFAULT_UPDATE_METHOD as z };
@@ -1,5 +1,5 @@
1
1
 
2
- import { l as PermissionCheck } from "./base-CxrV1LmG.mjs";
2
+ import { l as PermissionCheck } from "./base-CZyixEQR.mjs";
3
3
  import { FastifyPluginAsync } from "fastify";
4
4
  //#region src/integrations/jobs/execution.d.ts
5
5
  /**