@classytic/arc 2.6.3 → 2.7.3

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 (143) hide show
  1. package/README.md +98 -3
  2. package/dist/{BaseController-DzRtluEF.mjs → BaseController-CpMfCXdn.mjs} +134 -16
  3. package/dist/adapters/index.d.mts +2 -2
  4. package/dist/adapters/index.mjs +1 -1
  5. package/dist/{adapters-gM-WYjNe.mjs → adapters-BxGgSHjj.mjs} +1 -9
  6. package/dist/applyPermissionResult-D6GPMsvh.mjs +37 -0
  7. package/dist/audit/index.d.mts +1 -1
  8. package/dist/audit/index.mjs +1 -1
  9. package/dist/audit/mongodb.d.mts +1 -1
  10. package/dist/audit/mongodb.mjs +1 -1
  11. package/dist/auth/index.d.mts +4 -4
  12. package/dist/auth/index.mjs +7 -6
  13. package/dist/auth/mongoose.d.mts +191 -0
  14. package/dist/auth/mongoose.mjs +73 -0
  15. package/dist/auth/redis-session.d.mts +1 -1
  16. package/dist/{betterAuthOpenApi-lz0IRbXJ.mjs → betterAuthOpenApi-CCw3YX0g.mjs} +1 -1
  17. package/dist/cache/index.d.mts +2 -2
  18. package/dist/cache/index.mjs +2 -2
  19. package/dist/cli/commands/docs.mjs +2 -2
  20. package/dist/cli/commands/generate.mjs +1 -1
  21. package/dist/cli/commands/init.mjs +7 -5
  22. package/dist/cli/commands/introspect.mjs +1 -1
  23. package/dist/core/index.d.mts +3 -3
  24. package/dist/core/index.mjs +4 -4
  25. package/dist/{core-C1XCMtqM.mjs → core-BWekSEju.mjs} +41 -13
  26. package/dist/{createApp-D2w0LdYJ.mjs → createApp-D7e77m8C.mjs} +25 -14
  27. package/dist/{defineResource-wWMBB4GP.mjs → defineResource-DZzyl4a4.mjs} +42 -37
  28. package/dist/docs/index.d.mts +2 -2
  29. package/dist/docs/index.mjs +1 -1
  30. package/dist/dynamic/index.d.mts +2 -2
  31. package/dist/dynamic/index.mjs +2 -2
  32. package/dist/{elevation-BEdACOLB.mjs → elevation-By_p2lnn.mjs} +1 -1
  33. package/dist/elevation-D7WK0RXq.d.mts +23 -0
  34. package/dist/{errorHandler-r2595m8T.mjs → errorHandler-CH8wk1eD.mjs} +17 -2
  35. package/dist/{errorHandler-Do4vVQ1f.d.mts → errorHandler-pCpEtNd7.d.mts} +46 -2
  36. package/dist/{eventPlugin-Ba00swHF.mjs → eventPlugin-B6U_nCFU.mjs} +4 -3
  37. package/dist/{eventPlugin-DW45v4V5.d.mts → eventPlugin-CdvUoUna.d.mts} +1 -1
  38. package/dist/events/index.d.mts +3 -3
  39. package/dist/events/index.mjs +1 -1
  40. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  41. package/dist/events/transports/redis.d.mts +1 -1
  42. package/dist/factory/index.d.mts +1 -1
  43. package/dist/factory/index.mjs +1 -1
  44. package/dist/hooks/index.d.mts +1 -1
  45. package/dist/hooks/index.mjs +1 -1
  46. package/dist/idempotency/index.d.mts +3 -3
  47. package/dist/idempotency/mongodb.d.mts +1 -1
  48. package/dist/idempotency/redis.d.mts +1 -1
  49. package/dist/index-B0extFr4.d.mts +640 -0
  50. package/dist/{index-gz6iuzCp.d.mts → index-BjShrzoj.d.mts} +47 -4
  51. package/dist/{index-CHeJa4Zd.d.mts → index-C9eYNjGR.d.mts} +1 -1
  52. package/dist/index.d.mts +9 -8
  53. package/dist/index.mjs +10 -9
  54. package/dist/integrations/event-gateway.d.mts +1 -1
  55. package/dist/integrations/event-gateway.mjs +1 -1
  56. package/dist/integrations/index.d.mts +1 -1
  57. package/dist/integrations/mcp/index.d.mts +2 -2
  58. package/dist/integrations/mcp/index.mjs +8 -5
  59. package/dist/integrations/mcp/testing.d.mts +1 -1
  60. package/dist/integrations/mcp/testing.mjs +1 -1
  61. package/dist/integrations/webhooks.d.mts +58 -1
  62. package/dist/integrations/webhooks.mjs +78 -7
  63. package/dist/integrations/websocket.d.mts +7 -1
  64. package/dist/integrations/websocket.mjs +7 -1
  65. package/dist/{interface-DYH8AXGe.d.mts → interface-B91alUzq.d.mts} +151 -15
  66. package/dist/{mongodb-pMvOlR5_.d.mts → mongodb-B7zupyck.d.mts} +1 -1
  67. package/dist/{mongodb-kltrBPa1.d.mts → mongodb-Cgu9F1Nd.d.mts} +1 -1
  68. package/dist/{openapi-CBmZ6EQN.mjs → openapi-BBSTVcMm.mjs} +1 -1
  69. package/dist/org/index.d.mts +2 -2
  70. package/dist/org/index.mjs +1 -1
  71. package/dist/permissions/index.d.mts +4 -4
  72. package/dist/permissions/index.mjs +3 -2
  73. package/dist/{permissions-C8ImI8gC.mjs → permissions-CH4cNwJi.mjs} +358 -64
  74. package/dist/plugins/index.d.mts +52 -5
  75. package/dist/plugins/index.mjs +12 -11
  76. package/dist/plugins/response-cache.mjs +1 -1
  77. package/dist/plugins/tracing-entry.d.mts +1 -1
  78. package/dist/plugins/tracing-entry.mjs +1 -1
  79. package/dist/policies/index.d.mts +1 -1
  80. package/dist/presets/index.d.mts +3 -3
  81. package/dist/presets/index.mjs +1 -1
  82. package/dist/presets/multiTenant.d.mts +53 -3
  83. package/dist/presets/multiTenant.mjs +89 -47
  84. package/dist/{presets-BMfdy34e.mjs → presets-BFrGvvjL.mjs} +2 -2
  85. package/dist/{queryCachePlugin-DcmETvcB.d.mts → queryCachePlugin-Ckl71mkc.d.mts} +1 -1
  86. package/dist/{queryCachePlugin-XtFplYO9.mjs → queryCachePlugin-CwTpR04-.mjs} +2 -2
  87. package/dist/{redis-D0Qc-9EW.d.mts → redis-3TQxm2VZ.d.mts} +1 -1
  88. package/dist/{redis-stream-BW9UKLZM.d.mts → redis-stream-Dag5LFa9.d.mts} +1 -1
  89. package/dist/registry/index.d.mts +1 -1
  90. package/dist/registry/index.mjs +2 -2
  91. package/dist/replyHelpers-uDUIYh7u.mjs +40 -0
  92. package/dist/{resourceToTools-nCJWnG1r.mjs → resourceToTools-BJkoQoUP.mjs} +74 -25
  93. package/dist/rpc/index.d.mts +1 -1
  94. package/dist/rpc/index.mjs +1 -1
  95. package/dist/scope/index.d.mts +3 -2
  96. package/dist/scope/index.mjs +4 -3
  97. package/dist/{sse-BF7GR7IB.mjs → sse-6W0hjVS_.mjs} +2 -2
  98. package/dist/testing/index.d.mts +2 -2
  99. package/dist/testing/index.mjs +1 -1
  100. package/dist/types/index.d.mts +4 -3
  101. package/dist/types/index.mjs +1 -1
  102. package/dist/types--D3vvfdt.d.mts +286 -0
  103. package/dist/{types-By-5mIfn.d.mts → types-2FlNl0mL.d.mts} +44 -9
  104. package/dist/types-AOD8fxIw.mjs +229 -0
  105. package/dist/types-B4BNthET.d.mts +178 -0
  106. package/dist/{types-B4_TDdPe.d.mts → types-C5g2oRC7.d.mts} +18 -2
  107. package/dist/utils/index.d.mts +3 -3
  108. package/dist/utils/index.mjs +5 -5
  109. package/package.json +21 -6
  110. package/skills/arc/SKILL.md +314 -6
  111. package/skills/arc/references/integrations.md +32 -7
  112. package/skills/arc/references/mcp.md +31 -7
  113. package/skills/arc/references/multi-tenancy.md +208 -0
  114. package/skills/arc/references/production.md +69 -0
  115. package/dist/elevation-C_taLQrM.d.mts +0 -147
  116. package/dist/index-NGZksqM5.d.mts +0 -398
  117. package/dist/types-BNUccdcf.d.mts +0 -101
  118. package/dist/types-BhtYdxZU.mjs +0 -91
  119. /package/dist/{EventTransport-wc5hSLik.d.mts → EventTransport-C4VheKeC.d.mts} +0 -0
  120. /package/dist/{HookSystem-COkyWztM.mjs → HookSystem-D7lfx--K.mjs} +0 -0
  121. /package/dist/{ResourceRegistry-C6ngvOnn.mjs → ResourceRegistry-DsHiG9cL.mjs} +0 -0
  122. /package/dist/{caching-BSXB-Xr7.mjs → caching-5DtLwIqb.mjs} +0 -0
  123. /package/dist/{circuitBreaker-JP2GdJ4b.d.mts → circuitBreaker-BBPDt-J_.d.mts} +0 -0
  124. /package/dist/{circuitBreaker-BOBOpN2w.mjs → circuitBreaker-l18oRgL5.mjs} +0 -0
  125. /package/dist/{errors-CcVbl1-T.d.mts → errors-BS6lZvWy.d.mts} +0 -0
  126. /package/dist/{errors-NoQKsbAT.mjs → errors-Cg58SLNi.mjs} +0 -0
  127. /package/dist/{externalPaths-DpO-s7r8.d.mts → externalPaths-iba7jD3d.d.mts} +0 -0
  128. /package/dist/{fields-DFwdaWCq.d.mts → fields-D4nMDqnK.d.mts} +0 -0
  129. /package/dist/{interface-D_BWALyZ.d.mts → interface-CG7oRZjX.d.mts} +0 -0
  130. /package/dist/{interface-gr-7qo9j.d.mts → interface-CSbZdv_3.d.mts} +0 -0
  131. /package/dist/{logger-Dz3j1ItV.mjs → logger-DLg8-Ueg.mjs} +0 -0
  132. /package/dist/{memory-BFAYkf8H.mjs → memory-Cp7_cAko.mjs} +0 -0
  133. /package/dist/{metrics-Csh4nsvv.mjs → metrics-Qnvwc-LQ.mjs} +0 -0
  134. /package/dist/{mongodb-BuQ7fNTg.mjs → mongodb-B7X7P1P8.mjs} +0 -0
  135. /package/dist/{pluralize-CcT6qF0a.mjs → pluralize-Dckfq6US.mjs} +0 -0
  136. /package/dist/{registry-I-ogLgL9.mjs → registry-B3lRFBWo.mjs} +0 -0
  137. /package/dist/{requestContext-DYtmNpm5.mjs → requestContext-xHIKedG6.mjs} +0 -0
  138. /package/dist/{schemaConverter-DjzHpFam.mjs → schemaConverter-0TyONAwM.mjs} +0 -0
  139. /package/dist/{sessionManager-wbkYj2HL.d.mts → sessionManager-CEo9jwPI.d.mts} +0 -0
  140. /package/dist/{tracing-bz_U4EM1.d.mts → tracing-DEqdGkr-.d.mts} +0 -0
  141. /package/dist/{typeGuards-Cj5Rgvlg.mjs → typeGuards-CcFZXgU7.mjs} +0 -0
  142. /package/dist/{utils-Dc0WhlIl.mjs → utils-B-l6410F.mjs} +0 -0
  143. /package/dist/{versioning-BzfeHmhj.mjs → versioning-CdBbFefk.mjs} +0 -0
@@ -1,4 +1,5 @@
1
- import { _ as isMember, a as AUTHENTICATED_SCOPE, c as getOrgContext, d as getTeamId, f as getUserId, g as isElevated, h as isAuthenticated, i as elevationPlugin, l as getOrgId, m as hasOrgAccess, n as ElevationOptions, o as PUBLIC_SCOPE, p as getUserRoles, r as _default, s as RequestScope, t as ElevationEvent, u as getOrgRoles } from "../elevation-C_taLQrM.mjs";
1
+ import { _ as isAuthenticated, a as getClientId, b as isOrgInScope, c as getOrgRoles, d as getScopeContextMap, f as getServiceScopes, g as hasOrgAccess, h as getUserRoles, i as getAncestorOrgIds, l as getRequestScope, m as getUserId, n as PUBLIC_SCOPE, o as getOrgContext, p as getTeamId, r as RequestScope, s as getOrgId, t as AUTHENTICATED_SCOPE, u as getScopeContext, v as isElevated, x as isService, y as isMember } from "../types--D3vvfdt.mjs";
2
+ import { i as elevationPlugin, n as ElevationOptions, r as _default, t as ElevationEvent } from "../elevation-D7WK0RXq.mjs";
2
3
  import { FastifyReply, FastifyRequest } from "fastify";
3
4
 
4
5
  //#region src/scope/rateLimitKey.d.ts
@@ -29,4 +30,4 @@ interface ResolveOrgFromHeaderOptions {
29
30
  */
30
31
  declare function resolveOrgFromHeader(options: ResolveOrgFromHeaderOptions): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
31
32
  //#endregion
32
- export { AUTHENTICATED_SCOPE, type ElevationEvent, type ElevationOptions, PUBLIC_SCOPE, type RateLimitKeyContext, type RequestScope, type ResolveOrgFromHeaderOptions, type TenantKeyGeneratorOptions, createTenantKeyGenerator, _default as elevationPlugin, elevationPlugin as elevationPluginFn, getOrgContext, getOrgId, getOrgRoles, getTeamId, getUserId, getUserRoles, hasOrgAccess, isAuthenticated, isElevated, isMember, resolveOrgFromHeader };
33
+ export { AUTHENTICATED_SCOPE, type ElevationEvent, type ElevationOptions, PUBLIC_SCOPE, type RateLimitKeyContext, type RequestScope, type ResolveOrgFromHeaderOptions, type TenantKeyGeneratorOptions, createTenantKeyGenerator, _default as elevationPlugin, elevationPlugin as elevationPluginFn, getAncestorOrgIds, getClientId, getOrgContext, getOrgId, getOrgRoles, getRequestScope, getScopeContext, getScopeContextMap, getServiceScopes, getTeamId, getUserId, getUserRoles, hasOrgAccess, isAuthenticated, isElevated, isMember, isOrgInScope, isService, resolveOrgFromHeader };
@@ -1,6 +1,6 @@
1
- import { a as getOrgRoles, c as getUserRoles, d as isElevated, f as isMember, i as getOrgId, l as hasOrgAccess, n as PUBLIC_SCOPE, o as getTeamId, r as getOrgContext, s as getUserId, t as AUTHENTICATED_SCOPE, u as isAuthenticated } from "../types-BhtYdxZU.mjs";
1
+ import { _ as isElevated, a as getOrgContext, b as isService, c as getRequestScope, d as getServiceScopes, f as getTeamId, g as isAuthenticated, h as hasOrgAccess, i as getClientId, l as getScopeContext, m as getUserRoles, n as PUBLIC_SCOPE, o as getOrgId, p as getUserId, r as getAncestorOrgIds, s as getOrgRoles, t as AUTHENTICATED_SCOPE, u as getScopeContextMap, v as isMember, y as isOrgInScope } from "../types-AOD8fxIw.mjs";
2
2
  import { n as normalizeRoles } from "../types-ZUu_h0jp.mjs";
3
- import { n as elevation_default, t as elevationPlugin } from "../elevation-BEdACOLB.mjs";
3
+ import { n as elevation_default, t as elevationPlugin } from "../elevation-By_p2lnn.mjs";
4
4
  //#region src/scope/rateLimitKey.ts
5
5
  function createTenantKeyGenerator(opts) {
6
6
  if (opts?.strategy) return opts.strategy;
@@ -8,6 +8,7 @@ function createTenantKeyGenerator(opts) {
8
8
  const scope = ctx.scope;
9
9
  if (!scope || scope.kind === "public") return ctx.ip;
10
10
  if (scope.kind === "member") return scope.organizationId;
11
+ if (scope.kind === "service") return scope.organizationId;
11
12
  if (scope.kind === "elevated") return scope.organizationId ?? scope.userId ?? ctx.ip;
12
13
  return scope.userId ?? ctx.ip;
13
14
  };
@@ -75,4 +76,4 @@ function resolveOrgFromHeader(options) {
75
76
  };
76
77
  }
77
78
  //#endregion
78
- export { AUTHENTICATED_SCOPE, PUBLIC_SCOPE, createTenantKeyGenerator, elevation_default as elevationPlugin, elevationPlugin as elevationPluginFn, getOrgContext, getOrgId, getOrgRoles, getTeamId, getUserId, getUserRoles, hasOrgAccess, isAuthenticated, isElevated, isMember, resolveOrgFromHeader };
79
+ export { AUTHENTICATED_SCOPE, PUBLIC_SCOPE, createTenantKeyGenerator, elevation_default as elevationPlugin, elevationPlugin as elevationPluginFn, getAncestorOrgIds, getClientId, getOrgContext, getOrgId, getOrgRoles, getRequestScope, getScopeContext, getScopeContextMap, getServiceScopes, getTeamId, getUserId, getUserRoles, hasOrgAccess, isAuthenticated, isElevated, isMember, isOrgInScope, isService, resolveOrgFromHeader };
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
2
- import { i as getOrgId, n as PUBLIC_SCOPE } from "./types-BhtYdxZU.mjs";
3
- import { t as arcLog } from "./logger-Dz3j1ItV.mjs";
2
+ import { n as PUBLIC_SCOPE, o as getOrgId } from "./types-AOD8fxIw.mjs";
3
+ import { t as arcLog } from "./logger-DLg8-Ueg.mjs";
4
4
  import fp from "fastify-plugin";
5
5
  //#region src/plugins/sse.ts
6
6
  var sse_exports = /* @__PURE__ */ __exportAll({
@@ -1,5 +1,5 @@
1
- import { Ut as CrudRepository, Vt as ResourceDefinition, u as AnyRecord } from "../interface-DYH8AXGe.mjs";
2
- import { d as ResourceLike, r as CreateAppOptions } from "../types-By-5mIfn.mjs";
1
+ import { Ut as CrudRepository, Vt as ResourceDefinition, u as AnyRecord } from "../interface-B91alUzq.mjs";
2
+ import { d as ResourceLike, r as CreateAppOptions } from "../types-2FlNl0mL.mjs";
3
3
  import Fastify, { FastifyInstance, FastifyServerOptions } from "fastify";
4
4
  import { Connection } from "mongoose";
5
5
  import { Mock } from "vitest";
@@ -1796,7 +1796,7 @@ function runEventTests(resourceName, displayName, events) {
1796
1796
  * ```
1797
1797
  */
1798
1798
  async function createTestApp(options = {}) {
1799
- const { createApp } = await import("../createApp-D2w0LdYJ.mjs").then((n) => n.r);
1799
+ const { createApp } = await import("../createApp-D7e77m8C.mjs").then((n) => n.r);
1800
1800
  const { useInMemoryDb = true, mongoUri: providedMongoUri, ...appOptions } = options;
1801
1801
  const defaultAuth = {
1802
1802
  type: "jwt",
@@ -1,4 +1,5 @@
1
- import { _ as isMember, a as AUTHENTICATED_SCOPE, d as getTeamId, g as isElevated, h as isAuthenticated, l as getOrgId, m as hasOrgAccess, n as ElevationOptions, o as PUBLIC_SCOPE, s as RequestScope, t as ElevationEvent, u as getOrgRoles } from "../elevation-C_taLQrM.mjs";
2
- import { $ as RateLimitConfig, A as FieldRule, B as JwtContext, C as CrudRouterOptions, Ct as getUserId, D as FastifyRequestExtras, E as EventsDecorator, F as InferDocType, Ft as IController, G as OpenApiSchemas, Gt as PaginatedResult, H as MiddlewareConfig, I as InferResourceDoc, It as IControllerResponse, J as PopulateOption, K as OwnershipCheck, Kt as PaginationParams, L as IntrospectionData, Lt as IRequestContext, M as HealthCheck, Mt as ControllerHandler, N as HealthOptions, Nt as ControllerLike, O as FastifyWithAuth, P as InferAdapterDoc, Pt as FastifyHandler, Q as QueryParserInterface, R as IntrospectionPluginOptions, Rt as RouteHandler, S as CrudRouteKey, St as envelope, T as EventDefinition, Tt as BaseControllerOptions, U as MiddlewareHandler, Ut as CrudRepository, V as LookupOption, W as ObjectId, Wt as InferDoc, X as PresetHook, Y as PresetFunction, Z as PresetResult, _ as Authenticator, _t as TypedResourceConfig, at as ResourceCacheConfig, b as ControllerQueryOptions, bt as ValidateOptions, ct as ResourceHooks, d as ApiResponse, dt as RouteHandlerMethod, et as RegistryEntry, f as ArcDecorator, ft as RouteSchemaOptions, g as AuthPluginOptions, gt as TypedRepository, h as AuthHelpers, ht as TypedController, it as RequestWithExtras, j as GracefulShutdownOptions, k as FastifyWithDecorators, l as AdditionalRoute, lt as ResourceMetadata, m as ArcRequest, mt as TokenPair, nt as RequestContext, ot as ResourceConfig, p as ArcInternalMetadata, pt as ServiceContext, q as ParsedQuery, qt as QueryOptions, rt as RequestIdOptions, st as ResourceHookContext, tt as RegistryStats, u as AnyRecord, ut as ResourcePermissions, v as AuthenticatorContext, vt as UserLike, w as CrudSchemas, x as CrudController, xt as ValidationResult, y as ConfigError, yt as UserOrganization, z as JWTPayload } from "../interface-DYH8AXGe.mjs";
3
- import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "../types-BNUccdcf.mjs";
1
+ import { _ as isAuthenticated, c as getOrgRoles, g as hasOrgAccess, n as PUBLIC_SCOPE, p as getTeamId, r as RequestScope, s as getOrgId, t as AUTHENTICATED_SCOPE, v as isElevated, y as isMember } from "../types--D3vvfdt.mjs";
2
+ import { $ as RateLimitConfig, A as FieldRule, B as JwtContext, C as CrudRouterOptions, Ct as getUserId, D as FastifyRequestExtras, E as EventsDecorator, F as InferDocType, Ft as IController, G as OpenApiSchemas, Gt as PaginatedResult, H as MiddlewareConfig, I as InferResourceDoc, It as IControllerResponse, J as PopulateOption, K as OwnershipCheck, Kt as PaginationParams, L as IntrospectionData, Lt as IRequestContext, M as HealthCheck, Mt as ControllerHandler, N as HealthOptions, Nt as ControllerLike, O as FastifyWithAuth, P as InferAdapterDoc, Pt as FastifyHandler, Q as QueryParserInterface, R as IntrospectionPluginOptions, Rt as RouteHandler, S as CrudRouteKey, St as envelope, T as EventDefinition, Tt as BaseControllerOptions, U as MiddlewareHandler, Ut as CrudRepository, V as LookupOption, W as ObjectId, Wt as InferDoc, X as PresetHook, Y as PresetFunction, Z as PresetResult, _ as Authenticator, _t as TypedResourceConfig, at as ResourceCacheConfig, b as ControllerQueryOptions, bt as ValidateOptions, ct as ResourceHooks, d as ApiResponse, dt as RouteHandlerMethod, et as RegistryEntry, f as ArcDecorator, ft as RouteSchemaOptions, g as AuthPluginOptions, gt as TypedRepository, h as AuthHelpers, ht as TypedController, it as RequestWithExtras, j as GracefulShutdownOptions, k as FastifyWithDecorators, l as AdditionalRoute, lt as ResourceMetadata, m as ArcRequest, mt as TokenPair, nt as RequestContext, ot as ResourceConfig, p as ArcInternalMetadata, pt as ServiceContext, q as ParsedQuery, qt as QueryOptions, rt as RequestIdOptions, st as ResourceHookContext, tt as RegistryStats, u as AnyRecord, ut as ResourcePermissions, v as AuthenticatorContext, vt as UserLike, w as CrudSchemas, x as CrudController, xt as ValidationResult, y as ConfigError, yt as UserOrganization, z as JWTPayload } from "../interface-B91alUzq.mjs";
3
+ import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "../types-B4BNthET.mjs";
4
+ import { n as ElevationOptions, t as ElevationEvent } from "../elevation-D7WK0RXq.mjs";
4
5
  export { AUTHENTICATED_SCOPE, AdditionalRoute, AnyRecord, ApiResponse, ArcDecorator, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRepository, CrudRouteKey, CrudRouterOptions, CrudSchemas, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OpenApiSchemas, OwnershipCheck, PUBLIC_SCOPE, PaginatedResult, PaginationParams, ParsedQuery, PermissionCheck, PermissionContext, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryOptions, QueryParserInterface, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResourceCacheConfig, ResourceConfig, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteHandler, RouteHandlerMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult, envelope, getOrgId, getOrgRoles, getTeamId, getUserId, hasOrgAccess, isAuthenticated, isElevated, isMember };
@@ -1,4 +1,4 @@
1
- import { a as getOrgRoles, d as isElevated, f as isMember, i as getOrgId, l as hasOrgAccess, n as PUBLIC_SCOPE, o as getTeamId, t as AUTHENTICATED_SCOPE, u as isAuthenticated } from "../types-BhtYdxZU.mjs";
1
+ import { _ as isElevated, f as getTeamId, g as isAuthenticated, h as hasOrgAccess, n as PUBLIC_SCOPE, o as getOrgId, s as getOrgRoles, t as AUTHENTICATED_SCOPE, v as isMember } from "../types-AOD8fxIw.mjs";
2
2
  //#region src/types/index.ts
3
3
  /**
4
4
  * Response envelope helper — wraps data in Arc's standard `{ success, data }` format.
@@ -0,0 +1,286 @@
1
+ //#region src/scope/types.d.ts
2
+ /**
3
+ * Request Scope — The One Standard
4
+ *
5
+ * Discriminated union representing the access context of every request.
6
+ * Replaces scattered orgScope/orgRoles/organizationId/bypassRoles.
7
+ *
8
+ * Set once by auth adapters, read everywhere by permissions/presets/guards.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // In a permission check
13
+ * const scope = request.scope;
14
+ * if (isElevated(scope)) return true;
15
+ * if (isMember(scope) && scope.orgRoles.includes('admin')) return true;
16
+ *
17
+ * // Get user identity from scope
18
+ * const userId = getUserId(scope);
19
+ * const globalRoles = getUserRoles(scope);
20
+ * ```
21
+ */
22
+ /**
23
+ * Request scope — 5 kinds, no ambiguity.
24
+ *
25
+ * | Kind | Meaning |
26
+ * |---------------|--------------------------------------------------|
27
+ * | public | No authentication |
28
+ * | authenticated | Logged-in user, no org context |
29
+ * | member | User in an org with specific roles |
30
+ * | service | Machine-to-machine (API key, service account) |
31
+ * | elevated | Platform admin, explicit elevation |
32
+ *
33
+ * **Identity fields by kind:**
34
+ * - `userId` / `userRoles` — available on `authenticated`, `member`, `elevated` (a real human)
35
+ * - `clientId` — available on `service` (a machine identity, NOT a user)
36
+ * - `organizationId` — required on `member` and `service`, optional on `elevated`
37
+ * - `orgRoles` — org-level roles, only on `member` (from membership records)
38
+ * - `scopes` — optional OAuth-style scope strings on `service` (e.g. `['jobs:write', 'memories:read']`)
39
+ *
40
+ * Use `getUserId(scope)` / `getClientId(scope)` / `getOrgId(scope)` instead of
41
+ * narrowing manually — helpers return `undefined` when the field isn't present.
42
+ */
43
+ type RequestScope = {
44
+ kind: "public";
45
+ } | {
46
+ kind: "authenticated";
47
+ userId?: string;
48
+ userRoles?: string[];
49
+ } | {
50
+ kind: "member";
51
+ userId?: string;
52
+ userRoles: string[];
53
+ organizationId: string;
54
+ orgRoles: string[];
55
+ teamId?: string;
56
+ /**
57
+ * App-defined scope dimensions beyond org and team. Use this to carry
58
+ * branch / project / department / region / workspace identifiers that
59
+ * arc itself shouldn't take a position on.
60
+ *
61
+ * Read with `getScopeContext(scope, key)`. Filtered by
62
+ * `multiTenantPreset({ tenantFields: [...] })` and gated by
63
+ * `requireScopeContext(...)`. Populated by your auth function or
64
+ * adapter (e.g. from JWT claims, BA session fields, or request headers).
65
+ *
66
+ * Treat as immutable — `Readonly` enforces that at the type level.
67
+ */
68
+ context?: Readonly<Record<string, string>>;
69
+ /**
70
+ * Parent organizations the caller has access to, ordered closest-first
71
+ * (immediate parent → … → root). Used for explicit hierarchy checks
72
+ * via `isOrgInScope` and `requireOrgInScope` — there's no automatic
73
+ * inheritance, every check is opt-in.
74
+ *
75
+ * Arc takes no position on the source — your auth function loads the
76
+ * chain from your own org table during sign-in or middleware. Empty
77
+ * or absent = caller has no parent orgs (the common case).
78
+ */
79
+ ancestorOrgIds?: readonly string[];
80
+ } | {
81
+ kind: "service";
82
+ clientId: string;
83
+ organizationId: string;
84
+ scopes?: readonly string[]; /** App-defined scope dimensions — see `member.context` for details. */
85
+ context?: Readonly<Record<string, string>>; /** Parent organizations — see `member.ancestorOrgIds` for details. */
86
+ ancestorOrgIds?: readonly string[];
87
+ } | {
88
+ kind: "elevated";
89
+ userId?: string;
90
+ organizationId?: string;
91
+ elevatedBy: string; /** App-defined scope dimensions — see `member.context` for details. */
92
+ context?: Readonly<Record<string, string>>; /** Parent organizations — see `member.ancestorOrgIds` for details. */
93
+ ancestorOrgIds?: readonly string[];
94
+ };
95
+ /** Check if scope is `member` kind */
96
+ declare function isMember(scope: RequestScope): scope is Extract<RequestScope, {
97
+ kind: "member";
98
+ }>;
99
+ /** Check if scope is `elevated` kind */
100
+ declare function isElevated(scope: RequestScope): scope is Extract<RequestScope, {
101
+ kind: "elevated";
102
+ }>;
103
+ /** Check if scope is `service` kind (machine-to-machine auth) */
104
+ declare function isService(scope: RequestScope): scope is Extract<RequestScope, {
105
+ kind: "service";
106
+ }>;
107
+ /** Check if scope has org access (member, service, or elevated) */
108
+ declare function hasOrgAccess(scope: RequestScope): boolean;
109
+ /** Check if request is authenticated (any kind except public) */
110
+ declare function isAuthenticated(scope: RequestScope): boolean;
111
+ /** Get organizationId from scope (member, service, or elevated — undefined otherwise) */
112
+ declare function getOrgId(scope: RequestScope): string | undefined;
113
+ /**
114
+ * Get stable client identity from a service scope.
115
+ *
116
+ * Returns the `clientId` for machine-to-machine auth (API keys, service accounts),
117
+ * or `undefined` for any other scope kind. Use this for audit logging, rate limiting,
118
+ * and anywhere you need to distinguish "this specific API client" from "this user".
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * const clientId = getClientId(request.scope);
123
+ * if (clientId) {
124
+ * auditLog.record({ actor: clientId, action: 'create' });
125
+ * }
126
+ * ```
127
+ */
128
+ declare function getClientId(scope: RequestScope): string | undefined;
129
+ /**
130
+ * Get OAuth-style scope strings from a service scope (e.g. `['jobs:write']`).
131
+ * Returns an empty array for any non-service kind.
132
+ */
133
+ declare function getServiceScopes(scope: RequestScope): readonly string[];
134
+ /** Get org roles from scope (empty array if not a member) */
135
+ declare function getOrgRoles(scope: RequestScope): string[];
136
+ /** Get team ID from scope (only available on member kind) */
137
+ declare function getTeamId(scope: RequestScope): string | undefined;
138
+ /**
139
+ * Get an app-defined scope dimension by key (e.g. `branchId`, `projectId`).
140
+ *
141
+ * Returns the value when the scope is `member`/`service`/`elevated` AND has
142
+ * `context` set AND the key exists; `undefined` otherwise. Designed to be
143
+ * the single read path for any custom tenancy dimension your app cares about
144
+ * — branch, project, department, region, workspace, etc.
145
+ *
146
+ * Arc itself takes no position on what keys you use — that's your domain.
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * import { getScopeContext } from '@classytic/arc/scope';
151
+ *
152
+ * const branchId = getScopeContext(request.scope, 'branchId');
153
+ * if (!branchId) return reply.code(403).send({ error: 'Branch context required' });
154
+ * ```
155
+ */
156
+ declare function getScopeContext(scope: RequestScope, key: string): string | undefined;
157
+ /**
158
+ * Get the full scope context map (read-only). Returns `undefined` for scope
159
+ * kinds that don't carry context (`public`, `authenticated`).
160
+ */
161
+ declare function getScopeContextMap(scope: RequestScope): Readonly<Record<string, string>> | undefined;
162
+ /**
163
+ * Get the parent-organization chain for a scope (closest-first, root-last).
164
+ *
165
+ * Returns the `ancestorOrgIds` array when the scope is `member`/`service`/
166
+ * `elevated` and has it set; an empty array otherwise (including for kinds
167
+ * that can't carry org context).
168
+ *
169
+ * Arc takes no position on what the chain represents — your auth function
170
+ * loads it from your own data model. Common use cases: holding company →
171
+ * subsidiaries, MSP → managed tenants, white-label parent → child accounts.
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * import { getAncestorOrgIds } from '@classytic/arc/scope';
176
+ *
177
+ * const ancestors = getAncestorOrgIds(request.scope);
178
+ * if (ancestors.includes('acme-holding')) {
179
+ * // caller has access to a path that includes Acme Holding
180
+ * }
181
+ * ```
182
+ */
183
+ declare function getAncestorOrgIds(scope: RequestScope): readonly string[];
184
+ /**
185
+ * Pure predicate: does this scope grant access to `targetOrgId`?
186
+ *
187
+ * Returns `true` if `targetOrgId` equals the scope's `organizationId` OR
188
+ * appears in `ancestorOrgIds`. Returns `false` otherwise — including for
189
+ * elevated scopes (this is a pure data query, not a permission check; the
190
+ * elevated bypass lives in `requireOrgInScope`, not here).
191
+ *
192
+ * Designed to be the building block for any custom hierarchy logic in your
193
+ * own permission checks. Use `requireOrgInScope` for the route-gating
194
+ * version that includes the elevated bypass.
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * import { isOrgInScope } from '@classytic/arc/scope';
199
+ *
200
+ * // Inside a custom permission check
201
+ * if (!isOrgInScope(request.scope, request.params.orgId)) {
202
+ * return { granted: false, reason: 'Not in your org hierarchy' };
203
+ * }
204
+ * ```
205
+ */
206
+ declare function isOrgInScope(scope: RequestScope, targetOrgId: string): boolean;
207
+ /**
208
+ * Get userId from scope (available on authenticated, member, elevated).
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * import { getUserId } from '@classytic/arc/scope';
213
+ * const userId = getUserId(request.scope);
214
+ * ```
215
+ */
216
+ declare function getUserId(scope: RequestScope): string | undefined;
217
+ /**
218
+ * Get global user roles from scope (available on authenticated and member).
219
+ * These are user-level roles (e.g. superadmin, finance-admin) distinct from
220
+ * org-level roles (scope.orgRoles).
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * import { getUserRoles } from '@classytic/arc/scope';
225
+ * const globalRoles = getUserRoles(request.scope);
226
+ * ```
227
+ */
228
+ declare function getUserRoles(scope: RequestScope): string[];
229
+ /**
230
+ * Org context — canonical extraction from a Fastify request.
231
+ *
232
+ * Works regardless of auth type (JWT, Better Auth, custom) by reading
233
+ * `request.scope` and `request.user`. Eliminates the need for each resource
234
+ * to re-invent org extraction from headers/user/scope.
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * import { getOrgContext } from '@classytic/arc/scope';
239
+ *
240
+ * handler: async (request, reply) => {
241
+ * const { userId, organizationId, roles, orgRoles } = getOrgContext(request);
242
+ * }
243
+ * ```
244
+ */
245
+ declare function getOrgContext(request: {
246
+ scope?: RequestScope;
247
+ user?: Record<string, unknown> | null;
248
+ headers?: Record<string, string | string[] | undefined>;
249
+ }): {
250
+ userId: string | undefined;
251
+ organizationId: string | undefined;
252
+ roles: string[];
253
+ orgRoles: string[];
254
+ };
255
+ /**
256
+ * Read `request.scope` safely from any object that *might* have one.
257
+ * Falls back to `PUBLIC_SCOPE` when the field is absent or undefined.
258
+ *
259
+ * This is the canonical way for permission checks, presets, and middleware
260
+ * to read scope — never access `request.scope` directly because it can be
261
+ * `undefined` on requests that haven't been touched by an auth adapter yet.
262
+ *
263
+ * Accepts a structural shape (`{ scope?: RequestScope }`) instead of the
264
+ * full Fastify request type so it can be called from any layer without
265
+ * dragging in the Fastify type. The actual runtime is identical.
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * import { getRequestScope } from '@classytic/arc/scope';
270
+ *
271
+ * function myCheck(ctx: PermissionContext) {
272
+ * const scope = getRequestScope(ctx.request);
273
+ * if (isElevated(scope)) return true;
274
+ * // ...
275
+ * }
276
+ * ```
277
+ */
278
+ declare function getRequestScope(request: {
279
+ scope?: RequestScope;
280
+ }): RequestScope;
281
+ /** Default public scope — used as initial decoration value */
282
+ declare const PUBLIC_SCOPE: Readonly<RequestScope>;
283
+ /** Default authenticated scope — used when user is logged in but no org */
284
+ declare const AUTHENTICATED_SCOPE: Readonly<RequestScope>;
285
+ //#endregion
286
+ export { isAuthenticated as _, getClientId as a, isOrgInScope as b, getOrgRoles as c, getScopeContextMap as d, getServiceScopes as f, hasOrgAccess as g, getUserRoles as h, getAncestorOrgIds as i, getRequestScope as l, getUserId as m, PUBLIC_SCOPE as n, getOrgContext as o, getTeamId as p, RequestScope as r, getOrgId as s, AUTHENTICATED_SCOPE as t, getScopeContext as u, isElevated as v, isService as x, isMember as y };
@@ -1,12 +1,12 @@
1
- import { n as ElevationOptions } from "./elevation-C_taLQrM.mjs";
2
- import { _ as Authenticator } from "./interface-DYH8AXGe.mjs";
3
- import { t as ExternalOpenApiPaths } from "./externalPaths-DpO-s7r8.mjs";
4
- import { i as CacheStore } from "./interface-D_BWALyZ.mjs";
5
- import { r as QueryCachePluginOptions } from "./queryCachePlugin-DcmETvcB.mjs";
6
- import { i as EventTransport } from "./EventTransport-wc5hSLik.mjs";
7
- import { t as EventPluginOptions } from "./eventPlugin-DW45v4V5.mjs";
8
- import { c as MetricsOptions, d as SSEOptions, m as CachingOptions, r as VersioningOptions, t as ErrorHandlerOptions } from "./errorHandler-Do4vVQ1f.mjs";
9
- import { r as IdempotencyStore } from "./interface-gr-7qo9j.mjs";
1
+ import { _ as Authenticator } from "./interface-B91alUzq.mjs";
2
+ import { n as ElevationOptions } from "./elevation-D7WK0RXq.mjs";
3
+ import { t as ExternalOpenApiPaths } from "./externalPaths-iba7jD3d.mjs";
4
+ import { i as CacheStore } from "./interface-CG7oRZjX.mjs";
5
+ import { r as QueryCachePluginOptions } from "./queryCachePlugin-Ckl71mkc.mjs";
6
+ import { i as EventTransport } from "./EventTransport-C4VheKeC.mjs";
7
+ import { t as EventPluginOptions } from "./eventPlugin-CdvUoUna.mjs";
8
+ import { c as MetricsOptions, d as SSEOptions, m as CachingOptions, r as VersioningOptions, t as ErrorHandlerOptions } from "./errorHandler-pCpEtNd7.mjs";
9
+ import { r as IdempotencyStore } from "./interface-CSbZdv_3.mjs";
10
10
  import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
11
11
 
12
12
  //#region src/factory/loadResources.d.ts
@@ -598,6 +598,41 @@ interface CreateAppOptions {
598
598
  ajv?: {
599
599
  keywords?: string[];
600
600
  };
601
+ /**
602
+ * Enable `reply.ok()`, `reply.fail()`, `reply.paginated()` response helpers.
603
+ *
604
+ * Default: `false` (opt-in).
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * const app = await createApp({ replyHelpers: true });
609
+ *
610
+ * // Then in any handler:
611
+ * return reply.ok({ name: 'MacBook' }); // → 200 { success: true, data: { ... } }
612
+ * return reply.ok(product, 201); // → 201 { success: true, data: { ... } }
613
+ * return reply.fail('Not found', 404); // → 404 { success: false, error: '...' }
614
+ * return reply.fail(['err1', 'err2'], 422); // → 422 { success: false, errors: [...] }
615
+ * return reply.paginated({ docs, total, page, limit });
616
+ * ```
617
+ */
618
+ replyHelpers?: boolean;
619
+ /**
620
+ * Auto-convert BigInt values to Number in all JSON responses.
621
+ *
622
+ * When `true`, Arc adds a `preSerialization` hook that converts BigInt values
623
+ * to Number before JSON serialization. Without this, `JSON.stringify` throws
624
+ * on BigInt values (e.g., from financial libraries like fin-io).
625
+ *
626
+ * Default: `false` (opt-in — most apps don't use BigInt).
627
+ *
628
+ * @example
629
+ * ```typescript
630
+ * const app = await createApp({
631
+ * serializeBigInt: true,
632
+ * });
633
+ * ```
634
+ */
635
+ serializeBigInt?: boolean;
601
636
  /**
602
637
  * Resources to register automatically.
603
638
  * Each resource's `.toPlugin()` is called and registered for you.