@classytic/arc 2.21.0 → 2.23.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 (115) hide show
  1. package/dist/{BaseController-BnLYgE9A.mjs → BaseController-BQ8KNvWC.mjs} +3 -2
  2. package/dist/{ResourceRegistry-7RnrEWNP.mjs → ResourceRegistry-y9Hnypus.mjs} +1 -0
  3. package/dist/{actionPermissions-ze70xXJi.mjs → actionPermissions-lszoJle1.mjs} +1 -1
  4. package/dist/applyPermissionResult-Tw4iXtlf.mjs +264 -0
  5. package/dist/audit/index.d.mts +2 -2
  6. package/dist/auth/index.d.mts +30 -2
  7. package/dist/auth/index.mjs +6 -3
  8. package/dist/cli/commands/describe.d.mts +1 -1
  9. package/dist/cli/commands/describe.mjs +1 -1
  10. package/dist/cli/commands/docs.mjs +2 -2
  11. package/dist/cli/commands/init.mjs +1 -1
  12. package/dist/cli/commands/introspect.mjs +1 -1
  13. package/dist/cli/index.mjs +1 -1
  14. package/dist/core/index.d.mts +2 -2
  15. package/dist/core/index.mjs +3 -3
  16. package/dist/{core-DZ6Xe1jR.mjs → core-DQ6rDTyH.mjs} +126 -68
  17. package/dist/{createActionRouter-BWMDW-dL.mjs → createActionRouter-BuOv-m4Y.mjs} +10 -6
  18. package/dist/{createAggregationRouter-l5mNdYrZ.mjs → createAggregationRouter-CgJv_BU_.mjs} +3 -3
  19. package/dist/{createApp-Bi61XxqU.mjs → createApp-CjOeWJ9_.mjs} +252 -57
  20. package/dist/docs/index.d.mts +1 -1
  21. package/dist/docs/index.mjs +1 -1
  22. package/dist/encryption/index.mjs +9 -5
  23. package/dist/{errorHandler-Dxf6P_kV.mjs → errorHandler-Bq2OeEQL.mjs} +34 -10
  24. package/dist/{errorHandler-B0e-bq-O.d.mts → errorHandler-C6yv4ZTW.d.mts} +13 -0
  25. package/dist/events/index.mjs +5 -2
  26. package/dist/factory/index.d.mts +46 -9
  27. package/dist/factory/index.mjs +64 -13
  28. package/dist/{fastify-augmentation-DafigGQp.d.mts → fastify-augmentation-g_f9omSc.d.mts} +2 -2
  29. package/dist/fields-D3lhgzhD.d.mts +121 -0
  30. package/dist/health-ScyjIVo5.mjs +202 -0
  31. package/dist/hooks/index.d.mts +1 -1
  32. package/dist/idempotency/index.d.mts +7 -0
  33. package/dist/idempotency/index.mjs +7 -17
  34. package/dist/{index-Dtrj6XZk.d.mts → index-BBsvQt7U.d.mts} +1310 -1226
  35. package/dist/{types-DpxoNX5v.d.mts → index-Ba10fdKp.d.mts} +196 -66
  36. package/dist/{index-B5N-NaHs.d.mts → index-CC5ruDGh.d.mts} +3 -3
  37. package/dist/{index-B5PoNbfu.d.mts → index-wMoWBLkn.d.mts} +68 -2
  38. package/dist/index.d.mts +6 -5
  39. package/dist/index.mjs +6 -5
  40. package/dist/{init-0YhHkXGk.mjs → init-CjO4p_q1.mjs} +123 -4
  41. package/dist/integrations/event-gateway.mjs +1 -1
  42. package/dist/integrations/index.d.mts +1 -1
  43. package/dist/integrations/mcp/index.d.mts +67 -4
  44. package/dist/integrations/mcp/index.mjs +1 -1
  45. package/dist/integrations/mcp/testing.d.mts +1 -1
  46. package/dist/integrations/mcp/testing.mjs +1 -1
  47. package/dist/integrations/webhooks.d.mts +131 -7
  48. package/dist/integrations/webhooks.mjs +169 -10
  49. package/dist/interface-n5hpKg1d.mjs +16 -0
  50. package/dist/jsonBody-BlzAoGCe.mjs +43 -0
  51. package/dist/{loadResourcesFromEntry-OMCvIEE7.mjs → loadResourcesFromEntry-kvGT6EcO.mjs} +1 -1
  52. package/dist/logger/index.d.mts +26 -1
  53. package/dist/logger/index.mjs +39 -1
  54. package/dist/{mcpPlugin-B9XjjNVG.mjs → mcpPlugin-BtzIL_kM.mjs} +312 -39
  55. package/dist/middleware/index.d.mts +1 -1
  56. package/dist/{module-WeuU5jfd.d.mts → module-B4u10iOJ.d.mts} +26 -1
  57. package/dist/{openapi-Kyod_di6.mjs → openapi-jSDx-VDv.mjs} +3 -3
  58. package/dist/permissions/index.d.mts +4 -3
  59. package/dist/permissions/index.mjs +3 -2
  60. package/dist/{permissions-BJMuKMl7.mjs → permissions-tbxFHxjZ.mjs} +77 -264
  61. package/dist/pipeline/index.d.mts +1 -1
  62. package/dist/plugins/index.d.mts +24 -7
  63. package/dist/plugins/index.mjs +14 -282
  64. package/dist/plugins/response-cache.mjs +1 -0
  65. package/dist/plugins/tracing-entry.mjs +7 -4
  66. package/dist/presets/filesUpload.d.mts +2 -2
  67. package/dist/presets/filesUpload.mjs +1 -1
  68. package/dist/presets/index.d.mts +1 -1
  69. package/dist/presets/index.mjs +1 -1
  70. package/dist/presets/multiTenant.d.mts +1 -1
  71. package/dist/presets/search.d.mts +2 -2
  72. package/dist/presets/search.mjs +1 -1
  73. package/dist/{presets-gw0ciIUD.mjs → presets-BOe4Ugkl.mjs} +1 -1
  74. package/dist/rateLimitKey-BoWRH3e7.mjs +14 -0
  75. package/dist/realtime-I8OrfnMR.mjs +375 -0
  76. package/dist/{registerRoute-oGAl0oA8.mjs → registerRoute-CWO6mdYe.mjs} +38 -18
  77. package/dist/registry/index.d.mts +2 -2
  78. package/dist/registry/index.mjs +1 -1
  79. package/dist/requestId-5BhTVzBv.mjs +113 -0
  80. package/dist/schemaConverter-DJvodiHj.mjs +171 -0
  81. package/dist/{schemaIR-ajetw3Fv.mjs → schemaIR-Ca7ySNPx.mjs} +2 -2
  82. package/dist/scim/index.mjs +6 -7
  83. package/dist/scope/index.mjs +2 -76
  84. package/dist/scope-LONQ3mfZ.mjs +37 -0
  85. package/dist/simpleEqualityMatcher-Cg05HPsn.mjs +68 -0
  86. package/dist/{sse-CfUjwjDk.mjs → sse-0u4P4-OI.mjs} +7 -30
  87. package/dist/sseStream-BQ7Qaynp.mjs +57 -0
  88. package/dist/testing/index.d.mts +83 -3
  89. package/dist/testing/index.mjs +70 -3
  90. package/dist/types/index.d.mts +2 -2
  91. package/dist/{types-DRj-Ut4n.d.mts → types-5OuqeTDX.d.mts} +37 -2
  92. package/dist/{fields-BGqrAa_u.d.mts → types-Csxga7d3.d.mts} +1 -121
  93. package/dist/usage/index.d.mts +142 -0
  94. package/dist/usage/index.mjs +0 -0
  95. package/dist/utils/index.d.mts +101 -19
  96. package/dist/utils/index.mjs +5 -3
  97. package/dist/{utils-CO8a3B_1.mjs → utils-CZyeRXTh.mjs} +80 -82
  98. package/dist/{versioning-DQ4mCvg0.d.mts → versioning-D6PvCwpq.d.mts} +43 -9
  99. package/llms.txt +39 -0
  100. package/package.json +513 -447
  101. package/skills/arc/SKILL.md +14 -8
  102. package/skills/arc/references/api-reference.md +34 -0
  103. package/skills/arc/references/auth.md +21 -4
  104. package/skills/arc/references/mcp.md +1 -1
  105. package/skills/arc/references/production.md +734 -654
  106. package/skills/arc-code-review/SKILL.md +1 -1
  107. package/skills/arc-code-review/references/anti-patterns.md +71 -18
  108. package/skills/arc-code-review/references/arc-cheatsheet.md +15 -2
  109. package/skills/arc-code-review/references/migration-recipes.md +7 -7
  110. package/skills/arc-code-review/references/mongokit-migration.md +4 -3
  111. package/skills/arc-module-publishing/SKILL.md +2 -1
  112. package/skills/arc-module-publishing/references/authoring-modules.md +55 -0
  113. package/skills/arc-module-publishing/references/package-manifest.md +4 -2
  114. package/dist/preloadResources-CHw3_oA_.mjs +0 -45
  115. package/dist/schemaConverter-U0MnO9vd.mjs +0 -110
@@ -1,5 +1,5 @@
1
1
  import { t as CRUD_OPERATIONS } from "../constants-DNre0wRg.mjs";
2
- import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-CHw3_oA_.mjs";
2
+ import { d as getModuleExports, h as preloadResourcesAsync, m as preloadResources, n as createApp } from "../createApp-CjOeWJ9_.mjs";
3
3
  import { runStorageContract } from "./storageContract.mjs";
4
4
  import Fastify from "fastify";
5
5
  import { afterAll, describe, expect, it, vi } from "vitest";
@@ -462,6 +462,73 @@ async function setupBetterAuthTestApp(input) {
462
462
  };
463
463
  }
464
464
  //#endregion
465
+ //#region src/testing/bootModuleApp.ts
466
+ /**
467
+ * The built-in DB factory: in-memory MongoDB via lazy devDep imports.
468
+ * Everything Mongo-specific about the harness lives HERE — the harness
469
+ * itself is driver-blind and any kit can replace this via `database`.
470
+ */
471
+ async function mongoMemoryDatabase(opts) {
472
+ let mms;
473
+ try {
474
+ mms = await import("mongodb-memory-server");
475
+ } catch {
476
+ throw new Error("[arc-testing] bootModuleApp's default database is in-memory MongoDB — install 'mongodb-memory-server' + 'mongoose' as devDependencies, or inject your own `database` factory for a different store");
477
+ }
478
+ const server = opts.replset ? await mms.MongoMemoryReplSet.create({ replSet: { count: 1 } }) : await mms.MongoMemoryServer.create();
479
+ const uri = server.getUri();
480
+ const mongoose = (await import("mongoose")).default;
481
+ if (mongoose.connection.readyState !== 0) await mongoose.disconnect();
482
+ await mongoose.connect(uri);
483
+ mongoose.connection.deleteModel(/.*/);
484
+ return {
485
+ uri,
486
+ connection: mongoose.connection,
487
+ teardown: async () => {
488
+ if (mongoose.connection.readyState !== 0) await mongoose.disconnect().catch(() => void 0);
489
+ await server.stop().catch(() => void 0);
490
+ }
491
+ };
492
+ }
493
+ async function bootModuleApp(modules, options = {}) {
494
+ const db = await (options.database ?? mongoMemoryDatabase)({ replset: options.replset ?? false });
495
+ const ctx = {
496
+ uri: db.uri,
497
+ mongoUri: db.uri,
498
+ connection: db.connection
499
+ };
500
+ const resolved = typeof modules === "function" ? await modules(ctx) : modules;
501
+ const list = Array.isArray(resolved) ? resolved : [resolved];
502
+ let app;
503
+ try {
504
+ app = await createApp({
505
+ preset: "testing",
506
+ auth: false,
507
+ sensible: false,
508
+ ...options.app,
509
+ modules: list
510
+ });
511
+ await app.ready();
512
+ } catch (err) {
513
+ await db.teardown().catch(() => void 0);
514
+ throw err;
515
+ }
516
+ let closed = false;
517
+ return {
518
+ app,
519
+ uri: db.uri,
520
+ mongoUri: db.uri,
521
+ connection: db.connection,
522
+ exports: (name) => getModuleExports(app, name),
523
+ close: async () => {
524
+ if (closed) return;
525
+ closed = true;
526
+ await app.close().catch(() => void 0);
527
+ await db.teardown().catch(() => void 0);
528
+ }
529
+ };
530
+ }
531
+ //#endregion
465
532
  //#region src/testing/fixtures.ts
466
533
  function createTestFixtures() {
467
534
  const registry = /* @__PURE__ */ new Map();
@@ -1049,7 +1116,7 @@ function pickDefaultAuth(authMode, callerAuth) {
1049
1116
  };
1050
1117
  }
1051
1118
  async function createTestApp(options = {}) {
1052
- const { createApp } = await import("../createApp-Bi61XxqU.mjs").then((n) => n.r);
1119
+ const { createApp } = await import("../createApp-CjOeWJ9_.mjs").then((n) => n.r);
1053
1120
  const { resources = [], db = "in-memory", connectMongoose = false, authMode = "jwt", defaultOrgId, plugins, auth: callerAuth, ...appOptions } = options;
1054
1121
  let dbHandle;
1055
1122
  let dbUri;
@@ -1119,4 +1186,4 @@ function createMinimalTestApp(options = {}) {
1119
1186
  });
1120
1187
  }
1121
1188
  //#endregion
1122
- export { HttpTestHarness, createBetterAuthProvider, createBetterAuthTestHelpers, createCustomAuthProvider, createDataFactory, createHttpTestHarness, createJwtAuthProvider, createMinimalTestApp, createMockController, createMockReply, createMockRepository, createMockRequest, createMockUser, createSpy, createTestApp, createTestFixtures, createTestTimer, expectArc, preloadResources, preloadResourcesAsync, runStorageContract, safeParseBody, setupBetterAuthTestApp, waitFor };
1189
+ export { HttpTestHarness, bootModuleApp, createBetterAuthProvider, createBetterAuthTestHelpers, createCustomAuthProvider, createDataFactory, createHttpTestHarness, createJwtAuthProvider, createMinimalTestApp, createMockController, createMockReply, createMockRepository, createMockRequest, createMockUser, createSpy, createTestApp, createTestFixtures, createTestTimer, expectArc, mongoMemoryDatabase, preloadResources, preloadResourcesAsync, runStorageContract, safeParseBody, setupBetterAuthTestApp, waitFor };
@@ -1,5 +1,5 @@
1
- import { $ as OnTenantDeleteConfig, $t as UserOrganization, A as RequestIdOptions, C as RequestContext, D as HealthCheck, E as GracefulShutdownOptions, F as FastifyWithDecorators, Fn as BaseControllerOptions, G as ActionsMap, Gt as JwtContext, H as ActionDefinition, Ht as AuthPluginOptions, I as MiddlewareHandler, J as CrudRouteKey, Jt as ApiResponse, K as ArcFieldRule, Kt as TokenPair, L as RequestWithExtras, M as EventsDecorator, N as FastifyRequestExtras, O as HealthOptions, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as UserLike, S as QueryParserInterface, St as RouteHandler, T as CrudRouterOptions, U as ActionEntry, Ut as Authenticator, Vt as AuthHelpers, W as ActionHandlerFn, Wt as AuthenticatorContext, X as EventDefinition, Xt as JWTPayload, Y as CrudSchemas, Yt as ArcRequest, Z as FieldRule, Zt as ObjectId, _ as ControllerQueryOptions, _t as ControllerLike, a as InferAdapterDoc, at as ResolvedTenantPurge, b as ParsedQuery, bt as IControllerResponse, c as TypedController, ct as ResourceExtensions, d as PaginationResult, dt as ResourcePermissions, et as OpenApiSchemas, f as IntrospectionData, ft as RouteDefinition, g as ArcInternalMetadata, gt as ControllerHandler, h as ResourceMetadata, ht as RouteSchemaOptions, i as ValidationResult, it as RateLimitConfig, j as ArcDecorator, k as IntrospectionPluginOptions, l as TypedRepository, lt as ResourceHookContext, m as RegistryStats, mt as RouteMethod, n as ConfigError, nt as PresetHook, o as InferDocType, ot as ResourceCacheConfig, p as RegistryEntry, pt as RouteMcpConfig, q as CrudController, qt as AnyRecord, r as ValidateOptions, rt as PresetResult, s as InferResourceDoc, st as ResourceConfig, t as RouteHandlerMethod, tt as PresetFunction, u as TypedResourceConfig, ut as ResourceHooks, v as LookupOption, vt as FastifyHandler, w as ServiceContext, x as PopulateOption, xt as IRequestContext, y as OwnershipCheck, yt as IController } from "../index-Dtrj6XZk.mjs";
1
+ import { $ as OpenApiSchemas, $t as UserLike, A as RequestIdOptions, At as RouteDefinition, Bt as RouteHandler, C as RequestContext, D as HealthCheck, Dt as ActionEntry, E as GracefulShutdownOptions, Et as ActionDefinition, F as FastifyWithDecorators, Ft as ControllerLike, G as OnTenantDeleteConfig, Gt as AuthenticatorContext, H as CrudController, Ht as AuthHelpers, I as MiddlewareHandler, In as BaseControllerOptions, It as FastifyHandler, J as PresetHook, Jt as AnyRecord, K as ResolvedTenantPurge, Kt as JwtContext, L as RequestWithExtras, Lt as IController, M as EventsDecorator, Mt as RouteMethod, N as FastifyRequestExtras, Nt as RateLimitConfig, O as HealthOptions, Ot as ActionHandlerFn, P as FastifyWithAuth, Pt as ControllerHandler, Q as MiddlewareConfig, Qt as ObjectId, Rt as IControllerResponse, S as QueryParserInterface, T as CrudRouterOptions, Tt as ResourceCacheConfig, U as ResourceConfig, Ut as AuthPluginOptions, W as ResourcePermissions, Wt as Authenticator, X as CrudRouteKey, Xt as ArcRequest, Y as PresetResult, Yt as ApiResponse, Z as CrudSchemas, Zt as JWTPayload, _ as ControllerQueryOptions, a as InferAdapterDoc, at as ResourceExtensions, b as ParsedQuery, c as TypedController, d as PaginationResult, en as UserOrganization, et as RouteSchemaOptions, f as IntrospectionData, g as ArcInternalMetadata, h as ResourceMetadata, i as ValidationResult, it as ResourceHooks, j as ArcDecorator, jt as RouteMcpConfig, k as IntrospectionPluginOptions, kt as ActionsMap, l as TypedRepository, m as RegistryStats, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, q as PresetFunction, qt as TokenPair, r as ValidateOptions, rt as ResourceHookContext, s as InferResourceDoc, t as RouteHandlerMethod, tt as ArcFieldRule, u as TypedResourceConfig, v as LookupOption, w as ServiceContext, x as PopulateOption, y as OwnershipCheck, zt as IRequestContext } from "../index-BBsvQt7U.mjs";
2
2
  import { i as RequestScope } from "../types-DH0GupI7.mjs";
3
- import { c as PermissionCheck, d as UserBase, l as PermissionContext, u as PermissionResult } from "../fields-BGqrAa_u.mjs";
3
+ import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "../types-Csxga7d3.mjs";
4
4
  import { n as ElevationOptions, t as ElevationEvent } from "../elevation-C9s5hFP_.mjs";
5
5
  export type { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ApiResponse, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, ResourceCacheConfig, ResourceConfig, ResourceExtensions, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult };
@@ -1,4 +1,4 @@
1
- import { V as ResourceDefinition } from "./index-Dtrj6XZk.mjs";
1
+ import { V as ResourceDefinition } from "./index-BBsvQt7U.mjs";
2
2
  import { z } from "zod";
3
3
  //#region src/integrations/mcp/types.d.ts
4
4
  /** Behavioral hints for MCP clients (tool annotations per MCP spec) */
@@ -157,6 +157,41 @@ interface CrudDescriptionMeta {
157
157
  * Arc's auto-derived filterable-fields blurb.
158
158
  */
159
159
  type CrudDescriptionOverride = string | ((meta: CrudDescriptionMeta) => string);
160
+ /**
161
+ * Execution wiring for MCP tools — the app-level services HTTP requests
162
+ * receive via Fastify decorators (`fastify.arc.hooks`, `fastify.events`,
163
+ * `fastify.audit`, `fastify.log`, `fastify.idempotency`) and MCP's
164
+ * synthetic-context path historically dropped.
165
+ *
166
+ * When present, tool handlers thread it into the request context so the
167
+ * controller pipeline achieves FULL HTTP parity: resource hooks run
168
+ * (before/around/after), the arcCorePlugin after-hook publishes
169
+ * `<resource>.<op>d` events (→ realtime feeds, webhooks, event-driven
170
+ * cache invalidation all see MCP-originated mutations), `ctx.server.*`
171
+ * works inside handlers, and mutating CRUD tools accept an optional
172
+ * `_idempotencyKey` input for retry-safe execution.
173
+ *
174
+ * `mcpPlugin` builds this automatically from its Fastify instance (lazy
175
+ * getters — decorator registration order doesn't matter). Standalone
176
+ * `resourceToTools()` / `createMcpServer()` callers pass their own, or
177
+ * omit it to keep the legacy dispatch-only behavior.
178
+ */
179
+ interface McpExecutionWiring {
180
+ /** Shared `HookSystem` — `fastify.arc.hooks`. */
181
+ readonly hooks?: unknown;
182
+ /** Event bus decorator — `fastify.events`. */
183
+ readonly events?: unknown;
184
+ /** Audit decorator — `fastify.audit`. */
185
+ readonly audit?: unknown;
186
+ /** Structured logger — `fastify.log`. */
187
+ readonly log?: unknown;
188
+ /**
189
+ * Idempotency store (the `IdempotencyStore` contract from
190
+ * `@classytic/arc/idempotency`). Presence advertises `_idempotencyKey`
191
+ * on mutating CRUD tools and enables executor-level check/lock/replay.
192
+ */
193
+ readonly idempotencyStore?: unknown;
194
+ }
160
195
  /** Per-resource MCP configuration overrides */
161
196
  interface McpResourceConfig {
162
197
  /** Which CRUD operations to expose (default: all enabled on the resource) */
@@ -392,4 +427,4 @@ interface CreateMcpServerConfig {
392
427
  /** CRUD operation type */
393
428
  type CrudOperation = "list" | "get" | "create" | "update" | "delete";
394
429
  //#endregion
395
- export { CrudDescriptionOverride as a, McpAuthResult as c, PromptDefinition as d, PromptResult as f, ToolDefinition as g, ToolContext as h, CrudDescriptionMeta as i, McpPluginOptions as l, ToolAnnotations as m, CallToolResult as n, CrudOperation as o, SessionEntry as p, CreateMcpServerConfig as r, McpAuthResolver as s, BetterAuthHandler as t, McpResourceConfig as u };
430
+ export { ToolDefinition as _, CrudDescriptionOverride as a, McpAuthResult as c, McpResourceConfig as d, PromptDefinition as f, ToolContext as g, ToolAnnotations as h, CrudDescriptionMeta as i, McpExecutionWiring as l, SessionEntry as m, CallToolResult as n, CrudOperation as o, PromptResult as p, CreateMcpServerConfig as r, McpAuthResolver as s, BetterAuthHandler as t, McpPluginOptions as u };
@@ -195,124 +195,4 @@ interface PermissionCheckMeta {
195
195
  };
196
196
  }
197
197
  //#endregion
198
- //#region src/permissions/fields.d.ts
199
- /**
200
- * Field-Level Permissions
201
- *
202
- * Control field visibility and writability per role.
203
- * Integrated into the response path (read) and sanitization path (write).
204
- *
205
- * @example
206
- * ```typescript
207
- * import { fields, defineResource } from '@classytic/arc';
208
- *
209
- * const userResource = defineResource({
210
- * name: 'user',
211
- * adapter: userAdapter,
212
- * fields: {
213
- * salary: fields.visibleTo(['admin', 'hr']),
214
- * internalNotes: fields.writableBy(['admin']),
215
- * email: fields.redactFor(['viewer']),
216
- * password: fields.hidden(),
217
- * },
218
- * });
219
- * ```
220
- */
221
- type FieldPermissionType = "hidden" | "visibleTo" | "writableBy" | "redactFor";
222
- interface FieldPermission {
223
- readonly _type: FieldPermissionType;
224
- readonly roles?: readonly string[];
225
- readonly redactValue?: unknown;
226
- }
227
- type FieldPermissionMap = Record<string, FieldPermission>;
228
- declare const fields: {
229
- /**
230
- * Field is never included in responses. Not writable via API.
231
- *
232
- * @example
233
- * ```typescript
234
- * fields: { password: fields.hidden() }
235
- * ```
236
- */
237
- hidden(): FieldPermission;
238
- /**
239
- * Field is only visible to users with specified roles.
240
- * Other users don't see the field at all.
241
- *
242
- * @example
243
- * ```typescript
244
- * fields: { salary: fields.visibleTo(['admin', 'hr']) }
245
- * ```
246
- */
247
- visibleTo(roles: readonly string[]): FieldPermission;
248
- /**
249
- * Field is only writable by users with specified roles.
250
- * All users can still read the field. Users without the role
251
- * have the field silently stripped from write operations.
252
- *
253
- * @example
254
- * ```typescript
255
- * fields: { role: fields.writableBy(['admin']) }
256
- * ```
257
- */
258
- writableBy(roles: readonly string[]): FieldPermission;
259
- /**
260
- * Field is redacted (replaced with a placeholder) for specified roles.
261
- * Other users see the real value.
262
- *
263
- * @param roles - Roles that see the redacted value
264
- * @param redactValue - Replacement value (default: '***')
265
- *
266
- * @example
267
- * ```typescript
268
- * fields: {
269
- * email: fields.redactFor(['viewer']),
270
- * ssn: fields.redactFor(['basic'], '***-**-****'),
271
- * }
272
- * ```
273
- */
274
- redactFor(roles: readonly string[], redactValue?: unknown): FieldPermission;
275
- };
276
- /**
277
- * Apply field-level READ permissions to a response object.
278
- * Strips hidden fields, enforces visibility, and applies redaction.
279
- *
280
- * @param data - The response object (mutated in place for performance)
281
- * @param fieldPermissions - Field permission map from resource config
282
- * @param userRoles - Current user's roles (empty array for unauthenticated)
283
- * @returns The filtered object
284
- */
285
- declare function applyFieldReadPermissions<T extends Record<string, unknown>>(data: T, fieldPermissions: FieldPermissionMap, userRoles: readonly string[]): T;
286
- /**
287
- * Result of applying write permissions — includes both the filtered body
288
- * and the list of fields that were stripped so callers can decide whether
289
- * to reject the request (secure default) or silently strip (legacy).
290
- */
291
- interface FieldWritePermissionResult<T extends Record<string, unknown>> {
292
- readonly body: T;
293
- readonly deniedFields: readonly string[];
294
- }
295
- /**
296
- * Apply field-level WRITE permissions to request body.
297
- *
298
- * Returns both the filtered body and the list of denied fields. Callers are
299
- * expected to reject the request when `deniedFields.length > 0` — silently
300
- * stripping fields hides misconfigurations and real attacks. See
301
- * `BodySanitizer` for the default policy.
302
- *
303
- * @param body - The request body (returns a new filtered copy)
304
- * @param fieldPermissions - Field permission map from resource config
305
- * @param userRoles - Current user's roles
306
- */
307
- declare function applyFieldWritePermissions<T extends Record<string, unknown>>(body: T, fieldPermissions: FieldPermissionMap, userRoles: readonly string[]): FieldWritePermissionResult<T>;
308
- /**
309
- * Resolve effective roles by merging global user roles with org-level roles.
310
- *
311
- * Global roles come from `req.user.role` (normalized via getUserRoles()).
312
- * Org roles come from `req.context.orgRoles` (set by BA adapter's org bridge).
313
- *
314
- * When no org context exists, returns global roles only — backward compatible.
315
- */
316
- declare function resolveEffectiveRoles(userRoles: readonly string[], orgRoles: readonly string[]): string[];
317
- //#endregion
318
- export { applyFieldWritePermissions as a, PermissionCheck as c, UserBase as d, getUserRoles as f, applyFieldReadPermissions as i, PermissionContext as l, FieldPermissionMap as n, fields as o, normalizeRoles as p, FieldPermissionType as r, resolveEffectiveRoles as s, FieldPermission as t, PermissionResult as u };
198
+ export { getUserRoles as a, UserBase as i, PermissionContext as n, normalizeRoles as o, PermissionResult as r, PermissionCheck as t };
@@ -0,0 +1,142 @@
1
+ import { i as RequestScope } from "../types-DH0GupI7.mjs";
2
+ import { n as PermissionContext, t as PermissionCheck } from "../types-Csxga7d3.mjs";
3
+ import { FastifyPluginAsync, FastifyRequest } from "fastify";
4
+ //#region src/usage/requireQuota.d.ts
5
+ interface QuotaOptions {
6
+ /** Counter to enforce — `ai.tokens`, `export.runs`, `api.requests`, ... */
7
+ kind: string;
8
+ /**
9
+ * Ceiling for the current period. A number, `false` (unlimited — lets
10
+ * plan tables express "enterprise: false" uniformly), or a sync/async
11
+ * resolver receiving the permission context (plan-aware quotas).
12
+ */
13
+ limit: number | false | ((ctx: PermissionContext) => number | false | Promise<number | false>);
14
+ /**
15
+ * Actor key override. Default: the meter's own chain
16
+ * (org → user → client → `ip:<addr>`), so quota buckets are the same
17
+ * buckets usage writes and rate limits read.
18
+ */
19
+ actorOf?: (ctx: PermissionContext) => string | undefined;
20
+ /**
21
+ * Counter-store failure policy. Default `'allow'` (fail-open — see
22
+ * module header). `'deny'` throws the same 429 shape with
23
+ * `code: 'quota.unavailable'` and status 503.
24
+ */
25
+ onStoreError?: "allow" | "deny";
26
+ /** Memoize summary reads per (actor, kind) for this many ms. Default 0. */
27
+ cacheTtlMs?: number;
28
+ }
29
+ declare function requireQuota(options: QuotaOptions): PermissionCheck;
30
+ //#endregion
31
+ //#region src/usage/stores/interface.d.ts
32
+ /**
33
+ * Usage store contract — period-bucketed counters per actor.
34
+ *
35
+ * CANONICAL HOME: `@classytic/repo-core/usage` (>=0.10) owns this
36
+ * contract for the ecosystem — kits implement it there without ever
37
+ * depending on arc (`@classytic/mongokit/usage`, ...). This file is a
38
+ * deliberate STRUCTURAL MIRROR of that shape — same trick as
39
+ * `ScheduleLockLike` vs repo-core's `LockAdapter` — so arc's emitted
40
+ * declarations carry no repo-core@>=0.10 subpath reference and the
41
+ * peer floor stays honest. Any conforming adapter assigns directly.
42
+ *
43
+ * The deliberately tiny surface (one increment, one read) is what makes
44
+ * every backend trivial: memory (dev/tests), Redis (`HINCRBY`), or any kit
45
+ * (Mongo `$inc` upsert) implements it in a handful of lines. Aggregation
46
+ * happens IN the store — arc never buffers counters in process memory
47
+ * beyond the built-in memory store, so multi-replica deployments stay
48
+ * correct as long as the store is shared.
49
+ *
50
+ * This is the HORIZONTAL usage layer (per-actor, per-period platform
51
+ * accounting for quotas/plans/billing). Itemized vertical records — e.g.
52
+ * `@classytic/arc-ai/usage`'s per-run AI token/cost tracking — keep their
53
+ * own richer stores and can sink into this one (`kind: 'ai.tokens'`).
54
+ */
55
+ /** One counter cell: (actor, period, kind). */
56
+ interface UsageBucket {
57
+ /** Who consumed — org / user / client id, or an IP-derived fallback. */
58
+ actor: string;
59
+ /** Aggregation period, `YYYY-MM` (see `usagePeriod()`). */
60
+ period: string;
61
+ /** Namespaced counter, dot-separated: `api.requests`, `ai.tokens`, `storage.bytes`. */
62
+ kind: string;
63
+ }
64
+ interface UsageStore {
65
+ /** Store name for diagnostics (e.g. 'memory', 'redis', 'mongo'). */
66
+ readonly name: string;
67
+ /** Add `amount` to the bucket's counter, creating it at 0 first. MUST be atomic per bucket. */
68
+ increment(bucket: UsageBucket, amount: number): Promise<void> | void;
69
+ /** Every counter for an actor in a period: `{ 'api.requests': 40231, ... }`. */
70
+ summary(actor: string, period: string): Promise<Record<string, number>>;
71
+ /** Optional cleanup hook (connections, timers). */
72
+ close?(): Promise<void>;
73
+ }
74
+ /**
75
+ * Canonical period key for a date — calendar month, UTC: `2026-07`.
76
+ * Monthly is the billing-native granularity; stores that want finer
77
+ * windows can shard internally without changing the contract.
78
+ */
79
+ declare function usagePeriod(date?: Date): string;
80
+ //#endregion
81
+ //#region src/usage/stores/memory.d.ts
82
+ declare class MemoryUsageStore implements UsageStore {
83
+ #private;
84
+ readonly name = "memory";
85
+ increment(bucket: UsageBucket, amount: number): void;
86
+ summary(actor: string, period: string): Promise<Record<string, number>>;
87
+ /** Test convenience — drop everything. */
88
+ clear(): void;
89
+ }
90
+ //#endregion
91
+ //#region src/usage/usagePlugin.d.ts
92
+ interface UsageTrackOptions {
93
+ /** Count every completed request as `api.requests` (default: true). */
94
+ requests?: boolean;
95
+ /** Sum `content-length` response bytes as `api.egress.bytes` (default: false). */
96
+ egress?: boolean;
97
+ }
98
+ interface UsagePluginOptions {
99
+ /** Master switch — `false` registers a typed no-op (config-gated environments). */
100
+ enabled?: boolean;
101
+ /** Counter backend. Default: in-memory (per-process — use a shared store in multi-replica). */
102
+ store?: UsageStore;
103
+ /** Automatic per-request accounting. Default: `{ requests: true, egress: false }`. */
104
+ track?: UsageTrackOptions;
105
+ /**
106
+ * Derive the actor key from a request. Default: org → user → client →
107
+ * `ip:<addr>` (same chain as `createTenantKeyGenerator`).
108
+ */
109
+ actorOf?: (request: FastifyRequest) => string | undefined;
110
+ /**
111
+ * Paths exempt from automatic tracking. Exact or trailing-`*` prefix.
112
+ * Default: `['/_health*', '/_metrics*']`.
113
+ */
114
+ ignorePaths?: string[];
115
+ }
116
+ /** The `fastify.usage` surface. */
117
+ interface UsageMeter {
118
+ /**
119
+ * Add to a counter. `actor` may be a raw key or a `RequestScope`
120
+ * (derived via the org → user → client chain). Fire-and-forget safe:
121
+ * awaiting is optional, errors never throw into request flow.
122
+ */
123
+ record(actor: string | RequestScope | undefined, kind: string, amount?: number): Promise<void>;
124
+ /** All counters for an actor. Period defaults to the current month. */
125
+ summary(actor: string, period?: string): Promise<Record<string, number>>;
126
+ /** Canonical period key (`YYYY-MM`) for a date. */
127
+ period(date?: Date): string;
128
+ /** The actor key automatic tracking would use for this request. */
129
+ actorOf(request: FastifyRequest): string;
130
+ /** The active store (diagnostics). */
131
+ readonly store: UsageStore;
132
+ }
133
+ declare module "fastify" {
134
+ interface FastifyInstance {
135
+ /** Per-actor usage counters — registered by `usagePlugin`. */
136
+ usage?: UsageMeter;
137
+ }
138
+ }
139
+ declare const usagePluginFn: FastifyPluginAsync<UsagePluginOptions>;
140
+ declare const _default: FastifyPluginAsync<UsagePluginOptions>;
141
+ //#endregion
142
+ export { MemoryUsageStore, type QuotaOptions, type UsageBucket, type UsageMeter, type UsagePluginOptions, type UsageStore, type UsageTrackOptions, _default as default, requireQuota, usagePeriod, usagePluginFn as usagePlugin };
Binary file
@@ -1,5 +1,5 @@
1
- import { Qt as UserLike, S as QueryParserInterface, b as ParsedQuery, et as OpenApiSchemas, qt as AnyRecord, st as ResourceConfig } from "../index-Dtrj6XZk.mjs";
2
- import { n as ErrorMapper } from "../errorHandler-B0e-bq-O.mjs";
1
+ import { $ as OpenApiSchemas, $t as UserLike, Jt as AnyRecord, S as QueryParserInterface, U as ResourceConfig, b as ParsedQuery } from "../index-BBsvQt7U.mjs";
2
+ import { n as ErrorMapper } from "../errorHandler-C6yv4ZTW.mjs";
3
3
  import { a as NotFoundError, c as RateLimitError, d as ValidationError, f as createDomainError, i as ForbiddenError, l as ServiceUnavailableError, m as isArcError, n as ConflictError, o as OrgAccessDeniedError, p as createError, r as ErrorOptions, s as OrgRequiredError, t as ArcError, u as UnauthorizedError } from "../errors-DHcHVAgk.mjs";
4
4
  import { errorContractSchema, errorDetailSchema } from "@classytic/repo-core/errors";
5
5
  import { FastifyInstance, FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
@@ -437,6 +437,34 @@ declare const NEUTRAL_DIALECT: FilterDialect;
437
437
  */
438
438
  declare function handleRaw<T>(handler: (request: FastifyRequest, reply: FastifyReply) => Promise<T>, statusCode?: number): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
439
439
  //#endregion
440
+ //#region src/utils/headers.d.ts
441
+ /**
442
+ * Canonical header typing + accessor.
443
+ *
444
+ * Node/Fastify header values are `string | string[] | undefined` — repeated
445
+ * headers arrive as arrays. `IRequestContext.headers` is DECLARED as
446
+ * `Record<string, string | undefined>` for ergonomic host code, but the HTTP
447
+ * adapter passes Fastify's headers object through unchanged, so `string[]`
448
+ * CAN appear at runtime behind the narrower type (the declared type is
449
+ * scheduled to widen to {@link ArcHeaders} in v3). Until then, read headers
450
+ * through {@link getHeader} instead of indexing — it's honest about arrays
451
+ * and deterministic about duplicates.
452
+ */
453
+ /** What a headers bag actually contains at runtime — HTTP or synthetic MCP. */
454
+ type ArcHeaders = Readonly<Record<string, string | readonly string[] | undefined>>;
455
+ /**
456
+ * Read a single header value. Lowercases the name (Node normalizes incoming
457
+ * header names to lowercase) and returns the FIRST value when the header
458
+ * was repeated.
459
+ *
460
+ * Duplicate policy: first-value is deterministic, but for security-sensitive
461
+ * headers (authorization material, forwarded-for chains, content-length) a
462
+ * duplicate usually signals smuggling or a broken proxy — consumers that
463
+ * care should check `Array.isArray(headers[name])` and REJECT instead of
464
+ * picking a winner.
465
+ */
466
+ declare function getHeader(headers: ArcHeaders | Record<string, string | undefined> | undefined, name: string): string | undefined;
467
+ //#endregion
440
468
  //#region src/utils/queryParser.d.ts
441
469
  interface ArcQueryParserOptions {
442
470
  /** Maximum allowed limit value (default: 1000) */
@@ -599,9 +627,8 @@ declare function createQueryParser(options?: ArcQueryParserOptions): ArcQueryPar
599
627
  interface JsonSchema {
600
628
  /**
601
629
  * Optional because JSON Schema allows top-level combinator-only schemas
602
- * (`{ oneOf: [...] }`, `{ anyOf: [...] }`, `{ allOf: [...] }`) — see
603
- * `listResponse()`, which emits a `oneOf` of the four canonical list
604
- * shapes with no top-level `type`.
630
+ * (`{ oneOf: [...] }`, `{ anyOf: [...] }`, `{ allOf: [...] }`) — hosts
631
+ * may pass such schemas anywhere a `JsonSchema` is accepted.
605
632
  */
606
633
  type?: string | string[];
607
634
  properties?: Record<string, JsonSchema | AnyRecord>;
@@ -623,18 +650,25 @@ interface JsonSchema {
623
650
  */
624
651
  declare const paginationSchema: JsonSchema;
625
652
  /**
626
- * List response schema — full union of every wire shape `toCanonicalList`
627
- * can emit. Hosts who know their endpoint only ever produces one variant
628
- * can pin to a narrower helper:
653
+ * List response schema — accepts every wire shape `toCanonicalList` can
654
+ * emit. Hosts who know their endpoint only ever produces one variant can
655
+ * pin to a narrower helper (sharper OpenAPI docs, same serializer speed):
629
656
  * - `offsetListResponse(item)` — `{ method: 'offset', data, page, limit, total, pages, hasNext, hasPrev }`
630
657
  * - `keysetListResponse(item)` — `{ method: 'keyset', data, limit, hasMore, next: string|null }`
631
658
  * - `aggregateListResponse(item)` — `{ method: 'aggregate', ...offset fields }`
632
659
  * - `bareListResponse(item)` — `{ data }`
633
660
  *
634
- * The default `listResponse(item)` is the union (`oneOf`) of all four so
635
- * Fastify validation accepts any canonical kit shape — pre-2.13 this only
636
- * modelled offset and rejected keyset/aggregate/bare lists at the
637
- * response-schema gate.
661
+ * SHAPE: one merged permissive object, NOT a `oneOf` union (2.22). The
662
+ * pre-2.22 union was semantically identical on the wire — every variant is
663
+ * `additionalProperties: true` and the property definitions never conflict
664
+ * (`next` only exists on keyset, the offset counters only on offset/
665
+ * aggregate; fast-json-stringify skips undefined optionals) — but
666
+ * fast-json-stringify implements top-level `oneOf` by running full AJV
667
+ * validation PER RESPONSE to pick the branch, on the hottest route of
668
+ * every arc app. The merge keeps the exact bytes (pinned by
669
+ * `tests/utils/list-response-serialization.test.ts`) and drops the
670
+ * per-response branch validation. Only `data` is required — the one field
671
+ * all four variants share.
638
672
  */
639
673
  declare function listResponse(itemSchema: JsonSchema): JsonSchema;
640
674
  /** Offset variant — `{ method: 'offset', data, page, limit, total, pages, hasNext, hasPrev }`. */
@@ -663,9 +697,8 @@ declare const responses: {
663
697
  schema: {
664
698
  /**
665
699
  * Optional because JSON Schema allows top-level combinator-only schemas
666
- * (`{ oneOf: [...] }`, `{ anyOf: [...] }`, `{ allOf: [...] }`) — see
667
- * `listResponse()`, which emits a `oneOf` of the four canonical list
668
- * shapes with no top-level `type`.
700
+ * (`{ oneOf: [...] }`, `{ anyOf: [...] }`, `{ allOf: [...] }`) — hosts
701
+ * may pass such schemas anywhere a `JsonSchema` is accepted.
669
702
  */
670
703
  type?: string | string[];
671
704
  properties?: Record<string, JsonSchema | AnyRecord>;
@@ -1103,6 +1136,20 @@ declare function isJsonSchema(input: unknown): input is Record<string, unknown>;
1103
1136
  * Check if an object is a Zod schema (has `_zod` marker from Zod v4).
1104
1137
  */
1105
1138
  declare function isZodSchema(input: unknown): boolean;
1139
+ /**
1140
+ * How `toJsonSchema` reacts when a Zod schema CANNOT be converted (zod not
1141
+ * installed/loaded, zod v3, or `z.toJSONSchema()` threw):
1142
+ *
1143
+ * - `'throw'` — fail fast with an actionable error. Used by
1144
+ * `convertRouteSchema` (VALIDATION path): a schema that silently degrades
1145
+ * to `{ type: 'object' }` is validation switched off — the worst outcome
1146
+ * for a wire contract, worse than a boot failure.
1147
+ * - `'warn'` (default) — log loudly, degrade to a permissive `{ type:
1148
+ * 'object' }`. Used by doc-generation paths (OpenAPI extraction of
1149
+ * Better Auth endpoints etc.), where the schema is third-party and a doc
1150
+ * gap must not take the app down.
1151
+ */
1152
+ type UnconvertibleMode = "warn" | "throw";
1106
1153
  /**
1107
1154
  * Convert any schema input to JSON Schema.
1108
1155
  *
@@ -1110,13 +1157,16 @@ declare function isZodSchema(input: unknown): boolean;
1110
1157
  * 1. `null`/`undefined` → `undefined`
1111
1158
  * 2. Already JSON Schema → pass through as-is (zero overhead)
1112
1159
  * 3. Zod v4 schema → `z.toJSONSchema(schema, { target })`
1113
- * 4. Unrecognized object → return as-is (treat as opaque schema)
1160
+ * 4. Zod v3 schema → unconvertible (actionable "upgrade to v4" error/warn)
1161
+ * 5. Unrecognized object → return as-is (treat as opaque schema)
1114
1162
  *
1115
- * @param input Schema (Zod, plain JSON Schema, or opaque object)
1163
+ * @param input Schema (Zod, plain JSON Schema, or opaque object)
1116
1164
  * @param target Output target — defaults to `draft-7` for Fastify compatibility.
1117
1165
  * Pass `openapi-3.0`/`openapi-3.1` for OpenAPI document generation.
1166
+ * @param mode Failure policy for unconvertible Zod schemas — see
1167
+ * {@link UnconvertibleMode}. Defaults to `'warn'`.
1118
1168
  */
1119
- declare function toJsonSchema(input: unknown, target?: JsonSchemaTarget): Record<string, unknown> | undefined;
1169
+ declare function toJsonSchema(input: unknown, target?: JsonSchemaTarget, mode?: UnconvertibleMode): Record<string, unknown> | undefined;
1120
1170
  /**
1121
1171
  * Convert all schema fields in an OpenApiSchemas object.
1122
1172
  * JSON Schema values pass through unchanged. Only Zod schemas are converted.
@@ -1193,6 +1243,38 @@ declare function convertRouteSchema(schema: Record<string, unknown>, target?: Js
1193
1243
  */
1194
1244
  declare function simpleEqualityMatcher(item: unknown, filters: Record<string, unknown>): boolean;
1195
1245
  //#endregion
1246
+ //#region src/utils/sseStream.d.ts
1247
+ interface SseStreamOptions {
1248
+ /** Heartbeat comment interval in ms (default: 30000). */
1249
+ heartbeatMs?: number;
1250
+ /**
1251
+ * Reconnection-delay hint written once at connect as the standard SSE
1252
+ * `retry:` field (WHATWG EventSource honors it natively). Omit to send
1253
+ * no hint (browser default ~3s).
1254
+ */
1255
+ retryMs?: number;
1256
+ }
1257
+ interface SseStream {
1258
+ /**
1259
+ * Write one SSE frame. `id` (optional) becomes the standard SSE `id:`
1260
+ * field — clients receive it as `lastEventId` (WHATWG), enabling
1261
+ * client-side dedup/resume bookkeeping even when the server keeps no
1262
+ * replay log. Returns `false` when the connection was destroyed
1263
+ * (backpressure) — the stream is already cleaned up; stop writing.
1264
+ */
1265
+ write(eventName: string, data: string, id?: string): boolean;
1266
+ /** Idempotent teardown: heartbeat cleared, cleanups run, socket ended. */
1267
+ close(): void;
1268
+ /** Register teardown work (unsubscribes etc.) — runs exactly once. */
1269
+ onCleanup(fn: () => void): void;
1270
+ }
1271
+ /**
1272
+ * Take over the reply socket and open an SSE stream. Call ONLY after every
1273
+ * gate (auth, permissions, validation) has passed — after `hijack()` no
1274
+ * JSON error can be sent.
1275
+ */
1276
+ declare function openSseStream(request: FastifyRequest, reply: FastifyReply, options?: SseStreamOptions): SseStream;
1277
+ //#endregion
1196
1278
  //#region src/utils/stateMachine.d.ts
1197
1279
  /**
1198
1280
  * State Machine Utility
@@ -1453,4 +1535,4 @@ declare function hasEvents(instance: FastifyInstance): instance is FastifyInstan
1453
1535
  */
1454
1536
  declare function getUserId(user: UserLike | null | undefined): string | undefined;
1455
1537
  //#endregion
1456
- export { ArcError, ArcQueryParser, type ArcQueryParserOptions, CircuitBreaker, CircuitBreakerError, type CircuitBreakerOptions, CircuitBreakerRegistry, type CircuitBreakerStats, CircuitState, type CompensationDefinition, type CompensationError, type CompensationHooks, type CompensationResult, type CompensationStep, type ConfigError, ConflictError, type ErrorOptions, type EventsDecorator, type FilterDialect, ForbiddenError, type Guard, type GuardConfig, type JsonSchema, type JsonSchemaTarget, MONGO_DIALECT, NEUTRAL_DIALECT, NotFoundError, OrgAccessDeniedError, OrgRequiredError, type PipeUIMessageStreamOptions, RateLimitError, ServiceUnavailableError, type StateMachine, type TransitionConfig, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, type ValidateOptions, ValidationError, type ValidationResult, aggregateListResponse, assertValidConfig, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, formatValidationErrors, forwardedStreamHeaders, getDefaultCrudSchemas, getListQueryParams, getUserId, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, offsetListResponse, paginationSchema, pipeUIMessageStreamToReply, promoteStreamTokenToHeader, queryParams, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, validateResourceConfig, withCompensation };
1538
+ export { ArcError, type ArcHeaders, ArcQueryParser, type ArcQueryParserOptions, CircuitBreaker, CircuitBreakerError, type CircuitBreakerOptions, CircuitBreakerRegistry, type CircuitBreakerStats, CircuitState, type CompensationDefinition, type CompensationError, type CompensationHooks, type CompensationResult, type CompensationStep, type ConfigError, ConflictError, type ErrorOptions, type EventsDecorator, type FilterDialect, ForbiddenError, type Guard, type GuardConfig, type JsonSchema, type JsonSchemaTarget, MONGO_DIALECT, NEUTRAL_DIALECT, NotFoundError, OrgAccessDeniedError, OrgRequiredError, type PipeUIMessageStreamOptions, RateLimitError, ServiceUnavailableError, type SseStream, type SseStreamOptions, type StateMachine, type TransitionConfig, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, type ValidateOptions, ValidationError, type ValidationResult, aggregateListResponse, assertValidConfig, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, formatValidationErrors, forwardedStreamHeaders, getDefaultCrudSchemas, getHeader, getListQueryParams, getUserId, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, offsetListResponse, openSseStream, paginationSchema, pipeUIMessageStreamToReply, promoteStreamTokenToHeader, queryParams, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, validateResourceConfig, withCompensation };
@@ -1,6 +1,8 @@
1
1
  import { a as OrgAccessDeniedError, c as ServiceUnavailableError, d as createDomainError, f as createError, i as NotFoundError, l as UnauthorizedError, n as ConflictError, o as OrgRequiredError, p as isArcError, r as ForbiddenError, s as RateLimitError, t as ArcError, u as ValidationError } from "../errors-DkO8Nk6-.mjs";
2
- import { A as createCircuitBreaker, C as defineErrorMapper, D as CircuitBreakerError, E as CircuitBreaker, F as simpleEqualityMatcher, M as assertValidConfig, N as formatValidationErrors, O as CircuitBreakerRegistry, P as validateResourceConfig, S as defineGuard, T as withCompensation, _ as ArcQueryParser, a as bareListResponse, b as MONGO_DIALECT, c as errorDetailSchema, d as keysetListResponse, f as listResponse, g as responses, h as queryParams, i as aggregateListResponse, j as createCircuitBreakerRegistry, k as CircuitState, l as getDefaultCrudSchemas, m as paginationSchema, n as createStateMachine, o as deleteResponse, p as offsetListResponse, r as scheduleBackground, s as errorContractSchema, t as getUserId, u as getListQueryParams, v as createQueryParser, w as defineCompensation, x as NEUTRAL_DIALECT, y as handleRaw } from "../utils-CO8a3B_1.mjs";
3
- import { a as toJsonSchema, i as isZodSchema, n as convertRouteSchema, r as isJsonSchema, t as convertOpenApiSchemas } from "../schemaConverter-U0MnO9vd.mjs";
2
+ import { t as simpleEqualityMatcher } from "../simpleEqualityMatcher-Cg05HPsn.mjs";
3
+ import { A as CircuitState, C as defineGuard, D as CircuitBreaker, E as withCompensation, F as validateResourceConfig, M as createCircuitBreakerRegistry, N as assertValidConfig, O as CircuitBreakerError, P as formatValidationErrors, S as NEUTRAL_DIALECT, T as defineCompensation, _ as ArcQueryParser, a as bareListResponse, b as handleRaw, c as errorDetailSchema, d as keysetListResponse, f as listResponse, g as responses, h as queryParams, i as aggregateListResponse, j as createCircuitBreaker, k as CircuitBreakerRegistry, l as getDefaultCrudSchemas, m as paginationSchema, n as createStateMachine, o as deleteResponse, p as offsetListResponse, r as scheduleBackground, s as errorContractSchema, t as getUserId, u as getListQueryParams, v as createQueryParser, w as defineErrorMapper, x as MONGO_DIALECT, y as getHeader } from "../utils-CZyeRXTh.mjs";
4
+ import { a as isZodSchema, i as isJsonSchema, n as convertRouteSchema, o as toJsonSchema, t as convertOpenApiSchemas } from "../schemaConverter-DJvodiHj.mjs";
4
5
  import { a as promoteStreamTokenToHeader, i as pipeUIMessageStreamToReply, n as forwardedStreamHeaders, r as isReadableStream, t as UI_MESSAGE_STREAM_HEADERS } from "../streaming-BQcW6_Kq.mjs";
6
+ import { t as openSseStream } from "../sseStream-BQ7Qaynp.mjs";
5
7
  import { t as hasEvents } from "../typeGuards-C9KXUly6.mjs";
6
- export { ArcError, ArcQueryParser, CircuitBreaker, CircuitBreakerError, CircuitBreakerRegistry, CircuitState, ConflictError, ForbiddenError, MONGO_DIALECT, NEUTRAL_DIALECT, NotFoundError, OrgAccessDeniedError, OrgRequiredError, RateLimitError, ServiceUnavailableError, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, ValidationError, aggregateListResponse, assertValidConfig, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, formatValidationErrors, forwardedStreamHeaders, getDefaultCrudSchemas, getListQueryParams, getUserId, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, offsetListResponse, paginationSchema, pipeUIMessageStreamToReply, promoteStreamTokenToHeader, queryParams, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, validateResourceConfig, withCompensation };
8
+ export { ArcError, ArcQueryParser, CircuitBreaker, CircuitBreakerError, CircuitBreakerRegistry, CircuitState, ConflictError, ForbiddenError, MONGO_DIALECT, NEUTRAL_DIALECT, NotFoundError, OrgAccessDeniedError, OrgRequiredError, RateLimitError, ServiceUnavailableError, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, ValidationError, aggregateListResponse, assertValidConfig, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, formatValidationErrors, forwardedStreamHeaders, getDefaultCrudSchemas, getHeader, getListQueryParams, getUserId, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, offsetListResponse, openSseStream, paginationSchema, pipeUIMessageStreamToReply, promoteStreamTokenToHeader, queryParams, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, validateResourceConfig, withCompensation };