@classytic/arc 2.30.0 → 2.31.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 (239) 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-De7GqHck.mjs} +16 -17
  5. package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
  6. package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-9mlTgqzE.mjs} +1 -0
  7. package/dist/{HookSystem-WkIougo6.mjs → HookSystem-BcmPyq5I.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-qq0mn2s9.mjs} +3 -2
  10. package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-BE5NwaQk.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 +6 -5
  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-ChvUQGG1.mjs} +19 -10
  20. package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-CDrCJzmB.mjs} +4 -3
  21. package/dist/cache/index.d.mts +4 -3
  22. package/dist/cache/index.mjs +4 -3
  23. package/dist/{caching-_NJeDd1_.mjs → caching-BFHA6Scf.mjs} +2 -1
  24. package/dist/cleanup/index.d.mts +4 -3
  25. package/dist/cleanup/index.mjs +9 -13
  26. package/dist/cli/commands/describe.d.mts +2 -1
  27. package/dist/cli/commands/describe.mjs +3 -2
  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-D3Dv4LAV.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-BGpIxINN.mjs} +3 -2
  46. package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-CDXEdasl.mjs} +8 -7
  47. package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-KrQDzx-k.mjs} +7 -6
  48. package/dist/{createApp-CXrKFciH.mjs → createApp-Df89BEni.mjs} +484 -209
  49. package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-DbPPS8RI.mjs} +1 -0
  50. package/dist/{defineResource-CxWqDCAy.mjs → defineResource-Bv6EtN1x.mjs} +63 -38
  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-D2l1mh4g.mjs} +4 -3
  57. package/dist/encryption/index.d.mts +2 -1
  58. package/dist/encryption/index.mjs +3 -2
  59. package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-C5NeD6bT.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-Cj42AntO.mjs} +1 -0
  63. package/dist/{eventPlugin-D2NNR4py.mjs → eventPlugin-CkffEihm.mjs} +5 -4
  64. package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
  65. package/dist/events/index.d.mts +4 -3
  66. package/dist/events/index.mjs +16 -4
  67. package/dist/events/transports/redis-stream-entry.d.mts +2 -1
  68. package/dist/events/transports/redis-stream-entry.mjs +1 -0
  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 +7 -6
  74. package/dist/{fastify-augmentation-0WhPnUH7.d.mts → fastify-augmentation-zh0_AYHa.d.mts} +13 -4
  75. package/dist/{fields-CQ_7KQWw.mjs → fields-CB5Cuzk9.mjs} +1 -0
  76. package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
  77. package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
  78. package/dist/{generate-D0wZupBg.mjs → generate-EcA6ui4i.mjs} +2 -1
  79. package/dist/{headers-BvlQSDMB.mjs → headers-3zvE0rM3.mjs} +2 -1
  80. package/dist/{health-CB_m4S32.mjs → health-DjZYjM7H.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 +4 -3
  85. package/dist/idempotency/redis.d.mts +2 -1
  86. package/dist/idempotency/redis.mjs +1 -0
  87. package/dist/{index-Cx7bro4R.d.mts → index-Bc2ox8_U.d.mts} +5 -4
  88. package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
  89. package/dist/{index-Ch16aAah.d.mts → index-CEJNZFtX.d.mts} +53 -15
  90. package/dist/index-CFThn1K9.d.mts +224 -0
  91. package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
  92. package/dist/index.d.mts +9 -8
  93. package/dist/index.mjs +11 -10
  94. package/dist/{init-tlRSt667.mjs → init-BEiNZBsJ.mjs} +19 -23
  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 +108 -32
  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 +1 -0
  116. package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
  117. package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
  118. package/dist/{interface-n5hpKg1d.mjs → interface-DYzM0q-u.mjs} +1 -0
  119. package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-BYbLDi5D.mjs} +2 -1
  120. package/dist/{keys-Cd316u_y.mjs → keys-C0_pa1tY.mjs} +1 -0
  121. package/dist/{loadResources-DpU8pfjV.mjs → loadResources-yawi9tAE.mjs} +2 -1
  122. package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-BAjYZonx.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-B_es0hiF.mjs} +22 -23
  126. package/dist/{memory-CmnzXE5Z.mjs → memory-DR6wpa9F.mjs} +2 -1
  127. package/dist/{metrics-fdxI5mn_.mjs → metrics-CUdw_wLB.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 +2 -1
  132. package/dist/module-0pFJA6YW.mjs +78 -0
  133. package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-wOgj_fnj.mjs} +1 -0
  134. package/dist/{openapi-B8Vkbxbn.mjs → openapi-B2L4js1v.mjs} +6 -5
  135. package/dist/permissions/index.d.mts +5 -4
  136. package/dist/permissions/index.mjs +6 -5
  137. package/dist/{permissions-Bfu_8y1U.mjs → permissions-L--QDAir.mjs} +214 -41
  138. package/dist/{pipe-BOLmGIxa.mjs → pipe-DRDNsI2T.mjs} +2 -1
  139. package/dist/pipeline/index.d.mts +2 -1
  140. package/dist/pipeline/index.mjs +2 -1
  141. package/dist/{pipeline-BJnpkY9i.mjs → pipeline-UPQFatit.mjs} +6 -5
  142. package/dist/plugins/index.d.mts +8 -7
  143. package/dist/plugins/index.mjs +16 -15
  144. package/dist/plugins/response-cache.d.mts +1 -0
  145. package/dist/plugins/response-cache.mjs +2 -1
  146. package/dist/plugins/tracing-entry.d.mts +2 -1
  147. package/dist/plugins/tracing-entry.mjs +2 -1
  148. package/dist/{pluralize-BhrgwZb9.mjs → pluralize-O0FZgESl.mjs} +1 -0
  149. package/dist/{preloadResources-DCfa2egz.d.mts → preloadResources-CyoJMSiO.d.mts} +117 -12
  150. package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-Dz6BjzM6.mjs} +1 -0
  151. package/dist/presets/filesUpload.d.mts +6 -5
  152. package/dist/presets/filesUpload.mjs +9 -11
  153. package/dist/presets/index.d.mts +3 -2
  154. package/dist/presets/index.mjs +2 -1
  155. package/dist/presets/multiTenant.d.mts +2 -1
  156. package/dist/presets/multiTenant.mjs +3 -2
  157. package/dist/presets/search.d.mts +3 -2
  158. package/dist/presets/search.mjs +2 -1
  159. package/dist/{presets-CJOEXLuk.mjs → presets-C4-g4_4P.mjs} +4 -3
  160. package/dist/{projection-UBDgfMwu.mjs → projection-BHw6xlOQ.mjs} +2 -1
  161. package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
  162. package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-BZr8v46E.mjs} +5 -4
  163. package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
  164. package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-CMPY5Qms.mjs} +7 -3
  165. package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-Dn5JNmkj.mjs} +1 -0
  166. package/dist/{realtime-B9nmIY5V.mjs → realtime-C5NoxWFY.mjs} +20 -9
  167. package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
  168. package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
  169. package/dist/{registerRoute-JkxIEBJq.mjs → registerRoute-CBN84fc7.mjs} +4 -3
  170. package/dist/registry/index.d.mts +3 -2
  171. package/dist/registry/index.mjs +3 -2
  172. package/dist/{registry-BYXUUg21.mjs → registry-4213U4zb.mjs} +2 -1
  173. package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-Dll8mGgc.mjs} +1 -0
  174. package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DIiZKGUt.mjs} +2 -1
  175. package/dist/{repositoryFilter-Dz8k3S4P.mjs → repositoryFilter-f9eAfq_l.mjs} +1 -0
  176. package/dist/{requestContext-MrlJwECf.mjs → requestContext-2TxXOJ7T.mjs} +1 -0
  177. package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-CUsjNX9R.mjs} +1 -0
  178. package/dist/{schedules-CjOd2MG9.mjs → schedules-DdtlICTf.mjs} +3 -2
  179. package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-D--wdJM-.mjs} +70 -17
  180. package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-Bm2enbnh.mjs} +2 -1
  181. package/dist/schemas/index.d.mts +1 -0
  182. package/dist/schemas/index.mjs +1 -0
  183. package/dist/scim/index.d.mts +1 -0
  184. package/dist/scim/index.mjs +2 -1
  185. package/dist/scope/index.d.mts +3 -2
  186. package/dist/scope/index.mjs +5 -4
  187. package/dist/{scope-DfaPntpo.mjs → scope-DHx5Fous.mjs} +4 -3
  188. package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
  189. package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-DjQJ7FKA.mjs} +1 -0
  190. package/dist/{sse-BQ1w0dfl.mjs → sse-CUTo9y0X.mjs} +5 -4
  191. package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B_5XcVVd.mjs} +2 -1
  192. package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
  193. package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-D1MP_gRG.mjs} +1 -0
  194. package/dist/{streaming-BQcW6_Kq.mjs → streaming-PSZwi8JV.mjs} +1 -0
  195. package/dist/{subscribe-helpers-DfzsivM6.mjs → subscribe-helpers-C0Tb2aUp.mjs} +2 -1
  196. package/dist/sync/changelog.d.mts +1 -0
  197. package/dist/sync/changelog.mjs +1 -0
  198. package/dist/testing/cleanupStoreContract.d.mts +2 -1
  199. package/dist/testing/cleanupStoreContract.mjs +1 -0
  200. package/dist/testing/index.d.mts +139 -12
  201. package/dist/testing/index.mjs +230 -16
  202. package/dist/testing/outboxStoreContract.d.mts +1 -0
  203. package/dist/testing/outboxStoreContract.mjs +1 -0
  204. package/dist/testing/storageContract.d.mts +2 -1
  205. package/dist/testing/storageContract.mjs +1 -0
  206. package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
  207. package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-dAfBVUrk.mjs} +1 -0
  208. package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B0ryPo3I.mjs} +1 -0
  209. package/dist/types/index.d.mts +6 -5
  210. package/dist/types/index.mjs +1 -0
  211. package/dist/types/storage.d.mts +2 -1
  212. package/dist/types/storage.mjs +1 -0
  213. package/dist/{types-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
  214. package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
  215. package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
  216. package/dist/{types-D_n8L6VY.d.mts → types-CBgvkp8O.d.mts} +51 -12
  217. package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
  218. package/dist/{types-Bmmn-fO0.d.mts → types-CwcUQ610.d.mts} +2 -6
  219. package/dist/{types-CSyCxl2V.mjs → types-Cys0ko9Z.mjs} +4 -3
  220. package/dist/usage/index.d.mts +3 -2
  221. package/dist/usage/index.mjs +0 -0
  222. package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-ChYJ6CdK.mjs} +1 -0
  223. package/dist/utils/index.d.mts +16 -7
  224. package/dist/utils/index.mjs +10 -9
  225. package/dist/{utils-taUVD4p3.mjs → utils-vL8BrDE2.mjs} +3 -2
  226. package/dist/{validate-Bk44F2yT.mjs → validate-_KbifpHF.mjs} +2 -1
  227. package/dist/{versioning-gKWyryT3.mjs → versioning-CHDTor3P.mjs} +3 -2
  228. package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
  229. package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
  230. package/package.json +547 -539
  231. package/skills/arc/SKILL.md +22 -8
  232. package/skills/arc/references/api-reference.md +4 -0
  233. package/skills/arc/references/auth.md +3 -0
  234. package/skills/arc/references/integrations.md +33 -0
  235. package/skills/arc/references/mcp.md +6 -7
  236. package/skills/arc/references/production.md +24 -25
  237. package/skills/arc-code-review/references/anti-patterns.md +3 -3
  238. package/dist/index-CCzVR-N3.d.mts +0 -107
  239. package/dist/module-_-M7C5ES.mjs +0 -29
@@ -1,4 +1,5 @@
1
- import { a as UserBase, c as normalizeRoles, i as PermissionContext, n as DataPolicy, r as PermissionCheck, s as getUserRoles, t as AuthorizationDecision } from "../types-ChvvVNP8.mjs";
2
- import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-D3lhgzhD.mjs";
3
- import { $ as evaluatePermissionDecision, A as explainAccess, B as anyOf, C as requireGrant, D as collectPublicSurface, E as PermissionRequirement, 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, O as describePermission, P as PermissionEventBus, Q as applyPermissionResult, R as allow, S as modeSatisfies, T as AccessExplanation, U as not, V as deny, W as requireAuth, X as PermissionCheckReturn, Y as scopeOf, Z as applyAuthorizationDecision, _ as createRoleHierarchy, a as permissionMatrix, at as requireMandate, b as GrantResolution, c as publicReadAdminWrite, d as requireOrgMembership, et as normalizeToDecision, f as requireOrgRole, g as RoleHierarchy, h as requireTeamMembership, i as ownerWithAdminBypass, it as requireDPoP, j as ConnectEventsOptions, k as describePermissionMap, l as readOnly, m as requireServiceScope, n as authenticated, nt as RequireMandateOptions, o as presets_d_exports, p as requireScopeContext, q as roles, r as fullPublic, rt as requireAgentScope, s as publicRead, t as adminOnly, tt as RequireAgentScopeOptions, u as requireOrgInScope, v as GRANT_MODES, w as conjoinPolicyFilters, x as RequireGrantOptions, y as GrantMode, z as allowPublic } from "../index-Ch16aAah.mjs";
4
- export { type AccessExplanation, type AuthorizationDecision, type ConnectEventsOptions, type DataPolicy, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type FieldPermission, type FieldPermissionMap, type FieldPermissionType, GRANT_MODES, type GrantMode, type GrantResolution, type PermissionCheck, type PermissionCheckReturn, type PermissionContext, type PermissionEventBus, type PermissionRequirement, type RequireAgentScopeOptions, type RequireGrantOptions, type RequireMandateOptions, type RoleHierarchy, type UserBase, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
1
+
2
+ import { a as UserBase, c as normalizeRoles, i as PermissionContext, n as DataPolicy, r as PermissionCheck, s as getUserRoles, t as AuthorizationDecision } from "../types-B7XeLEgK.mjs";
3
+ import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-I_EeRWND.mjs";
4
+ import { $ as evaluatePermissionDecision, A as explainAccess, B as anyOf, C as requireGrant, D as collectPublicSurface, E as PermissionRequirement, F as createDynamicPermissionMatrix, G as requireOwnership, H as denyAll, I as createOrgPermissions, J as roles, K as requirePlatformRole, L as allOf, M as DynamicPermissionMatrix, N as DynamicPermissionMatrixConfig, O as describePermission, P as PermissionEventBus, Q as applyAuthorizationDecision, R as allow, S as modeSatisfies, T as AccessExplanation, U as not, V as deny, W as requireAuth, X as scopeOf, Y as when, Z as PermissionCheckReturn, _ as createRoleHierarchy, a as permissionMatrix, at as requireMandate, b as GrantResolution, c as publicReadAdminWrite, d as requireOrgMembership, et as normalizeToDecision, f as requireOrgRole, g as RoleHierarchy, h as requireTeamMembership, i as ownerWithAdminBypass, it as requireDPoP, j as ConnectEventsOptions, k as describePermissionMap, l as readOnly, m as requireServiceScope, n as authenticated, nt as RequireMandateOptions, o as presets_d_exports, p as requireScopeContext, q as requireRoles, r as fullPublic, rt as requireAgentScope, s as publicRead, t as adminOnly, tt as RequireAgentScopeOptions, u as requireOrgInScope, v as GRANT_MODES, w as conjoinPolicyFilters, x as RequireGrantOptions, y as GrantMode, z as allowPublic } from "../index-CEJNZFtX.mjs";
5
+ export { type AccessExplanation, type AuthorizationDecision, type ConnectEventsOptions, type DataPolicy, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type FieldPermission, type FieldPermissionMap, type FieldPermissionType, GRANT_MODES, type GrantMode, type GrantResolution, type PermissionCheck, type PermissionCheckReturn, type PermissionContext, type PermissionEventBus, type PermissionRequirement, type RequireAgentScopeOptions, type RequireGrantOptions, type RequireMandateOptions, type RoleHierarchy, type UserBase, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requirePlatformRole, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
@@ -1,5 +1,6 @@
1
- import { n as getUserRoles, r as normalizeRoles } from "../userHelpers-Cg_y3fBz.mjs";
2
- import { a as normalizeToDecision, i as evaluatePermissionDecision, n as applyPermissionResult, o as conjoinPolicyFilters, t as applyAuthorizationDecision } from "../applyPermissionResult-Cf6zUCvb.mjs";
3
- import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-CQ_7KQWw.mjs";
4
- import { A as allow, B as when, C as requireScopeContext, D as requireDPoP, E as requireAgentScope, F as not, I as requireAuth, L as requireOwnership, M as anyOf, N as deny, O as requireMandate, P as denyAll, R as requireRoles, S as requireOrgRole, T as requireTeamMembership, V as scopeOf, _ as explainAccess, a as permissionMatrix, b as requireOrgInScope, c as publicReadAdminWrite, d as GRANT_MODES, f as modeSatisfies, g as describePermissionMap, h as describePermission, i as ownerWithAdminBypass, j as allowPublic, k as allOf, l as readOnly, m as collectPublicSurface, n as authenticated, o as presets_exports, p as requireGrant, r as fullPublic, s as publicRead, t as adminOnly, u as createRoleHierarchy, v as createDynamicPermissionMatrix, w as requireServiceScope, x as requireOrgMembership, y as createOrgPermissions, z as roles } from "../permissions-Bfu_8y1U.mjs";
5
- export { GRANT_MODES, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { a as conjoinPolicyFilters, i as normalizeToDecision, r as evaluatePermissionDecision, t as applyAuthorizationDecision } from "../authorizationDecision-ChvUQGG1.mjs";
3
+ import { n as getUserRoles, r as normalizeRoles } from "../userHelpers-ChYJ6CdK.mjs";
4
+ import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-CB5Cuzk9.mjs";
5
+ import { A as allow, B as roles, C as requireScopeContext, D as requireDPoP, E as requireAgentScope, F as not, H as scopeOf, I as requireAuth, L as requireOwnership, M as anyOf, N as deny, O as requireMandate, P as denyAll, R as requirePlatformRole, S as requireOrgRole, T as requireTeamMembership, V as when, _ as explainAccess, a as permissionMatrix, b as requireOrgInScope, c as publicReadAdminWrite, d as GRANT_MODES, f as modeSatisfies, g as describePermissionMap, h as describePermission, i as ownerWithAdminBypass, j as allowPublic, k as allOf, l as readOnly, m as collectPublicSurface, n as authenticated, o as presets_exports, p as requireGrant, r as fullPublic, s as publicRead, t as adminOnly, u as createRoleHierarchy, v as createDynamicPermissionMatrix, w as requireServiceScope, x as requireOrgMembership, y as createOrgPermissions, z as requireRoles } from "../permissions-L--QDAir.mjs";
6
+ export { GRANT_MODES, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requirePlatformRole, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
@@ -1,9 +1,10 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
2
3
  import { arcLog } from "./logger/index.mjs";
3
- import { n as getUserRoles } from "./userHelpers-Cg_y3fBz.mjs";
4
- import { C as isService, S as isOrgInScope, a as getDPoPJkt, b as isElevated, d as getScopeContext, f as getScopeContextMap, g as getUserId, m as getTeamId, n as PUBLIC_SCOPE, o as getMandate, p as getServiceScopes, u as getRequestScope, v as hasOrgAccess, x as isMember } from "./types-CSyCxl2V.mjs";
5
- import { a as normalizeToDecision, o as conjoinPolicyFilters } from "./applyPermissionResult-Cf6zUCvb.mjs";
6
- import { t as MemoryCacheStore } from "./memory-CmnzXE5Z.mjs";
4
+ import { a as conjoinPolicyFilters, i as normalizeToDecision } from "./authorizationDecision-ChvUQGG1.mjs";
5
+ import { n as getUserRoles } from "./userHelpers-ChYJ6CdK.mjs";
6
+ import { C as isService, S as isOrgInScope, a as getDPoPJkt, b as isElevated, d as getScopeContext, f as getScopeContextMap, g as getUserId, m as getTeamId, n as PUBLIC_SCOPE, o as getMandate, p as getServiceScopes, u as getRequestScope, v as hasOrgAccess, x as isMember } from "./types-Cys0ko9Z.mjs";
7
+ import { t as MemoryCacheStore } from "./memory-DR6wpa9F.mjs";
7
8
  import { randomUUID } from "node:crypto";
8
9
  //#region src/permissions/context.ts
9
10
  /**
@@ -106,6 +107,7 @@ function requireAuth() {
106
107
  if (!ctx.user) return deny("Authentication required");
107
108
  return true;
108
109
  };
110
+ check._requiresAuth = true;
109
111
  return check;
110
112
  }
111
113
  function requireRoles(rolesOrFirst, optionsOrSecond, ...rest) {
@@ -139,6 +141,36 @@ function requireRoles(rolesOrFirst, optionsOrSecond, ...rest) {
139
141
  return check;
140
142
  }
141
143
  /**
144
+ * Require a PLATFORM role — global roles only. An organization role can never
145
+ * satisfy this gate.
146
+ *
147
+ * `requireRoles(["ops"])` also accepts an ORG role named `ops` (that is its
148
+ * documented default), and `requireOrgRole("manager")` grants ANY organization's
149
+ * manager. Both return a bare allow with no policy, so a surface that is global
150
+ * by construction — a queue dashboard, a cluster-wide operations endpoint —
151
+ * cannot distinguish them from a real operator gate by looking at the decision.
152
+ * That makes "platform-only" a property the check has to DECLARE, which is what
153
+ * `_platformOnly` records and what such a surface can then require.
154
+ *
155
+ * Elevated scope passes: platform admin is the identity this gate is for.
156
+ *
157
+ * @example
158
+ * permissions: { list: requirePlatformRole("platform-ops") }
159
+ */
160
+ function requirePlatformRole(...args) {
161
+ const roles = normalizeVariadicOrArray(args);
162
+ const check = (ctx) => {
163
+ if (isElevated(scopeOf(ctx))) return true;
164
+ if (!ctx.user) return deny("Authentication required");
165
+ const userRoles = getUserRoles(ctx.user);
166
+ if (roles.some((r) => userRoles.includes(r))) return true;
167
+ return deny(`Required platform roles: ${roles.join(", ")}`);
168
+ };
169
+ check._roles = roles;
170
+ check._platformOnly = true;
171
+ return check;
172
+ }
173
+ /**
142
174
  * Short-form alias of `requireRoles()`. Identical behavior — checks both
143
175
  * platform roles AND org roles. Prefer `requireRoles` for new code; this
144
176
  * exists for call sites that want a terser name.
@@ -234,6 +266,15 @@ function allOf(...checks) {
234
266
  if (rb?._roles?.length) check._roles = [...rb._roles];
235
267
  if (rb?._orgRoles?.length) check._orgRoles = [...rb._orgRoles];
236
268
  }
269
+ const scopeContext = {};
270
+ let scopeConflict = false;
271
+ for (const c of checks) for (const [dim, val] of Object.entries(c._scopeContext ?? {})) if (dim in scopeContext && scopeContext[dim] !== val) scopeConflict = true;
272
+ else scopeContext[dim] = val;
273
+ if (Object.keys(scopeContext).length > 0) check._scopeContext = scopeContext;
274
+ const hasMetaSurface = (c) => Boolean(c._isPublic || c._roles?.length || c._orgRoles?.length || c._scopeContext && Object.keys(c._scopeContext).length > 0);
275
+ const opaqueBranch = checks.some((c) => !hasMetaSurface(c) && !c._requiresAuth);
276
+ const childConditional = checks.some((c) => c._conditional);
277
+ if (opaqueBranch || scopeConflict || childConditional) check._conditional = true;
237
278
  return check;
238
279
  }
239
280
  /**
@@ -269,6 +310,7 @@ function anyOf(...checks) {
269
310
  }
270
311
  if (roles.size > 0) check._roles = [...roles];
271
312
  if (orgRoles.size > 0) check._orgRoles = [...orgRoles];
313
+ if (checks.some((c) => c._conditional)) check._conditional = true;
272
314
  }
273
315
  return check;
274
316
  }
@@ -818,20 +860,66 @@ function createDynamicPermissionMatrix(config) {
818
860
  }) : void 0;
819
861
  const cacheStore = config.cacheStore ?? internalStore;
820
862
  const trackedKeys = /* @__PURE__ */ new Set();
863
+ const orgKeyIndex = /* @__PURE__ */ new Map();
864
+ const maxTrackedKeys = config.cache?.maxEntries ?? 1e4;
865
+ /**
866
+ * Record a key and ENFORCE the cap in the same step.
867
+ *
868
+ * The cap has to live here rather than at the write site: a node that mostly
869
+ * READS a shared cache registers on every hit but may rarely set, so a
870
+ * cap applied only after a `set` never runs and the bookkeeping grows with
871
+ * every distinct org/user/role combination the node has ever seen — unbounded,
872
+ * and outliving the cache entries themselves, which the external store expires
873
+ * on its own schedule. Eviction is insertion-ordered (`Set` iteration order),
874
+ * so the oldest bookkeeping goes first; dropping a key only costs a missed
875
+ * local invalidation for an entry that will still expire by TTL.
876
+ */
877
+ const registerKey = (orgId, key) => {
878
+ trackedKeys.add(key);
879
+ const bucket = orgId ?? "no-org";
880
+ let keys = orgKeyIndex.get(bucket);
881
+ if (!keys) {
882
+ keys = /* @__PURE__ */ new Set();
883
+ orgKeyIndex.set(bucket, keys);
884
+ }
885
+ keys.add(key);
886
+ if (trackedKeys.size > maxTrackedKeys) {
887
+ const overflow = trackedKeys.size - maxTrackedKeys;
888
+ const iter = trackedKeys.values();
889
+ for (let i = 0; i < overflow; i++) {
890
+ const oldest = iter.next().value;
891
+ if (oldest) forgetKey(oldest);
892
+ }
893
+ }
894
+ };
895
+ const forgetKey = (key) => {
896
+ trackedKeys.delete(key);
897
+ for (const [bucket, keys] of orgKeyIndex) if (keys.delete(key) && keys.size === 0) orgKeyIndex.delete(bucket);
898
+ };
821
899
  const nodeId = randomUUID().slice(0, 8);
822
900
  const DEFAULT_EVENT_TYPE = "arc.permissions.invalidated";
823
901
  let eventBridge = null;
824
902
  async function localInvalidateByOrg(orgId) {
825
903
  if (!cacheStore) return;
826
904
  const prefix = `${orgId}::`;
827
- const toDelete = [];
828
- for (const key of trackedKeys) if (key.startsWith(prefix)) toDelete.push(key);
905
+ if (cacheStore.clear) try {
906
+ await cacheStore.clear(`${prefix}*`);
907
+ const keys = orgKeyIndex.get(orgId);
908
+ if (keys) for (const k of keys) trackedKeys.delete(k);
909
+ orgKeyIndex.delete(orgId);
910
+ return;
911
+ } catch (error) {
912
+ logger.warn(`[DynamicPermissionMatrix] invalidateByOrg clear('${prefix}*') failed — falling back to per-key delete: ${error instanceof Error ? error.message : String(error)}`);
913
+ }
914
+ const toDelete = new Set(orgKeyIndex.get(orgId) ?? []);
915
+ for (const key of trackedKeys) if (key.startsWith(prefix)) toDelete.add(key);
829
916
  for (const key of toDelete) try {
830
917
  await cacheStore.delete(key);
831
- trackedKeys.delete(key);
918
+ forgetKey(key);
832
919
  } catch (error) {
833
920
  logger.warn(`[DynamicPermissionMatrix] invalidateByOrg delete failed for '${key}': ${error instanceof Error ? error.message : String(error)}`);
834
921
  }
922
+ orgKeyIndex.delete(orgId);
835
923
  }
836
924
  function isActionAllowed(actions, action) {
837
925
  if (!actions || actions.length === 0) return false;
@@ -851,27 +939,22 @@ function createDynamicPermissionMatrix(config) {
851
939
  }
852
940
  async function resolveMatrix(ctx, orgId, orgRoles) {
853
941
  if (!cacheStore) return config.resolveRolePermissions(ctx);
854
- const cacheKey = config.cache?.key?.(ctx) ?? buildDefaultCacheKey(ctx, orgId, orgRoles);
942
+ const customKey = config.cache?.key?.(ctx);
943
+ const cacheKey = customKey ? `${orgId ?? "no-org"}::${(orgRoles ?? []).slice().sort().join(",")}::${customKey}` : buildDefaultCacheKey(ctx, orgId, orgRoles);
855
944
  if (!cacheKey) return config.resolveRolePermissions(ctx);
856
945
  try {
857
946
  const hit = await cacheStore.get(cacheKey);
858
- if (hit) return hit;
947
+ if (hit) {
948
+ registerKey(orgId, cacheKey);
949
+ return hit;
950
+ }
859
951
  } catch (error) {
860
952
  logger.warn(`[DynamicPermissionMatrix] Cache get failed for '${cacheKey}': ${error instanceof Error ? error.message : String(error)}`);
861
953
  }
862
954
  const value = await config.resolveRolePermissions(ctx);
863
955
  try {
864
956
  await cacheStore.set(cacheKey, value, cacheTtlSeconds);
865
- trackedKeys.add(cacheKey);
866
- const maxTracked = config.cache?.maxEntries ?? 1e4;
867
- if (trackedKeys.size > maxTracked) {
868
- const overflow = trackedKeys.size - maxTracked;
869
- const iter = trackedKeys.values();
870
- for (let i = 0; i < overflow; i++) {
871
- const oldest = iter.next().value;
872
- if (oldest) trackedKeys.delete(oldest);
873
- }
874
- }
957
+ registerKey(orgId, cacheKey);
875
958
  } catch (error) {
876
959
  logger.warn(`[DynamicPermissionMatrix] Cache set failed for '${cacheKey}': ${error instanceof Error ? error.message : String(error)}`);
877
960
  }
@@ -889,7 +972,8 @@ function createDynamicPermissionMatrix(config) {
889
972
  try {
890
973
  matrix = await resolveMatrix(ctx, scope.organizationId, orgRoles);
891
974
  } catch (error) {
892
- return deny(`Permission matrix resolution failed: ${error instanceof Error ? error.message : String(error)}`);
975
+ logger.warn(`[DynamicPermissionMatrix] matrix resolution failed for org '${scope.organizationId ?? "?"}': ${error instanceof Error ? error.message : String(error)}`);
976
+ return deny("Permission policy is temporarily unavailable");
893
977
  }
894
978
  for (const [resource, actions] of Object.entries(required)) for (const action of actions) if (!orgRoles.some((role) => roleAllows(matrix, role, resource, action))) return deny(`Missing permission: ${resource}:${action}`);
895
979
  return true;
@@ -925,6 +1009,7 @@ function createDynamicPermissionMatrix(config) {
925
1009
  if (cacheStore.clear) try {
926
1010
  await cacheStore.clear();
927
1011
  trackedKeys.clear();
1012
+ orgKeyIndex.clear();
928
1013
  return;
929
1014
  } catch (error) {
930
1015
  logger.warn(`[DynamicPermissionMatrix] cacheStore.clear failed: ${error instanceof Error ? error.message : String(error)}`);
@@ -935,6 +1020,7 @@ function createDynamicPermissionMatrix(config) {
935
1020
  logger.warn(`[DynamicPermissionMatrix] Cache delete failed for '${key}': ${error instanceof Error ? error.message : String(error)}`);
936
1021
  }
937
1022
  trackedKeys.clear();
1023
+ orgKeyIndex.clear();
938
1024
  },
939
1025
  async connectEvents(events, options) {
940
1026
  if (eventBridge) await this.disconnectEvents();
@@ -975,15 +1061,30 @@ function createDynamicPermissionMatrix(config) {
975
1061
  //#region src/permissions/explain.ts
976
1062
  /**
977
1063
  * Extract a check's static requirement from its `PermissionCheckMeta`. Public
978
- * wins; then the union of platform + org roles a role gate declares; otherwise
979
- * "authenticated" (auth-required / custom / request-time checks).
1064
+ * wins; then a scope-context gate (optionally with roles); then the union of
1065
+ * platform + org roles a role gate declares; otherwise "authenticated"
1066
+ * (auth-required / custom / request-time checks). An `allOf` that couldn't be
1067
+ * fully captured statically carries `conditional: true` (see `_conditional`).
980
1068
  */
981
1069
  function describePermission(check) {
982
1070
  if (check._isPublic) return { kind: "public" };
983
1071
  const roles = [...check._roles ?? [], ...check._orgRoles ?? []];
1072
+ const scope = check._scopeContext;
1073
+ const conditional = check._conditional ? true : void 0;
1074
+ if (scope && Object.keys(scope).length > 0) return roles.length > 0 ? {
1075
+ kind: "scoped",
1076
+ scope,
1077
+ roles,
1078
+ conditional
1079
+ } : {
1080
+ kind: "scoped",
1081
+ scope,
1082
+ conditional
1083
+ };
984
1084
  if (roles.length > 0) return {
985
1085
  kind: "roles",
986
- roles
1086
+ roles,
1087
+ conditional
987
1088
  };
988
1089
  return { kind: "authenticated" };
989
1090
  }
@@ -1008,23 +1109,63 @@ function explainAccess(check, principal) {
1008
1109
  reason: "requires authentication; decided per request",
1009
1110
  requirement
1010
1111
  };
1112
+ const held = /* @__PURE__ */ new Set([...principal?.roles ?? [], ...principal?.orgRoles ?? []]);
1113
+ if (requirement.kind === "scoped") {
1114
+ const scopeReason = describeScope(requirement.scope);
1115
+ const rolesReason = requirement.roles?.length ? `role(s) ${requirement.roles.join(", ")} + ` : "";
1116
+ if (requirement.roles?.length && principal && !requirement.roles.some((r) => held.has(r))) return {
1117
+ decision: "deny",
1118
+ reason: `requires ${rolesReason}${scopeReason}`,
1119
+ requirement
1120
+ };
1121
+ if (!principal?.scope) return {
1122
+ decision: "conditional",
1123
+ reason: `requires ${rolesReason}${scopeReason}`,
1124
+ requirement
1125
+ };
1126
+ if (!Object.entries(requirement.scope).every(([dim, val]) => val === void 0 ? principal.scope?.[dim] !== void 0 : principal.scope?.[dim] === val)) return {
1127
+ decision: "deny",
1128
+ reason: `requires ${rolesReason}${scopeReason}`,
1129
+ requirement
1130
+ };
1131
+ if (requirement.conditional) return {
1132
+ decision: "conditional",
1133
+ reason: `in scope ${scopeReason}; additional runtime conditions apply`,
1134
+ requirement
1135
+ };
1136
+ return {
1137
+ decision: "allow",
1138
+ reason: `granted in scope: ${scopeReason}`,
1139
+ requirement
1140
+ };
1141
+ }
1142
+ const rolesText = `requires one of: ${requirement.roles.join(", ")}`;
1011
1143
  if (!principal) return {
1012
1144
  decision: "conditional",
1013
- reason: `requires one of: ${requirement.roles.join(", ")}`,
1145
+ reason: rolesText,
1014
1146
  requirement
1015
1147
  };
1016
- const held = /* @__PURE__ */ new Set([...principal.roles ?? [], ...principal.orgRoles ?? []]);
1017
1148
  const matched = requirement.roles.filter((r) => held.has(r));
1018
- return matched.length > 0 ? {
1149
+ if (matched.length === 0) return {
1150
+ decision: "deny",
1151
+ reason: rolesText,
1152
+ requirement
1153
+ };
1154
+ if (requirement.conditional) return {
1155
+ decision: "conditional",
1156
+ reason: `has role(s) ${matched.join(", ")}; additional runtime conditions apply`,
1157
+ requirement
1158
+ };
1159
+ return {
1019
1160
  decision: "allow",
1020
1161
  reason: `granted via role(s): ${matched.join(", ")}`,
1021
1162
  requirement
1022
- } : {
1023
- decision: "deny",
1024
- reason: `requires one of: ${requirement.roles.join(", ")}`,
1025
- requirement
1026
1163
  };
1027
1164
  }
1165
+ /** Render a scope-context requirement as a readable clause: `branchRole=head_office`. */
1166
+ function describeScope(scope) {
1167
+ return Object.entries(scope).map(([dim, val]) => val === void 0 ? `${dim} (any)` : `${dim}=${val}`).join(", ");
1168
+ }
1028
1169
  /**
1029
1170
  * Introspect a whole permission map (`{ list, get, create, ... }` or any
1030
1171
  * action→check record) into `action → requirement`. The reusable core of a
@@ -1167,27 +1308,59 @@ function requireGrant(options) {
1167
1308
  */
1168
1309
  function createRoleHierarchy(map) {
1169
1310
  const cache = /* @__PURE__ */ new Map();
1170
- function resolveRole(role, visited) {
1171
- if (visited.has(role)) return [];
1172
- visited.add(role);
1311
+ /**
1312
+ * Resolve a role's transitive expansion.
1313
+ *
1314
+ * `stack` is the CURRENT recursion path (a DFS stack), NOT a shared visited
1315
+ * accumulator: a role is added on entry and REMOVED on exit, so sibling
1316
+ * branches never pollute each other. Without this, a diamond `A→B→D`, `A→C→D`
1317
+ * would let B's traversal leave `D` in a shared set, making C's `D` look like a
1318
+ * back-edge and caching `C` WITHOUT `D` — a nondeterministic under-grant.
1319
+ *
1320
+ * Returns `cyclic` = whether a back-edge into `stack` was cut anywhere in the
1321
+ * subtree. A cyclic subtree's result depends on the entry path, so it is NOT
1322
+ * cached (recomputed each call — correct, if unmemoized). Acyclic subtrees (the
1323
+ * norm) cache safely.
1324
+ */
1325
+ function resolveRole(role, stack) {
1326
+ if (stack.has(role)) return {
1327
+ roles: [],
1328
+ cyclic: true
1329
+ };
1173
1330
  const cached = cache.get(role);
1174
- if (cached) return cached;
1331
+ if (cached) return {
1332
+ roles: cached,
1333
+ cyclic: false
1334
+ };
1175
1335
  const children = map[role];
1176
1336
  if (!children || children.length === 0) {
1177
1337
  cache.set(role, [role]);
1178
- return [role];
1338
+ return {
1339
+ roles: [role],
1340
+ cyclic: false
1341
+ };
1179
1342
  }
1343
+ stack.add(role);
1180
1344
  const result = [role];
1181
- for (const child of children) result.push(...resolveRole(child, visited));
1345
+ let cyclic = false;
1346
+ for (const child of children) {
1347
+ const childResult = resolveRole(child, stack);
1348
+ result.push(...childResult.roles);
1349
+ if (childResult.cyclic) cyclic = true;
1350
+ }
1351
+ stack.delete(role);
1182
1352
  const deduped = [...new Set(result)];
1183
- cache.set(role, deduped);
1184
- return deduped;
1353
+ if (!cyclic) cache.set(role, deduped);
1354
+ return {
1355
+ roles: deduped,
1356
+ cyclic
1357
+ };
1185
1358
  }
1186
1359
  return {
1187
1360
  expand(roles) {
1188
1361
  if (roles.length === 0) return [];
1189
1362
  const all = /* @__PURE__ */ new Set();
1190
- for (const role of roles) for (const expanded of resolveRole(role, /* @__PURE__ */ new Set())) all.add(expanded);
1363
+ for (const role of roles) for (const expanded of resolveRole(role, /* @__PURE__ */ new Set()).roles) all.add(expanded);
1191
1364
  return [...all];
1192
1365
  },
1193
1366
  includes(userRoles, requiredRole) {
@@ -1372,4 +1545,4 @@ function readOnly(overrides) {
1372
1545
  }, overrides);
1373
1546
  }
1374
1547
  //#endregion
1375
- export { allow as A, when as B, requireScopeContext as C, requireDPoP as D, requireAgentScope as E, not as F, requireAuth as I, requireOwnership as L, anyOf as M, deny as N, requireMandate as O, denyAll as P, requireRoles as R, requireOrgRole as S, requireTeamMembership as T, scopeOf as V, explainAccess as _, permissionMatrix as a, requireOrgInScope as b, publicReadAdminWrite as c, GRANT_MODES as d, modeSatisfies as f, describePermissionMap as g, describePermission as h, ownerWithAdminBypass as i, allowPublic as j, allOf as k, readOnly as l, collectPublicSurface as m, authenticated as n, presets_exports as o, requireGrant as p, fullPublic as r, publicRead as s, adminOnly as t, createRoleHierarchy as u, createDynamicPermissionMatrix as v, requireServiceScope as w, requireOrgMembership as x, createOrgPermissions as y, roles as z };
1548
+ export { allow as A, roles as B, requireScopeContext as C, requireDPoP as D, requireAgentScope as E, not as F, scopeOf as H, requireAuth as I, requireOwnership as L, anyOf as M, deny as N, requireMandate as O, denyAll as P, requirePlatformRole as R, requireOrgRole as S, requireTeamMembership as T, when as V, explainAccess as _, permissionMatrix as a, requireOrgInScope as b, publicReadAdminWrite as c, GRANT_MODES as d, modeSatisfies as f, describePermissionMap as g, describePermission as h, ownerWithAdminBypass as i, allowPublic as j, allOf as k, readOnly as l, collectPublicSurface as m, authenticated as n, presets_exports as o, requireGrant as p, fullPublic as r, publicRead as s, adminOnly as t, createRoleHierarchy as u, createDynamicPermissionMatrix as v, requireServiceScope as w, requireOrgMembership as x, createOrgPermissions as y, requireRoles as z };
@@ -1,4 +1,5 @@
1
- import { r as ForbiddenError } from "./errors-DkO8Nk6-.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { r as ForbiddenError } from "./errors-Cj42AntO.mjs";
2
3
  //#region src/pipeline/pipe.ts
3
4
  /**
4
5
  * Compose pipeline steps into an ordered array.
@@ -1,4 +1,5 @@
1
- import { Ct as PipelineStep, Rt as IControllerResponse, St as PipelineContext, _t as Guard, bt as OperationFilter, vt as Interceptor, wt as Transform, xt as PipelineConfig, yt as NextFunction } from "../index-Q5gzEIWY.mjs";
1
+
2
+ import { Ct as PipelineStep, Rt as IControllerResponse, St as PipelineContext, _t as Guard, bt as OperationFilter, vt as Interceptor, wt as Transform, xt as PipelineConfig, yt as NextFunction } from "../index-CpzxqePp.mjs";
2
3
  //#region src/pipeline/guard.d.ts
3
4
  interface GuardOptions {
4
5
  operations?: OperationFilter;
@@ -1,4 +1,5 @@
1
- import { n as pipe, t as executePipeline } from "../pipe-BOLmGIxa.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { n as pipe, t as executePipeline } from "../pipe-DRDNsI2T.mjs";
2
3
  //#region src/pipeline/guard.ts
3
4
  /**
4
5
  * Create a named guard.
@@ -1,8 +1,9 @@
1
- import { n as getUserRoles } from "./userHelpers-Cg_y3fBz.mjs";
2
- import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-CSyCxl2V.mjs";
3
- import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-CQ_7KQWw.mjs";
4
- import { t as executePipeline } from "./pipe-BOLmGIxa.mjs";
5
- import { t as buildRequestScopeProjection } from "./projection-UBDgfMwu.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { n as getUserRoles } from "./userHelpers-ChYJ6CdK.mjs";
3
+ import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-Cys0ko9Z.mjs";
4
+ import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-CB5Cuzk9.mjs";
5
+ import { t as executePipeline } from "./pipe-DRDNsI2T.mjs";
6
+ import { t as buildRequestScopeProjection } from "./projection-BHw6xlOQ.mjs";
6
7
  import { isPaginatedResult, toCanonicalList } from "@classytic/repo-core/pagination";
7
8
  //#region src/core/fastifyAdapter.ts
8
9
  /** Type guard for Mongoose-like documents with toObject() */
@@ -1,10 +1,11 @@
1
- import { At as RouteDefinition, J as PresetHook, Q as MiddlewareConfig, et as RouteSchemaOptions } from "../index-Q5gzEIWY.mjs";
2
- import { l as AnyRecord } from "../types-ChvvVNP8.mjs";
3
- import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-C6yv4ZTW.mjs";
4
- import { _ as _default$3, d as ScheduleStats, f as SchedulesPluginOptions, g as HealthOptions, h as HealthCheck, m as schedulesPlugin, p as _default$7, u as ScheduleDefinition, v as healthPlugin } from "../types-D_n8L6VY.mjs";
5
- import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-0WhPnUH7.mjs";
6
- import { _ as CachingRule, a as MetricsCollector, c as metricsPlugin, d as _default$5, f as realtimePlugin, g as CachingOptions, h as ssePlugin, i as MetricEntry, l as ChangeOperation, m as _default$8, n as _default$9, o as MetricsOptions, p as SSEOptions, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as RealtimeOptions, v as _default$1, y as cachingPlugin } from "../versioning-DXgY5BUm.mjs";
7
- import { t as TracingOptions } from "../tracing-CsGKQJGg.mjs";
1
+
2
+ import { At as RouteDefinition, J as PresetHook, Q as MiddlewareConfig, et as RouteSchemaOptions } from "../index-CpzxqePp.mjs";
3
+ import { l as AnyRecord } from "../types-B7XeLEgK.mjs";
4
+ import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-CpYUJmPA.mjs";
5
+ import { _ as _default$3, d as ScheduleStats, f as SchedulesPluginOptions, g as HealthOptions, h as HealthCheck, m as schedulesPlugin, p as _default$7, u as ScheduleDefinition, v as healthPlugin } from "../types-CBgvkp8O.mjs";
6
+ import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-zh0_AYHa.mjs";
7
+ import { _ as CachingRule, a as MetricsCollector, c as metricsPlugin, d as _default$5, f as realtimePlugin, g as CachingOptions, h as ssePlugin, i as MetricEntry, l as ChangeOperation, m as _default$8, n as _default$9, o as MetricsOptions, p as SSEOptions, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as RealtimeOptions, v as _default$1, y as cachingPlugin } from "../versioning-D_rhHfZm.mjs";
8
+ import { t as TracingOptions } from "../tracing-Dro5eH6j.mjs";
8
9
  import { PaginatedResult } from "@classytic/repo-core/pagination";
9
10
  import { FastifyInstance, FastifyPluginAsync } from "fastify";
10
11
  //#region src/plugins/createPlugin.d.ts
@@ -1,18 +1,19 @@
1
- import { p as MUTATION_OPERATIONS } from "../constants-DNre0wRg.mjs";
2
- import { c as getOrgId } from "../types-CSyCxl2V.mjs";
3
- import { n as requestContext } from "../requestContext-MrlJwECf.mjs";
4
- import { t as hasEvents } from "../typeGuards-C9KXUly6.mjs";
5
- import { t as HookSystem } from "../HookSystem-WkIougo6.mjs";
6
- import { t as ResourceRegistry } from "../ResourceRegistry-y9Hnypus.mjs";
7
- import { a as requestIdPlugin, i as createRequestIdGenerator, n as health_default, o as requestId_default, s as sanitizeRequestId, t as healthPlugin } from "../health-CB_m4S32.mjs";
8
- import { n as caching_default, t as cachingPlugin } from "../caching-_NJeDd1_.mjs";
9
- import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-Bq2OeEQL.mjs";
10
- import { n as metrics_default, t as metricsPlugin } from "../metrics-fdxI5mn_.mjs";
11
- import { n as realtime_default, t as realtimePlugin } from "../realtime-B9nmIY5V.mjs";
12
- import { t as replyHelpersPlugin } from "../replyHelpers-67tRawQZ.mjs";
13
- import { n as schedules_default, t as schedulesPlugin } from "../schedules-CjOd2MG9.mjs";
14
- import { n as sse_default, t as ssePlugin } from "../sse-BQ1w0dfl.mjs";
15
- import { n as versioning_default, t as versioningPlugin } from "../versioning-gKWyryT3.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { p as MUTATION_OPERATIONS } from "../constants-D3Dv4LAV.mjs";
3
+ import { c as getOrgId } from "../types-Cys0ko9Z.mjs";
4
+ import { n as requestContext } from "../requestContext-2TxXOJ7T.mjs";
5
+ import { t as hasEvents } from "../typeGuards-B0ryPo3I.mjs";
6
+ import { t as HookSystem } from "../HookSystem-BcmPyq5I.mjs";
7
+ import { t as ResourceRegistry } from "../ResourceRegistry-qq0mn2s9.mjs";
8
+ import { a as requestIdPlugin, i as createRequestIdGenerator, n as health_default, o as requestId_default, s as sanitizeRequestId, t as healthPlugin } from "../health-DjZYjM7H.mjs";
9
+ import { n as caching_default, t as cachingPlugin } from "../caching-BFHA6Scf.mjs";
10
+ import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-C5NeD6bT.mjs";
11
+ import { n as metrics_default, t as metricsPlugin } from "../metrics-CUdw_wLB.mjs";
12
+ import { n as realtime_default, t as realtimePlugin } from "../realtime-C5NoxWFY.mjs";
13
+ import { t as replyHelpersPlugin } from "../replyHelpers-DIiZKGUt.mjs";
14
+ import { n as schedules_default, t as schedulesPlugin } from "../schedules-DdtlICTf.mjs";
15
+ import { n as sse_default, t as ssePlugin } from "../sse-CUTo9y0X.mjs";
16
+ import { n as versioning_default, t as versioningPlugin } from "../versioning-CHDTor3P.mjs";
16
17
  import fp from "fastify-plugin";
17
18
  //#region src/core/arcCorePlugin.ts
18
19
  const arcCorePlugin = async (fastify, opts = {}) => {
@@ -1,3 +1,4 @@
1
+
1
2
  import { FastifyPluginAsync, FastifyRequest } from "fastify";
2
3
  //#region src/plugins/response-cache.d.ts
3
4
  interface ResponseCacheRule {
@@ -1,4 +1,5 @@
1
- import { t as hasEvents } from "../typeGuards-C9KXUly6.mjs";
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
2
+ import { t as hasEvents } from "../typeGuards-B0ryPo3I.mjs";
2
3
  import fp from "fastify-plugin";
3
4
  //#region src/plugins/response-cache.ts
4
5
  /**
@@ -1,2 +1,3 @@
1
- import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-CsGKQJGg.mjs";
1
+
2
+ import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-Dro5eH6j.mjs";
2
3
  export { type TracingOptions, createSpan, isTracingAvailable, traced, _default as tracingPlugin };
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  import { createRequire } from "node:module";
2
3
  import fp from "fastify-plugin";
3
4
  //#region src/plugins/tracing.ts
@@ -58,7 +59,7 @@ try {
58
59
  function createTracerProvider(options) {
59
60
  if (!isAvailable || !NodeTracerProvider || !BatchSpanProcessor || !OTLPTraceExporter) return null;
60
61
  const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
61
- const resolvedVersion = serviceVersion ?? "2.30.0";
62
+ const resolvedVersion = serviceVersion ?? "2.31.0";
62
63
  const exporter = new OTLPTraceExporter({ url: exporterUrl });
63
64
  const provider = new NodeTracerProvider({ resource: { attributes: {
64
65
  "service.name": serviceName,
@@ -1,3 +1,4 @@
1
+ /*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
1
2
  //#region src/utils/pluralize.ts
2
3
  /**
3
4
  * Lightweight English pluralization for the Arc CLI.