@classytic/arc 2.30.0 → 2.32.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 (242) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -0
  3. package/TRADEMARK.md +22 -0
  4. package/dist/{BaseController-B5DwufbB.mjs → BaseController-Dk34dxhI.mjs} +21 -19
  5. package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
  6. package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-BV10D0oG.mjs} +1 -0
  7. package/dist/{HookSystem-WkIougo6.mjs → HookSystem-vimw5D7Z.mjs} +2 -1
  8. package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
  9. package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-BVr7PgA0.mjs} +18 -15
  10. package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-Dti7ebyv.mjs} +1 -0
  11. package/dist/audit/index.d.mts +3 -2
  12. package/dist/audit/index.mjs +2 -1
  13. package/dist/auth/audit.d.mts +1 -0
  14. package/dist/auth/audit.mjs +1 -0
  15. package/dist/auth/index.d.mts +5 -4
  16. package/dist/auth/index.mjs +11 -9
  17. package/dist/auth/redis-session.d.mts +2 -1
  18. package/dist/auth/redis-session.mjs +1 -0
  19. package/dist/{applyPermissionResult-Cf6zUCvb.mjs → authorizationDecision-__T3EJDA.mjs} +19 -10
  20. package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-Dn7rzUJo.mjs} +6 -4
  21. package/dist/cache/index.d.mts +4 -3
  22. package/dist/cache/index.mjs +4 -3
  23. package/dist/{caching-_NJeDd1_.mjs → caching-DFJqHyFs.mjs} +2 -1
  24. package/dist/cleanup/index.d.mts +39 -16
  25. package/dist/cleanup/index.mjs +50 -38
  26. package/dist/cli/commands/describe.d.mts +2 -1
  27. package/dist/cli/commands/describe.mjs +4 -5
  28. package/dist/cli/commands/docs.d.mts +1 -0
  29. package/dist/cli/commands/docs.mjs +3 -2
  30. package/dist/cli/commands/doctor.d.mts +1 -0
  31. package/dist/cli/commands/doctor.mjs +1 -0
  32. package/dist/cli/commands/generate.d.mts +2 -1
  33. package/dist/cli/commands/generate.mjs +2 -1
  34. package/dist/cli/commands/init.d.mts +2 -1
  35. package/dist/cli/commands/init.mjs +2 -1
  36. package/dist/cli/commands/introspect.d.mts +1 -0
  37. package/dist/cli/commands/introspect.mjs +2 -1
  38. package/dist/cli/index.d.mts +3 -2
  39. package/dist/cli/index.mjs +3 -2
  40. package/dist/{constants-DNre0wRg.mjs → constants-J99LGTJI.mjs} +1 -0
  41. package/dist/context/index.d.mts +1 -0
  42. package/dist/context/index.mjs +3 -2
  43. package/dist/core/index.d.mts +3 -2
  44. package/dist/core/index.mjs +7 -6
  45. package/dist/{core-poalJLvp.mjs → core-BwwmNSp7.mjs} +3 -2
  46. package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-DkJZWo0m.mjs} +14 -10
  47. package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-B1exOVD8.mjs} +10 -7
  48. package/dist/{createApp-CXrKFciH.mjs → createApp-Bv0m-Q6_.mjs} +625 -229
  49. package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-gX4No1gt.mjs} +1 -0
  50. package/dist/{defineResource-CxWqDCAy.mjs → defineResource-XFPPUu2c.mjs} +84 -50
  51. package/dist/discovery/index.d.mts +1 -0
  52. package/dist/discovery/index.mjs +1 -0
  53. package/dist/docs/index.d.mts +3 -2
  54. package/dist/docs/index.mjs +3 -2
  55. package/dist/{elevation-C9s5hFP_.d.mts → elevation-BXCfVcNG.d.mts} +1 -0
  56. package/dist/{elevation-CIz1GjGm.mjs → elevation-DNXXxgjl.mjs} +4 -3
  57. package/dist/encryption/index.d.mts +2 -1
  58. package/dist/encryption/index.mjs +5 -3
  59. package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-B2AZUJUj.mjs} +3 -2
  60. package/dist/{errorHandler-C6yv4ZTW.d.mts → errorHandler-CpYUJmPA.d.mts} +1 -0
  61. package/dist/{errors-DHcHVAgk.d.mts → errors-BGdVwP25.d.mts} +1 -0
  62. package/dist/{errors-DkO8Nk6-.mjs → errors-Bh1KK5ps.mjs} +1 -0
  63. package/dist/{eventPlugin-D2NNR4py.mjs → eventPlugin-Dk_TyXeE.mjs} +8 -6
  64. package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
  65. package/dist/events/index.d.mts +112 -44
  66. package/dist/events/index.mjs +177 -141
  67. package/dist/events/transports/redis-stream-entry.d.mts +2 -1
  68. package/dist/events/transports/redis-stream-entry.mjs +14 -9
  69. package/dist/events/transports/redis.d.mts +2 -1
  70. package/dist/events/transports/redis.mjs +1 -0
  71. package/dist/{externalPaths-BE6wFpYv.d.mts → externalPaths-CmGOxOtD.d.mts} +1 -0
  72. package/dist/factory/index.d.mts +9 -5
  73. package/dist/factory/index.mjs +131 -7
  74. package/dist/fastify-augmentation-BppG5bMT.d.mts +179 -0
  75. package/dist/{fields-CQ_7KQWw.mjs → fields-DEi65pGj.mjs} +6 -10
  76. package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
  77. package/dist/{generate-D0wZupBg.mjs → generate-CRSG0jTv.mjs} +2 -1
  78. package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
  79. package/dist/{headers-BvlQSDMB.mjs → headers-BXjQYbeC.mjs} +2 -1
  80. package/dist/{health-CB_m4S32.mjs → health-5XnTa2uo.mjs} +1 -0
  81. package/dist/hooks/index.d.mts +2 -1
  82. package/dist/hooks/index.mjs +2 -1
  83. package/dist/idempotency/index.d.mts +3 -2
  84. package/dist/idempotency/index.mjs +8 -5
  85. package/dist/idempotency/redis.d.mts +2 -1
  86. package/dist/idempotency/redis.mjs +1 -0
  87. package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
  88. package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
  89. package/dist/{index-Cx7bro4R.d.mts → index-DXlHwvuE.d.mts} +5 -4
  90. package/dist/index-ZWhLTp_s.d.mts +290 -0
  91. package/dist/{index-Ch16aAah.d.mts → index-zq6VrjaB.d.mts} +122 -15
  92. package/dist/index.d.mts +9 -8
  93. package/dist/index.mjs +11 -10
  94. package/dist/{init-tlRSt667.mjs → init-BbfP8aky.mjs} +25 -27
  95. package/dist/{init-BPEu8cs-.d.mts → init-Cscs4lab.d.mts} +1 -0
  96. package/dist/integrations/event-gateway.d.mts +3 -2
  97. package/dist/integrations/event-gateway.mjs +2 -1
  98. package/dist/integrations/index.d.mts +4 -3
  99. package/dist/integrations/index.mjs +1 -0
  100. package/dist/integrations/jobs/index.d.mts +2 -1
  101. package/dist/integrations/jobs/index.mjs +109 -33
  102. package/dist/integrations/mcp/index.d.mts +6 -6
  103. package/dist/integrations/mcp/index.mjs +2 -1
  104. package/dist/integrations/mcp/testing.d.mts +3 -2
  105. package/dist/integrations/mcp/testing.mjs +2 -2
  106. package/dist/integrations/streamline.d.mts +1 -0
  107. package/dist/integrations/streamline.mjs +3 -2
  108. package/dist/integrations/webhooks.d.mts +1 -0
  109. package/dist/integrations/webhooks.mjs +1 -0
  110. package/dist/integrations/websocket-pushref-redis.d.mts +2 -1
  111. package/dist/integrations/websocket-pushref-redis.mjs +1 -0
  112. package/dist/integrations/websocket-redis.d.mts +2 -1
  113. package/dist/integrations/websocket-redis.mjs +1 -0
  114. package/dist/integrations/websocket.d.mts +3 -2
  115. package/dist/integrations/websocket.mjs +38 -34
  116. package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
  117. package/dist/{interface-n5hpKg1d.mjs → interface-BP4IJCBO.mjs} +1 -0
  118. package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
  119. package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-DDSR2HFl.mjs} +2 -1
  120. package/dist/{keys-Cd316u_y.mjs → keys-B-HBTGXl.mjs} +1 -0
  121. package/dist/{loadResources-DpU8pfjV.mjs → loadResources-DisEAmkm.mjs} +4 -2
  122. package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-D1MJp13f.mjs} +2 -1
  123. package/dist/logger/index.d.mts +1 -0
  124. package/dist/logger/index.mjs +1 -0
  125. package/dist/{mcpPlugin-nRzm5g2s.mjs → mcpPlugin-CpfVpKHE.mjs} +38 -38
  126. package/dist/{memory-CmnzXE5Z.mjs → memory-DsuWnj4T.mjs} +5 -4
  127. package/dist/{metrics-fdxI5mn_.mjs → metrics-DdQL8syd.mjs} +2 -1
  128. package/dist/middleware/index.d.mts +2 -1
  129. package/dist/middleware/index.mjs +3 -2
  130. package/dist/migrations/index.d.mts +1 -0
  131. package/dist/migrations/index.mjs +3 -2
  132. package/dist/module-Br81am6m.mjs +78 -0
  133. package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-BnkBLN7v.mjs} +3 -2
  134. package/dist/{openapi-B8Vkbxbn.mjs → openapi-DIRzvxC0.mjs} +6 -5
  135. package/dist/outbox-admin/index.d.mts +85 -0
  136. package/dist/outbox-admin/index.mjs +115 -0
  137. package/dist/permissions/index.d.mts +5 -4
  138. package/dist/permissions/index.mjs +6 -5
  139. package/dist/{permissions-Bfu_8y1U.mjs → permissions-Dl_m0NCe.mjs} +308 -42
  140. package/dist/{pipe-BOLmGIxa.mjs → pipe-ELHCP3zj.mjs} +3 -4
  141. package/dist/pipeline/index.d.mts +2 -1
  142. package/dist/pipeline/index.mjs +2 -1
  143. package/dist/{pipeline-BJnpkY9i.mjs → pipeline-CPA-jx0M.mjs} +17 -14
  144. package/dist/plugins/index.d.mts +8 -7
  145. package/dist/plugins/index.mjs +16 -15
  146. package/dist/plugins/response-cache.d.mts +1 -0
  147. package/dist/plugins/response-cache.mjs +2 -1
  148. package/dist/plugins/tracing-entry.d.mts +2 -1
  149. package/dist/plugins/tracing-entry.mjs +2 -1
  150. package/dist/{pluralize-BhrgwZb9.mjs → pluralize-C2ZkKbsn.mjs} +1 -0
  151. package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-CDs87fTw.mjs} +1 -0
  152. package/dist/{preloadResources-DCfa2egz.d.mts → preloadResources-T1hmlTEZ.d.mts} +117 -12
  153. package/dist/presets/filesUpload.d.mts +6 -5
  154. package/dist/presets/filesUpload.mjs +10 -12
  155. package/dist/presets/index.d.mts +3 -2
  156. package/dist/presets/index.mjs +2 -1
  157. package/dist/presets/multiTenant.d.mts +2 -1
  158. package/dist/presets/multiTenant.mjs +3 -2
  159. package/dist/presets/search.d.mts +3 -2
  160. package/dist/presets/search.mjs +2 -1
  161. package/dist/{presets-CJOEXLuk.mjs → presets-Dntd_pUO.mjs} +6 -4
  162. package/dist/{projection-UBDgfMwu.mjs → projection-CjHhM5W1.mjs} +2 -1
  163. package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
  164. package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
  165. package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-Dhps-Ldt.mjs} +6 -5
  166. package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-C7mmAGs3.mjs} +7 -3
  167. package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-CccEFBfk.mjs} +1 -0
  168. package/dist/{realtime-B9nmIY5V.mjs → realtime-DVvVZZFz.mjs} +20 -9
  169. package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
  170. package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
  171. package/dist/{registerRoute-JkxIEBJq.mjs → registerRoute-B_QrjYZS.mjs} +10 -7
  172. package/dist/registry/index.d.mts +3 -2
  173. package/dist/registry/index.mjs +3 -2
  174. package/dist/{registry-BYXUUg21.mjs → registry-DqUmzA9W.mjs} +2 -1
  175. package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-BpP9wwj7.mjs} +1 -0
  176. package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DS-P0b32.mjs} +2 -1
  177. package/dist/{repositoryFilter-Dz8k3S4P.mjs → repositoryFilter-DotlxG3L.mjs} +1 -0
  178. package/dist/{requestContext-MrlJwECf.mjs → requestContext-B6vQF-sy.mjs} +1 -0
  179. package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-BhflRrBs.mjs} +1 -0
  180. package/dist/{schedules-CjOd2MG9.mjs → schedules-C2Q3uv2d.mjs} +3 -2
  181. package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-Crjvczi_.mjs} +70 -17
  182. package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-CnyKK_1j.mjs} +2 -1
  183. package/dist/schemas/index.d.mts +1 -0
  184. package/dist/schemas/index.mjs +1 -0
  185. package/dist/scim/index.d.mts +1 -0
  186. package/dist/scim/index.mjs +2 -1
  187. package/dist/scope/index.d.mts +3 -2
  188. package/dist/scope/index.mjs +5 -4
  189. package/dist/{scope-DfaPntpo.mjs → scope-afz_Ieek.mjs} +4 -3
  190. package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
  191. package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-C4KiMWUa.mjs} +1 -0
  192. package/dist/{sse-BQ1w0dfl.mjs → sse-B9P4Y-UI.mjs} +7 -5
  193. package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B3zb_d1h.mjs} +2 -1
  194. package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
  195. package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-DmEMHlPQ.mjs} +1 -0
  196. package/dist/{streaming-BQcW6_Kq.mjs → streaming-DPZdQmDz.mjs} +1 -0
  197. package/dist/{subscribe-helpers-DfzsivM6.mjs → subscribe-helpers-sp5xTDVA.mjs} +2 -1
  198. package/dist/sync/changelog.d.mts +1 -0
  199. package/dist/sync/changelog.mjs +1 -0
  200. package/dist/testing/cleanupStoreContract.d.mts +2 -1
  201. package/dist/testing/cleanupStoreContract.mjs +10 -5
  202. package/dist/testing/index.d.mts +166 -12
  203. package/dist/testing/index.mjs +315 -43
  204. package/dist/testing/outboxStoreContract.d.mts +12 -2
  205. package/dist/testing/outboxStoreContract.mjs +110 -20
  206. package/dist/testing/storageContract.d.mts +2 -1
  207. package/dist/testing/storageContract.mjs +11 -5
  208. package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
  209. package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-BvLKvOIL.mjs} +1 -0
  210. package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B_5-hKjJ.mjs} +1 -0
  211. package/dist/types/index.d.mts +6 -5
  212. package/dist/types/index.mjs +1 -0
  213. package/dist/types/storage.d.mts +2 -1
  214. package/dist/types/storage.mjs +1 -0
  215. package/dist/{types-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
  216. package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
  217. package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
  218. package/dist/{types-D_n8L6VY.d.mts → types-CT5vu6M0.d.mts} +132 -17
  219. package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
  220. package/dist/{types-Bmmn-fO0.d.mts → types-CwcUQ610.d.mts} +2 -6
  221. package/dist/{types-CSyCxl2V.mjs → types-DXYX7dIR.mjs} +4 -3
  222. package/dist/usage/index.d.mts +3 -2
  223. package/dist/usage/index.mjs +0 -0
  224. package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-BNsOXzOd.mjs} +1 -0
  225. package/dist/utils/index.d.mts +16 -7
  226. package/dist/utils/index.mjs +10 -9
  227. package/dist/{utils-taUVD4p3.mjs → utils-BtOha_Sp.mjs} +3 -2
  228. package/dist/{validate-Bk44F2yT.mjs → validate-PMCPR9El.mjs} +2 -1
  229. package/dist/{versioning-gKWyryT3.mjs → versioning-CKv2jz_U.mjs} +4 -3
  230. package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
  231. package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
  232. package/package.json +557 -539
  233. package/skills/arc/SKILL.md +22 -8
  234. package/skills/arc/references/api-reference.md +4 -0
  235. package/skills/arc/references/auth.md +3 -0
  236. package/skills/arc/references/integrations.md +33 -0
  237. package/skills/arc/references/mcp.md +6 -7
  238. package/skills/arc/references/production.md +24 -25
  239. package/skills/arc-code-review/references/anti-patterns.md +3 -3
  240. package/dist/fastify-augmentation-0WhPnUH7.d.mts +0 -76
  241. package/dist/index-CCzVR-N3.d.mts +0 -107
  242. package/dist/module-_-M7C5ES.mjs +0 -29
@@ -1,6 +1,7 @@
1
- import { r as CacheStore, t as CacheLogger } from "./interface-BGZCzOGL.mjs";
2
- import { i as RequestScope, n as Mandate } from "./types-DjC-KUCz.mjs";
3
- import { i as PermissionContext, r as PermissionCheck, t as AuthorizationDecision } from "./types-ChvvVNP8.mjs";
1
+
2
+ import { r as CacheStore, t as CacheLogger } from "./interface-BOk3YnTz.mjs";
3
+ import { i as RequestScope, n as Mandate } from "./types-ChuShpCP.mjs";
4
+ import { i as PermissionContext, r as PermissionCheck, t as AuthorizationDecision } from "./types-B7XeLEgK.mjs";
4
5
  import { FastifyReply, FastifyRequest } from "fastify";
5
6
  //#region src/permissions/agent.d.ts
6
7
  /**
@@ -162,7 +163,7 @@ interface RequireAgentScopeOptions<TDoc = Record<string, unknown>> extends Requi
162
163
  */
163
164
  declare function requireAgentScope<TDoc = Record<string, unknown>>(opts: RequireAgentScopeOptions<TDoc>): PermissionCheck<TDoc>;
164
165
  //#endregion
165
- //#region src/permissions/applyPermissionResult.d.ts
166
+ //#region src/permissions/authorizationDecision.d.ts
166
167
  /**
167
168
  * A permission check returns either a bare boolean (terse allow/deny sugar) or
168
169
  * a full {@link AuthorizationDecision}. There is no legacy `PermissionResult` —
@@ -222,12 +223,6 @@ type RequestSink = FastifyRequest & {
222
223
  * installed (and the obligation seam lives).
223
224
  */
224
225
  declare function applyAuthorizationDecision(decision: AuthorizationDecision, request: RequestSink): void;
225
- /**
226
- * @deprecated Renamed to {@link applyAuthorizationDecision} — the contract is an
227
- * `AuthorizationDecision`, not a `PermissionResult`. This alias is kept for
228
- * back-compat and will be removed in a future major.
229
- */
230
- declare const applyPermissionResult: typeof applyAuthorizationDecision;
231
226
  //#endregion
232
227
  //#region src/permissions/context.d.ts
233
228
  /**
@@ -307,6 +302,24 @@ declare function requireRoles(roles: readonly string[], options?: {
307
302
  */
308
303
  includeOrgRoles?: boolean;
309
304
  }): PermissionCheck;
305
+ /**
306
+ * Require a PLATFORM role — global roles only. An organization role can never
307
+ * satisfy this gate.
308
+ *
309
+ * `requireRoles(["ops"])` also accepts an ORG role named `ops` (that is its
310
+ * documented default), and `requireOrgRole("manager")` grants ANY organization's
311
+ * manager. Both return a bare allow with no policy, so a surface that is global
312
+ * by construction — a queue dashboard, a cluster-wide operations endpoint —
313
+ * cannot distinguish them from a real operator gate by looking at the decision.
314
+ * That makes "platform-only" a property the check has to DECLARE, which is what
315
+ * `_platformOnly` records and what such a surface can then require.
316
+ *
317
+ * Elevated scope passes: platform admin is the identity this gate is for.
318
+ *
319
+ * @example
320
+ * permissions: { list: requirePlatformRole("platform-ops") }
321
+ */
322
+ declare function requirePlatformRole(...args: string[] | [readonly string[]]): PermissionCheck;
310
323
  /**
311
324
  * Short-form alias of `requireRoles()`. Identical behavior — checks both
312
325
  * platform roles AND org roles. Prefer `requireRoles` for new code; this
@@ -522,22 +535,45 @@ declare function createDynamicPermissionMatrix(config: DynamicPermissionMatrixCo
522
535
  * - `public` — `allowPublic()`; anyone passes.
523
536
  * - `roles` — grants if the caller holds ANY of these (platform OR org roles,
524
537
  * unioned — matches how `requireRoles`/`requireOrgRole`/`anyOf` compose).
538
+ * - `scoped` — grants only within a caller SCOPE dimension (`_scopeContext`,
539
+ * e.g. `{ branchRole: "head_office" }`), optionally combined with `roles`. The
540
+ * scope dimensions are known statically even though their per-request VALUES
541
+ * aren't, so a consumer that holds the caller's scope (a FE that knows the
542
+ * active branch's role) can decide it client-side — the piece a flat `roles`
543
+ * requirement could not express.
525
544
  * - `authenticated` — the check reads request-time facts (custom auth, service
526
- * scope, ownership, scope-context, grants) that no static analysis can decide;
527
- * the definitive answer is computed per request. Treat as "server decides".
545
+ * scope, ownership, grants) that no static analysis can decide; the definitive
546
+ * answer is computed per request. Treat as "server decides".
528
547
  */
529
548
  type PermissionRequirement = {
530
549
  readonly kind: "public";
531
550
  } | {
532
551
  readonly kind: "roles";
533
552
  readonly roles: readonly string[];
553
+ /**
554
+ * `true` when these roles are NECESSARY but not SUFFICIENT — the gate is an
555
+ * `allOf(...)` that also carries an opaque runtime branch (ownership /
556
+ * custom / dynamic / flow-mode …). A role MATCH is then `conditional`, not a
557
+ * definitive `allow`; a MISMATCH is still a definitive `deny`.
558
+ */
559
+ readonly conditional?: boolean;
560
+ } | {
561
+ readonly kind: "scoped";
562
+ /** Required scope dimensions: `value` string = must equal; `undefined` = must be present. */
563
+ readonly scope: Readonly<Record<string, string | undefined>>;
564
+ /** Roles ALSO required alongside the scope (union of platform + org roles), if any. */
565
+ readonly roles?: readonly string[];
566
+ /** See `roles.conditional` — the composite also has an opaque/contradictory branch. */
567
+ readonly conditional?: boolean;
534
568
  } | {
535
569
  readonly kind: "authenticated";
536
570
  };
537
571
  /**
538
572
  * Extract a check's static requirement from its `PermissionCheckMeta`. Public
539
- * wins; then the union of platform + org roles a role gate declares; otherwise
540
- * "authenticated" (auth-required / custom / request-time checks).
573
+ * wins; then a scope-context gate (optionally with roles); then the union of
574
+ * platform + org roles a role gate declares; otherwise "authenticated"
575
+ * (auth-required / custom / request-time checks). An `allOf` that couldn't be
576
+ * fully captured statically carries `conditional: true` (see `_conditional`).
541
577
  */
542
578
  declare function describePermission(check: PermissionCheck): PermissionRequirement;
543
579
  /** Result of {@link explainAccess}. */
@@ -566,6 +602,8 @@ interface AccessExplanation {
566
602
  declare function explainAccess(check: PermissionCheck, principal?: {
567
603
  roles?: readonly string[];
568
604
  orgRoles?: readonly string[];
605
+ /** The caller's scope-context values (e.g. `{ branchRole: "head_office" }`) — supply to decide a `scoped` gate. */
606
+ scope?: Readonly<Record<string, string | undefined>>;
569
607
  }): AccessExplanation;
570
608
  /**
571
609
  * Introspect a whole permission map (`{ list, get, create, ... }` or any
@@ -952,4 +990,73 @@ declare function fullPublic<TDoc = Record<string, unknown>>(overrides?: Permissi
952
990
  */
953
991
  declare function readOnly<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
954
992
  //#endregion
955
- export { evaluatePermissionDecision as $, explainAccess as A, anyOf as B, requireGrant as C, collectPublicSurface as D, PermissionRequirement as E, createDynamicPermissionMatrix as F, requireOwnership as G, denyAll as H, createOrgPermissions as I, when as J, requireRoles as K, allOf as L, DynamicPermissionMatrix as M, DynamicPermissionMatrixConfig as N, describePermission as O, PermissionEventBus as P, applyPermissionResult as Q, allow as R, modeSatisfies as S, AccessExplanation as T, not as U, deny as V, requireAuth as W, PermissionCheckReturn as X, scopeOf as Y, applyAuthorizationDecision as Z, createRoleHierarchy as _, permissionMatrix as a, requireMandate as at, GrantResolution as b, publicReadAdminWrite as c, requireOrgMembership as d, normalizeToDecision as et, requireOrgRole as f, RoleHierarchy as g, requireTeamMembership as h, ownerWithAdminBypass as i, requireDPoP as it, ConnectEventsOptions as j, describePermissionMap as k, readOnly as l, requireServiceScope as m, authenticated as n, RequireMandateOptions as nt, presets_d_exports as o, requireScopeContext as p, roles as q, fullPublic as r, requireAgentScope as rt, publicRead as s, adminOnly as t, RequireAgentScopeOptions as tt, requireOrgInScope as u, GRANT_MODES as v, conjoinPolicyFilters as w, RequireGrantOptions as x, GrantMode as y, allowPublic as z };
993
+ //#region src/permissions/matrix.d.ts
994
+ type PermissionEntryType = "public" | "authenticated" | "roles" | "scoped";
995
+ interface PermissionEntry {
996
+ type: PermissionEntryType;
997
+ roles: string[];
998
+ /**
999
+ * Present only for `scoped` — the caller-scope dimensions the gate requires
1000
+ * (e.g. `{ branchRole: "head_office" }`), for the client to resolve against
1001
+ * the viewer's active context.
1002
+ */
1003
+ scope?: Record<string, unknown>;
1004
+ }
1005
+ /**
1006
+ * The slice of arc's `ResourceRegistry` this reads.
1007
+ *
1008
+ * Structural on purpose: coupling to the full registry type would drag the
1009
+ * resource layer into the permissions layer, and this only ever reads names
1010
+ * and gates.
1011
+ */
1012
+ interface PermissionMatrixRegistry {
1013
+ getAll(): ReadonlyArray<{
1014
+ name: string;
1015
+ permissions?: Record<string, unknown>;
1016
+ actions?: ReadonlyArray<{
1017
+ name: string;
1018
+ permissions?: unknown;
1019
+ }>;
1020
+ aggregations?: ReadonlyArray<{
1021
+ name: string;
1022
+ permissions?: unknown;
1023
+ }>;
1024
+ }>;
1025
+ }
1026
+ interface PermissionMatrixOptions {
1027
+ /** The live registry. Omit and the matrix carries only curated modules. */
1028
+ registry?: PermissionMatrixRegistry;
1029
+ /**
1030
+ * Curated, human-named groupings the client already organises around
1031
+ * (`products`, `finance`, …). Overlaid FIRST — the live registry wins on an
1032
+ * exact name collision, because the enforced gate beats an approximation.
1033
+ */
1034
+ curatedModules?: Record<string, unknown>;
1035
+ /**
1036
+ * Second curated layer, applied only where `curatedModules` has no entry —
1037
+ * typically per-resource policies behind the domain groupings.
1038
+ */
1039
+ fallbackModules?: Record<string, unknown>;
1040
+ /** Platform-level role names. */
1041
+ platformRoles?: readonly string[];
1042
+ /** Organization/branch-level role names. */
1043
+ orgRoles?: readonly string[];
1044
+ }
1045
+ interface PermissionMatrix {
1046
+ /** Every role name, both namespaces — so a role picker has one source. */
1047
+ roles: string[];
1048
+ roleGroups: {
1049
+ platform: string[];
1050
+ branch: string[];
1051
+ };
1052
+ modules: Record<string, Record<string, PermissionEntry>>;
1053
+ }
1054
+ /** Re-shape arc's typed requirement into the wire entry. */
1055
+ declare function introspectCheck(check: PermissionCheck): PermissionEntry;
1056
+ /** Introspect a permission module, flattening nested groups to `a.b`. */
1057
+ declare function introspectModule(mod: Record<string, unknown>): Record<string, PermissionEntry>;
1058
+ /** Every live resource's ACTUAL gates, keyed by arc resource name. */
1059
+ declare function introspectRegistry(registry: PermissionMatrixRegistry): Record<string, Record<string, PermissionEntry>>;
1060
+ declare function buildPermissionMatrix(options?: PermissionMatrixOptions): PermissionMatrix;
1061
+ //#endregion
1062
+ 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 };
package/dist/index.d.mts CHANGED
@@ -1,11 +1,12 @@
1
- import { $t as SlugExt, A as RequestIdOptions, An as ControllerConfigurableOptions, B as defineResource, Bt as RouteHandler, C as RequestContext, D as HealthCheck, Dn as ArcListResult, E as GracefulShutdownOptions, En as ArcGetResult, F as FastifyWithDecorators, Ft as ControllerLike, H as CrudController, Jt as BaseController, L as RequestWithExtras, Lt as IController, Mn as ListResult, N as FastifyRequestExtras, Nt as RateLimitConfig, O as HealthOptions, On as ArcUpdateResult, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as TreeMixin, Rt as IControllerResponse, S as QueryParserInterface, T as CrudRouterOptions, Tn as ArcDeleteResult, U as ResourceConfig, Ut as AuthPluginOptions, V as ResourceDefinition, X as CrudRouteKey, Xt as SoftDeleteMixin, Y as PresetResult, Yt as SoftDeleteExt, Z as CrudSchemas, Zt as TreeExt, a as InferAdapterDoc, c as TypedController, ct as AggMeasureShorthand, d as PaginationResult, dt as AggregationDateRangeRequirement, en as SlugMixin, et as RouteSchemaOptions, f as IntrospectionData, ft as AggregationIndexHint, g as ArcInternalMetadata, gt as AggregationsMap, h as ResourceMetadata, ht as AggregationRateLimit, i as ValidationResult, jn as ControllerConstructionOptions, k as IntrospectionPluginOptions, kn as BaseControllerOptions, l as TypedRepository, lt as AggregationCacheConfig, m as RegistryStats, mt as AggregationMaterializedResult, n as ConfigError, nn as BulkMixin, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, pt as AggregationMaterializedContext, q as PresetFunction, r as ValidateOptions, rn as BaseCrudController, s as InferResourceDoc, st as AggMeasureInput, t as RouteHandlerMethod, tn as BulkExt, u as TypedResourceConfig, ut as AggregationConfig, w as ServiceContext, wn as ArcCreateResult, y as OwnershipCheck, zt as IRequestContext } from "./index-Q5gzEIWY.mjs";
2
- import { a as UserBase, d as JWTPayload, i as PermissionContext, l as AnyRecord, m as UserOrganization, n as DataPolicy, r as PermissionCheck, t as AuthorizationDecision, u as ArcRequest } from "./types-ChvvVNP8.mjs";
3
- import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-D3lhgzhD.mjs";
4
- import "./fastify-augmentation-0WhPnUH7.mjs";
5
- import { A as DEFAULT_ID_FIELD, B as MAX_FILTER_DEPTH, D as defineAggregation, F as DEFAULT_UPDATE_METHOD, G as RESERVED_QUERY_PARAMS, H as MAX_SEARCH_LENGTH, I as HOOK_OPERATIONS, K as SYSTEM_FIELDS, L as HOOK_PHASES, M as DEFAULT_MAX_LIMIT, N as DEFAULT_SORT, O as CRUD_OPERATIONS, P as DEFAULT_TENANT_FIELD, R as HookOperation, S as mergeResourceConfig, U as MUTATION_OPERATIONS, V as MAX_REGEX_LENGTH, W as MutationOperation, b as ResourceSeams, j as DEFAULT_LIMIT, k as CrudOperation, p as getControllerScope, v as defineResourceVariants, w as defineAction, x as SeamedResourceConfig, y as AdapterLike, z as HookPhase } from "./index-Cx7bro4R.mjs";
6
- import { B as anyOf, F as createDynamicPermissionMatrix, G as requireOwnership, H as denyAll, I as createOrgPermissions, J as when, K as requireRoles, L as allOf, M as DynamicPermissionMatrix, N as DynamicPermissionMatrixConfig, W as requireAuth, c as publicReadAdminWrite, d as requireOrgMembership, f as requireOrgRole, h as requireTeamMembership, i as ownerWithAdminBypass, l as readOnly, m as requireServiceScope, n as authenticated, o as presets_d_exports, p as requireScopeContext, r as fullPublic, s as publicRead, t as adminOnly, u as requireOrgInScope, z as allowPublic } from "./index-Ch16aAah.mjs";
7
- import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-DHcHVAgk.mjs";
1
+
2
+ import { $t as TreeMixin, A as RequestIdOptions, An as BaseControllerOptions, B as defineResource, Bt as RawRouteHandler, C as RequestContext, D as HealthCheck, Dn as ArcGetResult, E as GracefulShutdownOptions, En as ArcDeleteResult, F as FastifyWithDecorators, Ft as ControllerLike, H as CrudController, L as RequestWithExtras, Lt as IController, Mn as ControllerConstructionOptions, N as FastifyRequestExtras, Nn as ListResult, Nt as RateLimitConfig, O as HealthOptions, On as ArcListResult, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as TreeExt, Rt as IControllerResponse, S as QueryParserInterface, T as CrudRouterOptions, Tn as ArcCreateResult, U as ResourceConfig, V as ResourceDefinition, Vt as RouteHandler, Wt as AuthPluginOptions, X as CrudRouteKey, Xt as SoftDeleteExt, Y as PresetResult, Yt as BaseController, Z as CrudSchemas, Zt as SoftDeleteMixin, a as InferAdapterDoc, c as TypedController, ct as AggMeasureShorthand, d as PaginationResult, dt as AggregationDateRangeRequirement, en as SlugExt, et as RouteSchemaOptions, f as IntrospectionData, ft as AggregationIndexHint, g as ArcInternalMetadata, gt as AggregationsMap, h as ResourceMetadata, ht as AggregationRateLimit, i as ValidationResult, in as BaseCrudController, jn as ControllerConfigurableOptions, k as IntrospectionPluginOptions, kn as ArcUpdateResult, l as TypedRepository, lt as AggregationCacheConfig, m as RegistryStats, mt as AggregationMaterializedResult, n as ConfigError, nn as BulkExt, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, pt as AggregationMaterializedContext, q as PresetFunction, r as ValidateOptions, rn as BulkMixin, s as InferResourceDoc, st as AggMeasureInput, t as RouteHandlerMethod, tn as SlugMixin, u as TypedResourceConfig, ut as AggregationConfig, w as ServiceContext, y as OwnershipCheck, zt as IRequestContext } from "./index-CpzxqePp.mjs";
3
+ import { a as UserBase, d as JWTPayload, i as PermissionContext, l as AnyRecord, m as UserOrganization, n as DataPolicy, r as PermissionCheck, t as AuthorizationDecision, u as ArcRequest } from "./types-B7XeLEgK.mjs";
4
+ import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-I_EeRWND.mjs";
5
+ import "./fastify-augmentation-BppG5bMT.mjs";
6
+ import { A as DEFAULT_ID_FIELD, B as MAX_FILTER_DEPTH, D as defineAggregation, F as DEFAULT_UPDATE_METHOD, G as RESERVED_QUERY_PARAMS, H as MAX_SEARCH_LENGTH, I as HOOK_OPERATIONS, K as SYSTEM_FIELDS, L as HOOK_PHASES, M as DEFAULT_MAX_LIMIT, N as DEFAULT_SORT, O as CRUD_OPERATIONS, P as DEFAULT_TENANT_FIELD, R as HookOperation, S as mergeResourceConfig, U as MUTATION_OPERATIONS, V as MAX_REGEX_LENGTH, W as MutationOperation, b as ResourceSeams, j as DEFAULT_LIMIT, k as CrudOperation, p as getControllerScope, v as defineResourceVariants, w as defineAction, x as SeamedResourceConfig, y as AdapterLike, z as HookPhase } from "./index-DXlHwvuE.mjs";
7
+ import { $ as requireAuth, C as requireServiceScope, G as createOrgPermissions, H as DynamicPermissionMatrixConfig, J as allowPublic, K as allOf, S as requireScopeContext, V as DynamicPermissionMatrix, W as createDynamicPermissionMatrix, Y as anyOf, Z as denyAll, _ as publicReadAdminWrite, b as requireOrgMembership, d as authenticated, et as requireOwnership, f as fullPublic, g as publicRead, h as presets_d_exports, it as when, nt as requireRoles, p as ownerWithAdminBypass, u as adminOnly, v as readOnly, w as requireTeamMembership, x as requireOrgRole, y as requireOrgInScope } from "./index-zq6VrjaB.mjs";
8
+ import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-BGdVwP25.mjs";
8
9
  //#region src/index.d.ts
9
10
  declare const version: string;
10
11
  //#endregion
11
- export { type AdapterLike, type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, type AnyRecord, type ArcCreateResult, type ArcDeleteResult, ArcError, type ArcGetResult, type ArcInternalMetadata, type ArcListResult, type ArcRequest, type ArcUpdateResult, type AuthPluginOptions, type AuthorizationDecision, BaseController, type BaseControllerOptions, BaseCrudController, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, type ControllerLike, type CrudController, type CrudOperation, type CrudRouteKey, type CrudRouterOptions, type CrudSchemas, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DataPolicy, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type EventDefinition, type FastifyRequestExtras, type FastifyWithAuth, type FastifyWithDecorators, type FieldPermission, type FieldPermissionMap, type FieldRule, ForbiddenError, type GracefulShutdownOptions, HOOK_OPERATIONS, HOOK_PHASES, type HealthCheck, type HealthOptions, type HookOperation, type HookPhase, type IController, type IControllerResponse, type IRequestContext, type InferAdapterDoc, type InferDocType, type InferResourceDoc, type IntrospectionData, type IntrospectionPluginOptions, type JWTPayload, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, type MiddlewareConfig, type MutationOperation, NotFoundError, type OwnershipCheck, type PaginationResult, type PermissionCheck, type PermissionContext, type PresetFunction, type PresetResult, type QueryParserInterface, RESERVED_QUERY_PARAMS, type RateLimitConfig, type RegistryEntry, type RegistryStats, type RequestContext, type RequestIdOptions, type RequestWithExtras, type ResourceConfig, ResourceDefinition, type ResourceMetadata, type ResourceSeams, type RouteHandler, type RouteHandlerMethod, type RouteSchemaOptions, SYSTEM_FIELDS, type SeamedResourceConfig, type ServiceContext, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type TypedController, type TypedRepository, type TypedResourceConfig, UnauthorizedError, type UserBase, type UserOrganization, type ValidateOptions, ValidationError, type ValidationResult, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, mergeResourceConfig, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
12
+ export { type AdapterLike, type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, type AnyRecord, type ArcCreateResult, type ArcDeleteResult, ArcError, type ArcGetResult, type ArcInternalMetadata, type ArcListResult, type ArcRequest, type ArcUpdateResult, type AuthPluginOptions, type AuthorizationDecision, BaseController, type BaseControllerOptions, BaseCrudController, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, type ControllerLike, type CrudController, type CrudOperation, type CrudRouteKey, type CrudRouterOptions, type CrudSchemas, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DataPolicy, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type EventDefinition, type FastifyRequestExtras, type FastifyWithAuth, type FastifyWithDecorators, type FieldPermission, type FieldPermissionMap, type FieldRule, ForbiddenError, type GracefulShutdownOptions, HOOK_OPERATIONS, HOOK_PHASES, type HealthCheck, type HealthOptions, type HookOperation, type HookPhase, type IController, type IControllerResponse, type IRequestContext, type InferAdapterDoc, type InferDocType, type InferResourceDoc, type IntrospectionData, type IntrospectionPluginOptions, type JWTPayload, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, type MiddlewareConfig, type MutationOperation, NotFoundError, type OwnershipCheck, type PaginationResult, type PermissionCheck, type PermissionContext, type PresetFunction, type PresetResult, type QueryParserInterface, RESERVED_QUERY_PARAMS, type RateLimitConfig, type RawRouteHandler, type RegistryEntry, type RegistryStats, type RequestContext, type RequestIdOptions, type RequestWithExtras, type ResourceConfig, ResourceDefinition, type ResourceMetadata, type ResourceSeams, type RouteHandler, type RouteHandlerMethod, type RouteSchemaOptions, SYSTEM_FIELDS, type SeamedResourceConfig, type ServiceContext, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type TypedController, type TypedRepository, type TypedResourceConfig, UnauthorizedError, type UserBase, type UserOrganization, type ValidateOptions, ValidationError, type ValidationResult, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, mergeResourceConfig, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
package/dist/index.mjs CHANGED
@@ -1,13 +1,14 @@
1
- import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "./constants-DNre0wRg.mjs";
2
- import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-DkO8Nk6-.mjs";
3
- import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-B5DwufbB.mjs";
4
- import { n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "./fields-CQ_7KQWw.mjs";
5
- import { a as ResourceDefinition, t as defineResource } from "./defineResource-CxWqDCAy.mjs";
6
- import { c as getControllerScope } from "./pipeline-BJnpkY9i.mjs";
7
- import { t as defineAggregation } from "./defineAggregation-ufWjUwml.mjs";
8
- import { a as mergeResourceConfig, i as defineResourceVariants, o as defineAction } from "./core-poalJLvp.mjs";
9
- import { B as when, C as requireScopeContext, I as requireAuth, L as requireOwnership, M as anyOf, P as denyAll, R as requireRoles, S as requireOrgRole, T as requireTeamMembership, b as requireOrgInScope, c as publicReadAdminWrite, i as ownerWithAdminBypass, j as allowPublic, k as allOf, l as readOnly, n as authenticated, o as presets_exports, r as fullPublic, s as publicRead, t as adminOnly, v as createDynamicPermissionMatrix, w as requireServiceScope, x as requireOrgMembership, y as createOrgPermissions } from "./permissions-Bfu_8y1U.mjs";
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
2
+ import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "./constants-J99LGTJI.mjs";
3
+ import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-Bh1KK5ps.mjs";
4
+ import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-Dk34dxhI.mjs";
5
+ import { n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "./fields-DEi65pGj.mjs";
6
+ import { a as ResourceDefinition, t as defineResource } from "./defineResource-XFPPUu2c.mjs";
7
+ import { c as getControllerScope } from "./pipeline-CPA-jx0M.mjs";
8
+ import { t as defineAggregation } from "./defineAggregation-gX4No1gt.mjs";
9
+ import { a as mergeResourceConfig, i as defineResourceVariants, o as defineAction } from "./core-BwwmNSp7.mjs";
10
+ import { B as requireAuth, C as createOrgPermissions, D as requireScopeContext, E as requireOrgRole, F as allowPublic, G as when, I as anyOf, N as allOf, O as requireServiceScope, R as denyAll, S as createDynamicPermissionMatrix, T as requireOrgMembership, U as requireRoles, V as requireOwnership, a as adminOnly, c as ownerWithAdminBypass, d as publicRead, f as publicReadAdminWrite, k as requireTeamMembership, o as authenticated, p as readOnly, s as fullPublic, u as presets_exports, w as requireOrgInScope } from "./permissions-Dl_m0NCe.mjs";
10
11
  //#region src/index.ts
11
- const version = "2.30.0";
12
+ const version = "2.32.0";
12
13
  //#endregion
13
14
  export { ArcError, BaseController, BaseCrudController, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, ForbiddenError, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, NotFoundError, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, mergeResourceConfig, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
2
  import * as fs from "node:fs/promises";
2
3
  import * as path from "node:path";
3
4
  import { dirname, join } from "node:path";
@@ -459,6 +460,11 @@ export async function createAppInstance()${ts ? ": Promise<FastifyInstance>" : "
459
460
  preset: config.env === 'production' ? (${config.edge ? "'edge'" : "'production'"}) : 'development',
460
461
  resources,
461
462
  resourcePrefix: '/api',
463
+ // Arc registers the error handler itself (CastError → 400, validation →
464
+ // 422, duplicate key → 409). Configure it HERE — registering
465
+ // errorHandlerPlugin again in your own plugins file overrides arc's in the
466
+ // same scope and boots with an FSTWRN004 warning.
467
+ errorHandler: { includeStack: config.isDev },
462
468
  ${authConfig}
463
469
  cors: {
464
470
  origin: config.cors.origins,
@@ -608,8 +614,7 @@ export const authResource = defineResource({
608
614
  path: '/register',
609
615
  summary: 'Register new user',
610
616
  permissions: allowPublic(),
611
- handler: handlers.register,
612
- raw: true,
617
+ rawHandler: handlers.register,
613
618
  schema: { body: schemas.registerBody, response: { 201: schemas.successResponse } },
614
619
  },
615
620
  {
@@ -617,8 +622,7 @@ export const authResource = defineResource({
617
622
  path: '/login',
618
623
  summary: 'User login',
619
624
  permissions: allowPublic(),
620
- handler: handlers.login,
621
- raw: true,
625
+ rawHandler: handlers.login,
622
626
  schema: { body: schemas.loginBody, response: { 200: schemas.loginResponse } },
623
627
  },
624
628
  {
@@ -626,8 +630,7 @@ export const authResource = defineResource({
626
630
  path: '/refresh',
627
631
  summary: 'Refresh access token',
628
632
  permissions: allowPublic(),
629
- handler: handlers.refreshToken,
630
- raw: true,
633
+ rawHandler: handlers.refreshToken,
631
634
  schema: { body: schemas.refreshBody, response: { 200: schemas.tokenResponse } },
632
635
  },
633
636
  {
@@ -635,8 +638,7 @@ export const authResource = defineResource({
635
638
  path: '/forgot-password',
636
639
  summary: 'Request password reset',
637
640
  permissions: allowPublic(),
638
- handler: handlers.forgotPassword,
639
- raw: true,
641
+ rawHandler: handlers.forgotPassword,
640
642
  schema: { body: schemas.forgotBody, response: { 200: schemas.successResponse } },
641
643
  },
642
644
  {
@@ -644,8 +646,7 @@ export const authResource = defineResource({
644
646
  path: '/reset-password',
645
647
  summary: 'Reset password with token',
646
648
  permissions: allowPublic(),
647
- handler: handlers.resetPassword,
648
- raw: true,
649
+ rawHandler: handlers.resetPassword,
649
650
  schema: { body: schemas.resetBody, response: { 200: schemas.successResponse } },
650
651
  },
651
652
  ],
@@ -669,8 +670,7 @@ export const userProfileResource = defineResource({
669
670
  path: '/me',
670
671
  summary: 'Get current user profile',
671
672
  permissions: requireAuth(),
672
- handler: handlers.getUserProfile,
673
- raw: true,
673
+ rawHandler: handlers.getUserProfile,
674
674
  schema: { response: { 200: schemas.userProfileResponse } },
675
675
  },
676
676
  {
@@ -678,8 +678,7 @@ export const userProfileResource = defineResource({
678
678
  path: '/me',
679
679
  summary: 'Update current user profile',
680
680
  permissions: requireAuth(),
681
- handler: handlers.updateUserProfile,
682
- raw: true,
681
+ rawHandler: handlers.updateUserProfile,
683
682
  schema: { body: schemas.updateUserBody, response: { 200: schemas.userProfileResponse } },
684
683
  },
685
684
  ],
@@ -998,7 +997,7 @@ export async function updateUserProfile(request${ts ? ": FastifyRequest" : ""},
998
997
  delete updates.role;
999
998
  delete updates.organizations;
1000
999
 
1001
- const user = await userRepository.Model.findByIdAndUpdate(userId, updates, { new: true });
1000
+ const user = await userRepository.Model.findByIdAndUpdate(userId, updates, { returnDocument: 'after' });
1002
1001
  return reply.send(user);
1003
1002
  } catch (error) {
1004
1003
  request.log.error({ err: error }, 'Update profile error');
@@ -2380,7 +2379,8 @@ export const requireAdmin = ()${returnType} =>
2380
2379
  export const requireSuperadmin = ()${returnType} =>
2381
2380
  requireRoles(['superadmin']);
2382
2381
  `;
2383
- if (config.tenant === "multi") if (config.auth === "better-auth") content += `
2382
+ if (config.tenant === "multi") {
2383
+ if (config.auth === "better-auth") content += `
2384
2384
  // ============================================================================
2385
2385
  // Better Auth Organization & Team Permission Helpers
2386
2386
  // ============================================================================
@@ -2432,7 +2432,7 @@ export const requireOrgManager = ()${returnType} =>
2432
2432
  export const requireOrgStaff = ()${returnType} =>
2433
2433
  requireOrgMembership();
2434
2434
  `;
2435
- else content += `
2435
+ else content += `
2436
2436
  /**
2437
2437
  * Require organization owner (elevated scope auto-bypasses)
2438
2438
  */
@@ -2451,6 +2451,7 @@ export const requireOrgManager = ()${returnType} =>
2451
2451
  export const requireOrgStaff = ()${returnType} =>
2452
2452
  requireRoles(['owner', 'manager', 'staff', 'admin', 'superadmin']);
2453
2453
  `;
2454
+ }
2454
2455
  content += `
2455
2456
  // ============================================================================
2456
2457
  // Standard Permission Sets
@@ -2533,7 +2534,6 @@ function pluginsIndexTemplate(config) {
2533
2534
  */
2534
2535
 
2535
2536
  ${typeImport}${ts ? "import type { AppConfig } from '../config/index.js';\n" : ""}import { openApiPlugin, scalarPlugin } from '@classytic/arc/docs';
2536
- import { errorHandlerPlugin } from '@classytic/arc/plugins';
2537
2537
  `;
2538
2538
  content += `
2539
2539
  /**
@@ -2546,12 +2546,9 @@ export async function registerPlugins(
2546
2546
  app${appType},
2547
2547
  deps${configType}
2548
2548
  )${ts ? ": Promise<void>" : ""} {
2549
- const { config } = deps;
2550
-
2551
- // Error handling (CastError → 400, validation → 422, duplicate → 409)
2552
- await app.register(errorHandlerPlugin, {
2553
- includeStack: config.isDev,
2554
- });
2549
+ // NOTE: no error handler here — arc registers it inside createApp().
2550
+ // Configure it via createApp({ errorHandler: { includeStack } }) in app.ts.
2551
+ // Registering it again would override arc's in the same scope (FSTWRN004).
2555
2552
 
2556
2553
  // API Documentation (Scalar UI)
2557
2554
  // OpenAPI spec: /_docs/openapi.json
@@ -2567,8 +2564,9 @@ export async function registerPlugins(
2567
2564
  theme: 'default',
2568
2565
  });
2569
2566
 
2570
- // Add your custom plugins here:
2571
- // await app.register(myCustomPlugin, { ...options });
2567
+ // Add your custom plugins here — deps carries your config and services:
2568
+ // const { config } = deps;
2569
+ // await app.register(myCustomPlugin, { apiKey: config.someKey });
2572
2570
  }
2573
2571
  `;
2574
2572
  return content;
@@ -3020,7 +3018,7 @@ class UserRepository extends Repository${ts ? "<UserDocument>" : ""} {
3020
3018
  return this.Model.findByIdAndUpdate(
3021
3019
  userId,
3022
3020
  { resetPasswordToken: token, resetPasswordExpires: expiresAt },
3023
- { new: true }
3021
+ { returnDocument: 'after' }
3024
3022
  );
3025
3023
  }
3026
3024
  ${config.tenant === "multi" ? `
@@ -1,3 +1,4 @@
1
+
1
2
  //#region src/cli/commands/init/types.d.ts
2
3
  /**
3
4
  * Shared types for the `arc init` scaffolder.
@@ -1,5 +1,6 @@
1
- import { n as DomainEvent } from "../EventTransport-QmY7A258.mjs";
2
- import { c as WebSocketClient, l as WebSocketMessage } from "../websocket-_Pd0CgR0.mjs";
1
+
2
+ import { n as DomainEvent } from "../EventTransport-2uVV34WU.mjs";
3
+ import { c as WebSocketClient, l as WebSocketMessage } from "../websocket-BOXVggMf.mjs";
3
4
  import { FastifyPluginAsync, FastifyRequest } from "fastify";
4
5
  //#region src/integrations/event-gateway.d.ts
5
6
  interface EventGatewayOptions {
@@ -1,10 +1,11 @@
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
2
  import fp from "fastify-plugin";
2
3
  //#region src/integrations/event-gateway.ts
3
4
  const eventGatewayPluginImpl = async (fastify, opts = {}) => {
4
5
  const { auth = true, orgScoped = false, roomPolicy, maxMessageBytes, maxSubscriptionsPerClient, authenticate } = opts;
5
6
  if (auth && !authenticate && !fastify.hasDecorator("authenticate")) throw new Error("[arc-event-gateway] auth is true but fastify.authenticate is not registered. Register an auth plugin first, provide a custom authenticate function, or set auth: false.");
6
7
  if (opts.sse !== false) {
7
- const { default: ssePlugin } = await import("../sse-BQ1w0dfl.mjs").then((n) => n.r);
8
+ const { default: ssePlugin } = await import("../sse-B9P4Y-UI.mjs").then((n) => n.r);
8
9
  await fastify.register(ssePlugin, {
9
10
  path: opts.sse?.path ?? "/events/stream",
10
11
  requireAuth: auth,
@@ -1,7 +1,8 @@
1
- import { c as WebSocketClient, l as WebSocketMessage, u as WebSocketPluginOptions } from "../websocket-_Pd0CgR0.mjs";
1
+
2
+ import { c as WebSocketClient, l as WebSocketMessage, u as WebSocketPluginOptions } from "../websocket-BOXVggMf.mjs";
2
3
  import { EventGatewayOptions } from "./event-gateway.mjs";
3
- import { a as JobMeta, c as JobsPluginOptions, i as JobDispatcher, l as QueueStats, n as JobDefinition, r as JobDispatchOptions } from "../index-CG4yqMDB.mjs";
4
- import { _ as ToolDefinition, c as McpAuthResult, d as McpResourceConfig, f as PromptDefinition, g as ToolContext, h as ToolAnnotations, n as CallToolResult, o as CrudOperation, r as CreateMcpServerConfig, t as BetterAuthHandler, u as McpPluginOptions } from "../types-Bmmn-fO0.mjs";
4
+ import { a as JobMeta, c as JobsPluginOptions, i as JobDispatcher, l as QueueStats, n as JobDefinition, r as JobDispatchOptions } from "../index-C-481Zf2.mjs";
5
+ import { _ as ToolDefinition, c as McpAuthResult, d as McpResourceConfig, f as PromptDefinition, g as ToolContext, h as ToolAnnotations, n as CallToolResult, o as CrudOperation, r as CreateMcpServerConfig, t as BetterAuthHandler, u as McpPluginOptions } from "../types-CwcUQ610.mjs";
5
6
  import { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike } from "./streamline.mjs";
6
7
  import { WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription } from "./webhooks.mjs";
7
8
  export type { BetterAuthHandler, CallToolResult, CreateMcpServerConfig, CrudOperation, EventGatewayOptions, JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, McpAuthResult, McpPluginOptions, McpResourceConfig, PromptDefinition, QueueStats, StreamlinePluginOptions, ToolAnnotations, ToolContext, ToolDefinition, WebSocketClient, WebSocketMessage, WebSocketPluginOptions, WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription, WorkflowLike, WorkflowRunLike };
@@ -1 +1,2 @@
1
+ /*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
1
2
  export {};
@@ -1,2 +1,3 @@
1
- import { a as JobMeta, c as JobsPluginOptions, d as ExecuteTimedHandlerOptions, f as TimedHandlerLogger, i as JobDispatcher, l as QueueStats, n as JobDefinition, o as JobRepeatOptions, p as executeTimedHandler, r as JobDispatchOptions, s as JobStatus, t as jobsPlugin, u as defineJob } from "../../index-CG4yqMDB.mjs";
1
+
2
+ import { a as JobMeta, c as JobsPluginOptions, d as ExecuteTimedHandlerOptions, f as TimedHandlerLogger, i as JobDispatcher, l as QueueStats, n as JobDefinition, o as JobRepeatOptions, p as executeTimedHandler, r as JobDispatchOptions, s as JobStatus, t as jobsPlugin, u as defineJob } from "../../index-C-481Zf2.mjs";
2
3
  export { type ExecuteTimedHandlerOptions, type JobDefinition, type JobDispatchOptions, type JobDispatcher, type JobMeta, type JobRepeatOptions, type JobStatus, type JobsPluginOptions, type QueueStats, type TimedHandlerLogger, defineJob, executeTimedHandler, jobsPlugin };