@classytic/arc 2.41.1 → 2.44.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 (248) hide show
  1. package/dist/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
  2. package/dist/{EventTransport-DSqD_Xsg.mjs → EventTransport-DZWDsaPa.mjs} +22 -17
  3. package/dist/{HookSystem-CMF94SEA.mjs → HookSystem-yjEgn7Cm.mjs} +2 -2
  4. package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
  5. package/dist/{ResourceRegistry-MGpXoxHZ.mjs → ResourceRegistry-DJxHUpE4.mjs} +44 -13
  6. package/dist/acquire-BozJ-9yt.mjs +35 -0
  7. package/dist/actionPermissions-5N04zBL4.mjs +772 -0
  8. package/dist/audit/index.d.mts +46 -8
  9. package/dist/audit/index.mjs +48 -26
  10. package/dist/auth/audit.d.mts +8 -8
  11. package/dist/auth/audit.mjs +1 -1
  12. package/dist/auth/index.d.mts +46 -16
  13. package/dist/auth/index.mjs +134 -156
  14. package/dist/auth/redis-session.d.mts +4 -5
  15. package/dist/auth/redis-session.mjs +1 -1
  16. package/dist/{authorizationDecision-DawKGoXb.mjs → authorizationDecision-wX3SA9w_.mjs} +7 -102
  17. package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
  18. package/dist/boundedMap-DWiKW7lP.mjs +57 -0
  19. package/dist/{buildHandler-CvxKOc0m.mjs → buildHandler-Bswu_vNb.mjs} +4 -4
  20. package/dist/cache/index.d.mts +31 -43
  21. package/dist/cache/index.mjs +4 -4
  22. package/dist/{caching-DbCBxlgw.mjs → caching-Drp68DIS.mjs} +3 -3
  23. package/dist/claimed-DYvQoZLv.mjs +8 -0
  24. package/dist/cleanup/index.d.mts +18 -22
  25. package/dist/cleanup/index.mjs +27 -73
  26. package/dist/cli/commands/describe.d.mts +7 -5
  27. package/dist/cli/commands/describe.mjs +7 -4
  28. package/dist/cli/commands/docs.d.mts +2 -3
  29. package/dist/cli/commands/docs.mjs +3 -3
  30. package/dist/cli/commands/doctor.d.mts +2 -3
  31. package/dist/cli/commands/doctor.mjs +1 -1
  32. package/dist/cli/commands/generate.mjs +2 -3
  33. package/dist/cli/commands/init.mjs +2 -3
  34. package/dist/cli/commands/introspect.d.mts +2 -3
  35. package/dist/cli/commands/introspect.mjs +2 -2
  36. package/dist/cli/index.mjs +3 -3
  37. package/dist/{constants-D5Ubn1fe.mjs → constants-B2QHb6u6.mjs} +4 -2
  38. package/dist/context/index.d.mts +11 -14
  39. package/dist/context/index.mjs +18 -38
  40. package/dist/core/index.d.mts +3 -3
  41. package/dist/core/index.mjs +8 -8
  42. package/dist/{core-5lazhva9.mjs → core-COcqo0Cp.mjs} +15 -5
  43. package/dist/{createActionRouter-DNqoaK81.mjs → createActionRouter-zG13rpPJ.mjs} +97 -39
  44. package/dist/{createAggregationRouter-BcbQJf10.mjs → createAggregationRouter-CWRz96Vr.mjs} +11 -8
  45. package/dist/{preloadResources-f3boenVZ.mjs → createApp-BGLYtErt.mjs} +305 -394
  46. package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-DSztofa9.d.mts} +1 -1
  47. package/dist/{defineAggregation-D_eJjm5A.mjs → defineAggregation--3xguLkk.mjs} +1 -1
  48. package/dist/{defineResource-DxkMTjRn.mjs → defineResource-gUp9ug66.mjs} +118 -1024
  49. package/dist/discovery/index.d.mts +6 -7
  50. package/dist/discovery/index.mjs +1 -1
  51. package/dist/docs/index.d.mts +11 -5
  52. package/dist/docs/index.mjs +4 -4
  53. package/dist/{elevation-CkvG0LG2.mjs → elevation-BG4gnMsJ.mjs} +41 -12
  54. package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
  55. package/dist/encryption/index.d.mts +5 -5
  56. package/dist/encryption/index.mjs +3 -3
  57. package/dist/{errorHandler-D1GHKGlV.mjs → errorHandler-COHw3N1b.mjs} +26 -5
  58. package/dist/{errors-BH7YU_9O.mjs → errors-CW4anJBy.mjs} +58 -23
  59. package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
  60. package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
  61. package/dist/{eventPlugin-zZY-unhr.mjs → eventPlugin-BweHAVws.mjs} +82 -21
  62. package/dist/{subscribe-helpers-DatDkcuG.mjs → eventTypes-N4-omQFR.mjs} +151 -17
  63. package/dist/events/index.d.mts +43 -18
  64. package/dist/events/index.mjs +49 -53
  65. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  66. package/dist/events/transports/redis-stream-entry.mjs +139 -157
  67. package/dist/events/transports/redis.d.mts +5 -6
  68. package/dist/events/transports/redis.mjs +2 -2
  69. package/dist/factory/index.d.mts +42 -27
  70. package/dist/factory/index.mjs +213 -32
  71. package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DRlCIWE9.d.mts} +11 -25
  72. package/dist/{fields-BHrkoF5y.mjs → fields-A5crhsJb.mjs} +1 -1
  73. package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
  74. package/dist/filter-merge-DGM-GQ1J.mjs +99 -0
  75. package/dist/{generate-BLRf2m3y.mjs → generate-BXKo2Gc8.mjs} +2 -2
  76. package/dist/{headers-BIXWKrzQ.mjs → headers-DKZQKL-Z.mjs} +2 -2
  77. package/dist/health-BYAwA6YS.mjs +22 -0
  78. package/dist/{health-ZRHeDHXH.mjs → health-CrqUp3sz.mjs} +115 -55
  79. package/dist/hooks/index.d.mts +2 -2
  80. package/dist/hooks/index.mjs +2 -3
  81. package/dist/idempotency/index.d.mts +36 -10
  82. package/dist/idempotency/index.mjs +230 -111
  83. package/dist/idempotency/redis.d.mts +1 -1
  84. package/dist/idempotency/redis.mjs +77 -12
  85. package/dist/{index-D4u76eQW.d.mts → index-Beg3aNnK.d.mts} +23 -101
  86. package/dist/{preloadResources-CjS2OfpU.d.mts → index-BkV55WlV.d.mts} +37 -38
  87. package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
  88. package/dist/index-CUJvoyw3.d.mts +510 -0
  89. package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
  90. package/dist/{index-DHbyPo5j.d.mts → index-WH7xgvxS.d.mts} +304 -254
  91. package/dist/index.d.mts +9 -9
  92. package/dist/index.mjs +11 -11
  93. package/dist/{init-CpLkjU18.mjs → init-BPzK5Lnr.mjs} +1 -1
  94. package/dist/integrations/event-gateway.d.mts +11 -7
  95. package/dist/integrations/event-gateway.mjs +4 -4
  96. package/dist/integrations/index.d.mts +3 -3
  97. package/dist/integrations/index.mjs +1 -1
  98. package/dist/integrations/jobs/index.d.mts +1 -1
  99. package/dist/integrations/jobs/index.mjs +18 -5
  100. package/dist/integrations/mcp/index.d.mts +102 -89
  101. package/dist/integrations/mcp/index.mjs +19 -4
  102. package/dist/integrations/mcp/testing.d.mts +8 -9
  103. package/dist/integrations/mcp/testing.mjs +2 -2
  104. package/dist/integrations/streamline.d.mts +85 -144
  105. package/dist/integrations/streamline.mjs +131 -55
  106. package/dist/integrations/webhooks.d.mts +83 -143
  107. package/dist/integrations/webhooks.mjs +36 -80
  108. package/dist/integrations/websocket-pushref-redis.d.mts +5 -6
  109. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  110. package/dist/integrations/websocket-redis.d.mts +5 -6
  111. package/dist/integrations/websocket-redis.mjs +1 -1
  112. package/dist/integrations/websocket.d.mts +3 -3
  113. package/dist/integrations/websocket.mjs +2 -2
  114. package/dist/{interface-DEWNOMza.d.mts → interface-JJzwH4Ro.d.mts} +34 -2
  115. package/dist/{jsonBody-ELR9lfeU.mjs → jsonBody-YIq-vGLv.mjs} +2 -2
  116. package/dist/{keys-cpZCtcIE.mjs → keys-CpoiZ8hU.mjs} +7 -18
  117. package/dist/{loadResources-BPfWiI5s.mjs → loadResources-6jO52-RR.mjs} +3 -3
  118. package/dist/{loadResourcesFromEntry-ixtfL3J2.mjs → loadResourcesFromEntry-MP8xEppu.mjs} +2 -2
  119. package/dist/logger/index.d.mts +9 -17
  120. package/dist/logger/index.mjs +2 -153
  121. package/dist/logger-D4V1zGLI.mjs +160 -0
  122. package/dist/{mcpPlugin-BX5PujI0.mjs → mcpPlugin-srPc7ItN.mjs} +446 -170
  123. package/dist/{memory-Iotz0cCx.mjs → memory-CTa5pOCW.mjs} +36 -34
  124. package/dist/{metrics-NMsmpRmY.mjs → metrics-DsZrvnpB.mjs} +39 -72
  125. package/dist/middleware/index.d.mts +5 -5
  126. package/dist/middleware/index.mjs +3 -3
  127. package/dist/migrations/index.d.mts +13 -13
  128. package/dist/migrations/index.mjs +2 -2
  129. package/dist/{module-DpLJG2_N.mjs → module--L0iBIZz.mjs} +8 -8
  130. package/dist/mongodb-memory-server-CHhYSq5y.mjs +35539 -0
  131. package/dist/mongoose-CYJCLyi-.mjs +67451 -0
  132. package/dist/multiTenant-CAtYlW6H.d.mts +104 -0
  133. package/dist/{multipartBody-DtRWM6_U.mjs → multipartBody-Cc7eZ9cq.mjs} +46 -7
  134. package/dist/node-D8UZv_8c.mjs +41236 -0
  135. package/dist/{openapi-CmFf3yq_.mjs → openapi-CMegfsm8.mjs} +48 -10
  136. package/dist/outbox-admin/index.d.mts +5 -5
  137. package/dist/outbox-admin/index.mjs +6 -18
  138. package/dist/{outbox-module-D2z5WkDY.mjs → outbox-module-Ryk270jd.mjs} +203 -33
  139. package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
  140. package/dist/permissions/index.d.mts +5 -4
  141. package/dist/permissions/index.mjs +8 -6
  142. package/dist/{permissions-D8TBH44E.mjs → permissions-C5ijIz5Q.mjs} +149 -33
  143. package/dist/{pipe-FMWNheSO.mjs → pipe-D81zMtWs.mjs} +2 -2
  144. package/dist/pipeline/index.d.mts +7 -7
  145. package/dist/pipeline/index.mjs +2 -2
  146. package/dist/plan-CJGMKoui.mjs +565 -0
  147. package/dist/{BaseController-CYEwjyjN.mjs → plugin-DALd9dcF.mjs} +1269 -346
  148. package/dist/plugins/index.d.mts +17 -14
  149. package/dist/plugins/index.mjs +44 -22
  150. package/dist/plugins/response-cache.d.mts +5 -6
  151. package/dist/plugins/response-cache.mjs +8 -14
  152. package/dist/plugins/tracing-entry.mjs +2 -2
  153. package/dist/{pluralize-CXWZIzTv.mjs → pluralize-COUNYo3d.mjs} +1 -1
  154. package/dist/presets/filesUpload.d.mts +8 -8
  155. package/dist/presets/filesUpload.mjs +5 -5
  156. package/dist/presets/index.d.mts +35 -40
  157. package/dist/presets/index.mjs +4 -4
  158. package/dist/presets/multiTenant.d.mts +2 -107
  159. package/dist/presets/multiTenant.mjs +22 -162
  160. package/dist/presets/search.d.mts +9 -10
  161. package/dist/presets/search.mjs +2 -2
  162. package/dist/{presets-ZJSPgmT2.mjs → presets-CONf2Qem.mjs} +99 -107
  163. package/dist/{projection-BzIgzoKZ.mjs → projection-wFoLqdss.mjs} +2 -2
  164. package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
  165. package/dist/{queryCachePlugin-DZHPOm9p.mjs → queryCachePlugin-BATECpyh.mjs} +12 -14
  166. package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
  167. package/dist/{rateLimitKey-BvOvcBDi.mjs → rateLimitKey-DVEZ_UpV.mjs} +1 -1
  168. package/dist/{realtime-8tIQWZz4.mjs → realtime-xyubMKSB.mjs} +25 -21
  169. package/dist/{redis-Bzi1y3F9.d.mts → redis-BDgv9Glw.d.mts} +17 -24
  170. package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
  171. package/dist/redisShapes-CQksY67q.d.mts +55 -0
  172. package/dist/registry/index.d.mts +15 -10
  173. package/dist/registry/index.mjs +4 -4
  174. package/dist/{registry-DNkgGQcK.mjs → registry-Bdzg-hdm.mjs} +13 -10
  175. package/dist/{renewingLease-yF8BdW4b.mjs → renewingLease-BFJxGPuh.mjs} +1 -1
  176. package/dist/{replyHelpers-CNdvMfM4.mjs → replyHelpers-Bnc6lJyy.mjs} +2 -2
  177. package/dist/{requestContext-cDkAUr-P.mjs → requestContext-C10UeFe5.mjs} +1 -1
  178. package/dist/requirement-Bu50QALH.mjs +35 -0
  179. package/dist/requirement-CbiLdQ1n.d.mts +22 -0
  180. package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
  181. package/dist/resourceRateLimit-urWPJxrt.mjs +180 -0
  182. package/dist/rolldown-runtime-MYrLNGnq.mjs +45 -0
  183. package/dist/routeValidator-DHtpzrzk.mjs +70 -0
  184. package/dist/{runtimeCapabilities-CkhS6jn6.mjs → runtimeCapabilities-DIMKMV2G.mjs} +1 -1
  185. package/dist/{schedules-j6uXXAeJ.mjs → schedules-CKTs5ys8.mjs} +46 -37
  186. package/dist/{schemaConverter-BVA7cFRG.mjs → schemaConverter-BVjkQ5DD.mjs} +2 -2
  187. package/dist/{schemaIR-CTvPDoPB.mjs → schemaIR-BA0Hb21Y.mjs} +2 -2
  188. package/dist/schemas/index.d.mts +20 -10
  189. package/dist/schemas/index.mjs +8 -3
  190. package/dist/scim/index.d.mts +13 -13
  191. package/dist/scim/index.mjs +2 -2
  192. package/dist/scope/index.d.mts +4 -4
  193. package/dist/scope/index.mjs +6 -6
  194. package/dist/{scope-BUi1xV1I.mjs → scope-DINaj7Ax.mjs} +4 -4
  195. package/dist/shutdown-LpLMH8T1.mjs +59 -0
  196. package/dist/{simpleEqualityMatcher-C9bzq2gO.mjs → simpleEqualityMatcher-DbwIM1f1.mjs} +1 -1
  197. package/dist/{sse-BeqVKQKu.mjs → sse-BzJFPX_1.mjs} +11 -15
  198. package/dist/{sseStream-Ppzo-WUH.mjs → sseStream-DQChzGTs.mjs} +2 -2
  199. package/dist/{store-helpers-dW71XVWL.mjs → store-helpers-Coj9RhOZ.mjs} +1 -1
  200. package/dist/{streaming-IcRFjWQU.mjs → streaming-JzB5CAga.mjs} +1 -1
  201. package/dist/subscriberIdentity-DeyppIif.mjs +28 -0
  202. package/dist/tenancy-DxV8OuX2.mjs +43 -0
  203. package/dist/tenantPreparation-CBvvAcAj.mjs +67 -0
  204. package/dist/testing/cleanupStoreContract.d.mts +4 -5
  205. package/dist/testing/cleanupStoreContract.mjs +1 -1
  206. package/dist/testing/index.d.mts +215 -197
  207. package/dist/testing/index.mjs +289 -214
  208. package/dist/testing/outboxStoreContract.d.mts +4 -5
  209. package/dist/testing/outboxStoreContract.mjs +137 -2
  210. package/dist/testing/requiredPorts.d.mts +16 -0
  211. package/dist/testing/requiredPorts.mjs +65 -0
  212. package/dist/testing/storageContract.d.mts +4 -5
  213. package/dist/testing/storageContract.mjs +1 -1
  214. package/dist/timing-CntavTlR.mjs +46 -0
  215. package/dist/{transactionContext-CPbdlnVw.mjs → transactionContext-orvnGu4F.mjs} +1 -1
  216. package/dist/{typeGuards-BLjPgVBm.mjs → typeGuards-kEaP_WmO.mjs} +1 -1
  217. package/dist/types/index.d.mts +4 -4
  218. package/dist/types/index.mjs +1 -1
  219. package/dist/types/storage.mjs +1 -1
  220. package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
  221. package/dist/{types-CWQn9-IC.d.mts → types-D3Ixsh00.d.mts} +22 -9
  222. package/dist/{types-CgenB1gv.mjs → types-fvO6Ovzx.mjs} +4 -4
  223. package/dist/usage/index.d.mts +5 -6
  224. package/dist/usage/index.mjs +5 -5
  225. package/dist/{userHelpers-ChRvkuSZ.mjs → userHelpers-C76zD5pa.mjs} +1 -1
  226. package/dist/utils/index.d.mts +125 -264
  227. package/dist/utils/index.mjs +13 -12
  228. package/dist/{utils-CxcctrAh.mjs → utils-BpkVZ8rB.mjs} +315 -404
  229. package/dist/{validate-DrYWnOzI.mjs → validate-CWp-lsrm.mjs} +6 -14
  230. package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
  231. package/dist/{versioning-DKkT4hNJ.mjs → versioning-CHhL9P3o.mjs} +4 -4
  232. package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
  233. package/dist/{workScope-CxKqoIFn.mjs → workScope-n9a7d_lZ.mjs} +2 -2
  234. package/package.json +57 -59
  235. package/skills/arc/SKILL.md +13 -4
  236. package/skills/arc/references/auth.md +8 -5
  237. package/skills/arc/references/integrations.md +1 -1
  238. package/skills/arc/references/mcp.md +8 -6
  239. package/skills/arc/references/multi-tenancy.md +19 -14
  240. package/skills/arc/references/production.md +27 -10
  241. package/dist/actionPermissions-BoPGQ5-4.mjs +0 -350
  242. package/dist/index-CFfLKMH4.d.mts +0 -290
  243. package/dist/interface-YzIbF7Ii.mjs +0 -17
  244. package/dist/redis-stream-BPKscsTB.d.mts +0 -260
  245. package/dist/registerRoute-Bsnk6NiZ.mjs +0 -364
  246. package/dist/rolldown-runtime-eysyzFAF.mjs +0 -15
  247. package/dist/sync/changelog.d.mts +0 -3
  248. package/dist/sync/changelog.mjs +0 -3
@@ -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, Hn as IRequestContext, I as CrudController, L as ResourceConfig, O as FastifyWithDecorators, St as ActionDefinition, Vn as IControllerResponse, X as RouteSchemaOptions, Z as ArcFieldRule, g as RequestContext, ot as AggregationConfig, v as CrudRouterOptions } from "./index-WH7xgvxS.mjs";
5
+ import "./fastify-augmentation-DRlCIWE9.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,90 +269,33 @@ 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>;
270
- //#endregion
271
- //#region src/core/entityHelpers.d.ts
272
- /**
273
- * Read the resource's configured `idField` for the current request.
274
- * Falls back to the framework default (`_id`) when the route hasn't
275
- * bound an idField — keeps handlers safe to author without checking
276
- * the resource config.
277
- */
278
- declare function getEntityIdField(req: RequestWithExtras): string;
279
- /**
280
- * Read the URL `:id` path param value as the resource handle.
281
- * Returns `undefined` when the route has no `:id` segment (collection
282
- * routes) — handlers that need the entity must be on row routes.
283
- */
284
- declare function getEntityId(req: RequestWithExtras): string | undefined;
285
- /**
286
- * Compose a `findOne` filter that resolves the current request's
287
- * entity, regardless of whether the resource binds `_id` or a custom
288
- * field. Idiomatic shape for arc action handlers.
289
- *
290
- * ```ts
291
- * const doc = await Model.findOne(getEntityQuery(req));
292
- * ```
293
- *
294
- * Returns `{}` when the route has no entity context (collection routes
295
- * or tests bypassing the router) — caller decides what that means.
296
- */
297
- declare function getEntityQuery(req: RequestWithExtras): Record<string, string>;
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>;
298
273
  //#endregion
299
274
  //#region src/core/fastifyAdapter.d.ts
300
275
  /**
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.
276
+ * Project `FastifyRequest` into the `IRequestContext` controllers receive,
277
+ * lifting scope, context, and a server accessor onto a flat, typed surface.
308
278
  */
309
279
  declare function createRequestContext(req: FastifyRequest): IRequestContext;
310
280
  /**
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.
281
+ * Typed auth context from an IRequestContext, for controller overrides.
282
+ * For org scope, use `getControllerScope(req)`.
315
283
  */
316
284
  declare function getControllerContext(req: IRequestContext): RequestContext;
317
- /**
318
- * Get request scope from an IRequestContext.
319
- * Returns the RequestScope set by auth adapters.
320
- */
285
+ /** The RequestScope set by auth adapters (`PUBLIC_SCOPE` when absent). */
321
286
  declare function getControllerScope(req: IRequestContext): RequestScope;
322
287
  /**
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.
288
+ * Send a controller's `IControllerResponse` envelope (status, meta, headers)
289
+ * through Fastify's reply, applying field masks and field read permissions.
330
290
  *
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.
291
+ * A bare return (no `data` key) is wrapped as `{ data, status: 200 }` so
292
+ * `fields:` permissions still apply — otherwise restricted fields would leak.
293
+ * The envelope remains the canonical contract.
344
294
  */
345
295
  declare function sendControllerResponse<T>(reply: FastifyReply, response: IControllerResponse<T>, request?: FastifyRequest): void;
346
296
  /**
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.
297
+ * Bridge an `IController` method into a Fastify route handler, sending the
298
+ * envelope through `sendControllerResponse`.
353
299
  *
354
300
  * @example
355
301
  * ```typescript
@@ -359,30 +305,6 @@ declare function sendControllerResponse<T>(reply: FastifyReply, response: IContr
359
305
  * ```
360
306
  */
361
307
  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
308
  //#endregion
387
309
  //#region src/core/fieldRulePredicates.d.ts
388
310
  /**
@@ -446,4 +368,4 @@ declare function formatValidationErrors(resourceName: string, result: Validation
446
368
  */
447
369
  declare function assertValidConfig(config: ResourceConfig, options?: ValidateOptions): void;
448
370
  //#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 };
371
+ export { CrudOperation as A, HookOperation as B, mergeResourceConfig as C, createPermissionMiddleware as D, createCrudRouter as E, DEFAULT_TENANT_FIELD as F, MUTATION_OPERATIONS as G, MAX_FILTER_DEPTH as H, DEFAULT_UPDATE_METHOD as I, SYSTEM_FIELDS as J, MutationOperation as K, DEFAULT_VERSION_FIELD as L, DEFAULT_LIMIT as M, DEFAULT_MAX_LIMIT as N, defineAggregation as O, DEFAULT_SORT as P, HOOK_OPERATIONS as R, SeamedResourceConfig as S, defineAction as T, MAX_REGEX_LENGTH as U, HookPhase as V, MAX_SEARCH_LENGTH as W, VariantsMap as _, formatValidationErrors as a, AdapterLike as b, nativePolicyFilter as c, createFastifyHandler as d, createRequestContext as f, VariantOverride as g, sendControllerResponse as h, assertValidConfig as i, DEFAULT_ID_FIELD as j, CRUD_OPERATIONS as k, collectReadBlockedFields as l, getControllerScope as m, ValidateOptions as n, validateResourceConfig as o, getControllerContext as p, RESERVED_QUERY_PARAMS as q, ValidationResult as r, NativePolicyFilter as s, ConfigError as t, isFieldReadable as u, VariantsResult as v, DefineActionConfig as w, ResourceSeams as x, defineResourceVariants as y, HOOK_PHASES as z };
@@ -1,16 +1,16 @@
1
1
 
2
- import { It as Authenticator } from "./index-DHbyPo5j.mjs";
2
+ import { Mt as Authenticator } from "./index-WH7xgvxS.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-CUJvoyw3.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 { i as IdempotencyStore } from "./interface-JJzwH4Ro.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,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 };