@classytic/arc 2.6.2 → 2.7.1

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 (135) hide show
  1. package/README.md +95 -1
  2. package/dist/{BaseController-AbbRx3e0.mjs → BaseController-CpMfCXdn.mjs} +214 -16
  3. package/dist/adapters/index.d.mts +2 -2
  4. package/dist/adapters/index.mjs +1 -1
  5. package/dist/{adapters-CTn28N4y.mjs → adapters-BxGgSHjj.mjs} +7 -13
  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-B_nvKNAQ.mjs} +11 -11
  27. package/dist/{defineResource-Ckxg6HrZ.mjs → defineResource-DZzyl4a4.mjs} +73 -56
  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-Dm-HTBCt.d.mts +23 -0
  34. package/dist/{errorHandler-Do4vVQ1f.d.mts → errorHandler-COa51ho_.d.mts} +1 -1
  35. package/dist/{errorHandler-r2595m8T.mjs → errorHandler-DXUttWEO.mjs} +1 -1
  36. package/dist/{eventPlugin-DW45v4V5.d.mts → eventPlugin-BgLxJkIB.d.mts} +1 -1
  37. package/dist/{eventPlugin-Ba00swHF.mjs → eventPlugin-DsaNNXzZ.mjs} +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-BYpRGXif.d.mts +640 -0
  50. package/dist/{index-B4uZm82R.d.mts → index-KXM8_JmQ.d.mts} +47 -4
  51. package/dist/{index-DrCqa3Jq.d.mts → index-StgFaQKD.d.mts} +3 -3
  52. package/dist/index.d.mts +8 -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 +1 -1
  59. package/dist/integrations/mcp/testing.d.mts +1 -1
  60. package/dist/integrations/mcp/testing.mjs +1 -1
  61. package/dist/{interface-CrN45qz1.d.mts → interface-Dwzqt4mn.d.mts} +204 -18
  62. package/dist/{mongodb-pMvOlR5_.d.mts → mongodb-Bq90j-Uj.d.mts} +1 -1
  63. package/dist/{mongodb-kltrBPa1.d.mts → mongodb-DdyYlIXg.d.mts} +1 -1
  64. package/dist/{openapi-CBmZ6EQN.mjs → openapi-C5UhIeWu.mjs} +1 -1
  65. package/dist/org/index.d.mts +2 -2
  66. package/dist/org/index.mjs +1 -1
  67. package/dist/permissions/index.d.mts +4 -4
  68. package/dist/permissions/index.mjs +3 -2
  69. package/dist/{permissions-C8ImI8gC.mjs → permissions-CH4cNwJi.mjs} +358 -64
  70. package/dist/plugins/index.d.mts +4 -4
  71. package/dist/plugins/index.mjs +10 -10
  72. package/dist/plugins/response-cache.mjs +1 -1
  73. package/dist/plugins/tracing-entry.d.mts +1 -1
  74. package/dist/plugins/tracing-entry.mjs +1 -1
  75. package/dist/policies/index.d.mts +1 -1
  76. package/dist/presets/index.d.mts +3 -3
  77. package/dist/presets/index.mjs +1 -1
  78. package/dist/presets/multiTenant.d.mts +53 -3
  79. package/dist/presets/multiTenant.mjs +89 -47
  80. package/dist/{presets-BMfdy34e.mjs → presets-BFrGvvjL.mjs} +2 -2
  81. package/dist/{queryCachePlugin-DcmETvcB.d.mts → queryCachePlugin-Bw8XyJpX.d.mts} +1 -1
  82. package/dist/{queryCachePlugin-XtFplYO9.mjs → queryCachePlugin-CwTpR04-.mjs} +2 -2
  83. package/dist/{redis-D0Qc-9EW.d.mts → redis-CyCntzTO.d.mts} +1 -1
  84. package/dist/{redis-stream-BW9UKLZM.d.mts → redis-stream-We_Ucl9-.d.mts} +1 -1
  85. package/dist/registry/index.d.mts +1 -1
  86. package/dist/registry/index.mjs +2 -2
  87. package/dist/{resourceToTools-DH3c3e-T.mjs → resourceToTools-CkVSSzKg.mjs} +313 -33
  88. package/dist/rpc/index.d.mts +1 -1
  89. package/dist/rpc/index.mjs +1 -1
  90. package/dist/scope/index.d.mts +3 -2
  91. package/dist/scope/index.mjs +4 -3
  92. package/dist/{sse-BF7GR7IB.mjs → sse-Bp3dabF1.mjs} +2 -2
  93. package/dist/testing/index.d.mts +2 -2
  94. package/dist/testing/index.mjs +1 -1
  95. package/dist/types/index.d.mts +4 -3
  96. package/dist/types/index.mjs +1 -1
  97. package/dist/types-AOD8fxIw.mjs +229 -0
  98. package/dist/types-CNEbix8T.d.mts +286 -0
  99. package/dist/{types-DurlBP2N.d.mts → types-ClmkMDK1.d.mts} +1 -1
  100. package/dist/{types-C1Z28coa.d.mts → types-D0qf0Mf4.d.mts} +9 -9
  101. package/dist/types-DPsC0taJ.d.mts +178 -0
  102. package/dist/utils/index.d.mts +3 -3
  103. package/dist/utils/index.mjs +5 -5
  104. package/package.json +34 -22
  105. package/skills/arc/SKILL.md +278 -6
  106. package/skills/arc/references/multi-tenancy.md +208 -0
  107. package/dist/elevation-C_taLQrM.d.mts +0 -147
  108. package/dist/index-NGZksqM5.d.mts +0 -398
  109. package/dist/types-BNUccdcf.d.mts +0 -101
  110. package/dist/types-BhtYdxZU.mjs +0 -91
  111. /package/dist/{EventTransport-wc5hSLik.d.mts → EventTransport-CUpRK_Lg.d.mts} +0 -0
  112. /package/dist/{HookSystem-COkyWztM.mjs → HookSystem-D7lfx--K.mjs} +0 -0
  113. /package/dist/{ResourceRegistry-C6ngvOnn.mjs → ResourceRegistry-DsHiG9cL.mjs} +0 -0
  114. /package/dist/{caching-BSXB-Xr7.mjs → caching-5DtLwIqb.mjs} +0 -0
  115. /package/dist/{circuitBreaker-JP2GdJ4b.d.mts → circuitBreaker-DwxrljLB.d.mts} +0 -0
  116. /package/dist/{circuitBreaker-BOBOpN2w.mjs → circuitBreaker-l18oRgL5.mjs} +0 -0
  117. /package/dist/{errors-CcVbl1-T.d.mts → errors-CCSsMpXE.d.mts} +0 -0
  118. /package/dist/{errors-NoQKsbAT.mjs → errors-Cg58SLNi.mjs} +0 -0
  119. /package/dist/{externalPaths-DpO-s7r8.d.mts → externalPaths-Dg7OLsKo.d.mts} +0 -0
  120. /package/dist/{fields-DFwdaWCq.d.mts → fields-CYuLMJPD.d.mts} +0 -0
  121. /package/dist/{interface-gr-7qo9j.d.mts → interface-B9rHWPxD.d.mts} +0 -0
  122. /package/dist/{interface-D_BWALyZ.d.mts → interface-CnluRL4_.d.mts} +0 -0
  123. /package/dist/{logger-Dz3j1ItV.mjs → logger-DLg8-Ueg.mjs} +0 -0
  124. /package/dist/{memory-BFAYkf8H.mjs → memory-Cp7_cAko.mjs} +0 -0
  125. /package/dist/{metrics-Csh4nsvv.mjs → metrics-Qnvwc-LQ.mjs} +0 -0
  126. /package/dist/{mongodb-BuQ7fNTg.mjs → mongodb-mlgxkYI3.mjs} +0 -0
  127. /package/dist/{pluralize-CcT6qF0a.mjs → pluralize-COpOVar8.mjs} +0 -0
  128. /package/dist/{registry-I-ogLgL9.mjs → registry-B3lRFBWo.mjs} +0 -0
  129. /package/dist/{requestContext-DYtmNpm5.mjs → requestContext-xHIKedG6.mjs} +0 -0
  130. /package/dist/{schemaConverter-DjzHpFam.mjs → schemaConverter-0TyONAwM.mjs} +0 -0
  131. /package/dist/{sessionManager-wbkYj2HL.d.mts → sessionManager-IW4sbIea.d.mts} +0 -0
  132. /package/dist/{tracing-bz_U4EM1.d.mts → tracing-65B51Dw3.d.mts} +0 -0
  133. /package/dist/{typeGuards-Cj5Rgvlg.mjs → typeGuards-CcFZXgU7.mjs} +0 -0
  134. /package/dist/{utils-Dc0WhlIl.mjs → utils-B-l6410F.mjs} +0 -0
  135. /package/dist/{versioning-BzfeHmhj.mjs → versioning-aUUVziBY.mjs} +0 -0
@@ -1,5 +1,6 @@
1
- import { t as BaseController } from "./BaseController-AbbRx3e0.mjs";
2
- import { t as pluralize } from "./pluralize-CcT6qF0a.mjs";
1
+ import { t as BaseController } from "./BaseController-CpMfCXdn.mjs";
2
+ import { n as normalizePermissionResult } from "./applyPermissionResult-D6GPMsvh.mjs";
3
+ import { t as pluralize } from "./pluralize-COpOVar8.mjs";
3
4
  import { z } from "zod";
4
5
  //#region src/integrations/mcp/createMcpServer.ts
5
6
  /**
@@ -88,7 +89,9 @@ const PAGINATION_SHAPE = {
88
89
  page: z.number().int().min(1).optional().describe("Page number (1-based)"),
89
90
  limit: z.number().int().min(1).max(100).optional().describe("Items per page (max 100)"),
90
91
  sort: z.string().optional().describe("Sort field, prefix with - for descending"),
91
- search: z.string().optional().describe("Full-text search query")
92
+ search: z.string().optional().describe("Full-text search query"),
93
+ select: z.string().optional().describe("Comma-separated field list to project (e.g. 'name,price'). Prefix with '-' to exclude (e.g. '-description')."),
94
+ populate: z.string().optional().describe("Comma-separated relation paths to hydrate (e.g. 'supplier,category'). Follows Mongoose populate syntax when the adapter is MongoKit.")
92
95
  };
93
96
  /**
94
97
  * Convert Arc fieldRules to a flat Zod shape.
@@ -179,6 +182,7 @@ function buildListShape(fieldRules, options) {
179
182
  if (allHidden.has(name)) continue;
180
183
  const rule = fieldRules[name];
181
184
  if (!rule) continue;
185
+ if (rule.hidden || rule.systemManaged) continue;
182
186
  const filterField = buildFieldSchema(rule);
183
187
  shape[name] = filterField.optional();
184
188
  if (allowedOperators?.length) {
@@ -212,9 +216,17 @@ function buildListShape(fieldRules, options) {
212
216
  * | create | {} | {} | all input fields |
213
217
  * | update | { id } | {} | input minus id |
214
218
  * | delete | { id } | {} | undefined |
219
+ *
220
+ * **scopeOverride** — when a permission check (e.g. `requireApiKey()`) returns
221
+ * `PermissionResult.scope`, the MCP tool handler must install it on the request
222
+ * context the same way CRUD/action routes do. This parameter follows the exact
223
+ * same non-downgrade rule as `applyPermissionResult`: it overrides only when
224
+ * the session-derived scope is `public` (i.e. MCP called with `auth: false`).
225
+ * An authenticated session scope is never overwritten.
215
226
  */
216
- function buildRequestContext(input, auth, operation, policyFilters) {
217
- const scope = buildScope(auth);
227
+ function buildRequestContext(input, auth, operation, policyFilters, scopeOverride) {
228
+ const sessionScope = buildScope(auth);
229
+ const scope = scopeOverride && sessionScope.kind === "public" ? scopeOverride : sessionScope;
218
230
  const base = {
219
231
  user: auth ? {
220
232
  id: auth.userId,
@@ -264,7 +276,30 @@ function buildRequestContext(input, auth, operation, policyFilters) {
264
276
  };
265
277
  }
266
278
  }
267
- /** Convert MCP operator keys (`price_gt`) to MongoKit bracket notation (`price[gt]`). */
279
+ /**
280
+ * Convert MCP operator keys (`price_gt`, `location_withinRadius`) to the
281
+ * nested object shape MongoKit's QueryParser expects (`{ price: { gt: ... } }`,
282
+ * `{ location: { withinRadius: ... } }`).
283
+ *
284
+ * **Comparison operators** (price_gt, age_lte, …): coerce filter values via
285
+ * the parser's coercion path.
286
+ *
287
+ * **Set operators** (status_in, role_nin, …): MongoKit accepts both
288
+ * comma-separated strings and arrays.
289
+ *
290
+ * **Existence** (deletedAt_exists): coerced to boolean by the parser.
291
+ *
292
+ * **Geo operators** (location_near, location_withinRadius, location_geoWithin,
293
+ * location_nearSphere): MongoKit 3.5.5+ — values are coordinate strings the
294
+ * parser's geo primitive handles. Without these in the allowlist, MCP agents
295
+ * couldn't pass geo filters at all and Arc would silently leak unfiltered docs.
296
+ *
297
+ * Keep this set in sync with MongoKit's QueryParser operators map (search for
298
+ * `private readonly operators` in QueryParser.ts) plus the geo operators
299
+ * recognized by `isGeoOperator` in primitives/geo.ts. We deliberately list
300
+ * them explicitly here rather than asking the parser at runtime — Arc must
301
+ * not import MongoKit internals just to know what an operator looks like.
302
+ */
268
303
  const OPERATOR_SUFFIXES = new Set([
269
304
  "eq",
270
305
  "ne",
@@ -274,7 +309,16 @@ const OPERATOR_SUFFIXES = new Set([
274
309
  "lte",
275
310
  "in",
276
311
  "nin",
277
- "exists"
312
+ "exists",
313
+ "size",
314
+ "type",
315
+ "like",
316
+ "contains",
317
+ "regex",
318
+ "near",
319
+ "nearSphere",
320
+ "withinRadius",
321
+ "geoWithin"
278
322
  ]);
279
323
  function expandOperatorKeys(input) {
280
324
  const out = {};
@@ -314,6 +358,146 @@ function buildScope(auth) {
314
358
  };
315
359
  }
316
360
  //#endregion
361
+ //#region src/integrations/mcp/jsonSchemaToZod.ts
362
+ /**
363
+ * @classytic/arc — JSON Schema → Zod shape converter
364
+ *
365
+ * Converts an adapter-emitted JSON Schema body shape (`createBody` / `updateBody`)
366
+ * to a flat Zod shape compatible with the MCP SDK's `registerTool({ inputSchema })`
367
+ * contract.
368
+ *
369
+ * Why this exists:
370
+ * - The MCP SDK expects a flat `Record<string, ZodType>` shape (it wraps it in
371
+ * z.object() internally).
372
+ * - When users don't supply explicit `schemaOptions.fieldRules`, MCP would
373
+ * otherwise see an empty schema and silently strip every body field — that's
374
+ * a real DX footgun.
375
+ * - Adapters (Mongoose, MongoKit's buildCrudSchemasFromModel, custom) already
376
+ * emit JSON Schema describing the body. We translate it to Zod so MCP tools
377
+ * can validate input the same way REST routes do.
378
+ *
379
+ * Supported JSON Schema features:
380
+ * - Primitives: string, number, integer, boolean, null (skipped)
381
+ * - Constraints: minLength, maxLength, minimum, maximum, pattern, enum, format
382
+ * - Arrays: typed items + nested object items
383
+ * - Nested objects with `properties` (recursive)
384
+ * - Type unions: ["string", "null"] → string (null skipped)
385
+ * - Composition: oneOf / anyOf / allOf → first viable branch
386
+ * - $ref → permissive (z.unknown()) — refs are not resolved
387
+ * - Unknown types → z.unknown() (lenient — let the controller validate)
388
+ *
389
+ * NOT supported (intentionally — keeps the surface small + deterministic):
390
+ * - Conditional schemas (if/then/else)
391
+ * - dependencies / dependentRequired
392
+ * - Custom keywords beyond standard JSON Schema
393
+ */
394
+ /**
395
+ * Convert a JSON Schema **object** body to a flat Zod shape.
396
+ * Returns `undefined` if the input has no usable properties.
397
+ *
398
+ * @param schema Top-level JSON Schema (must be `type: 'object'` with `properties`)
399
+ * @param mode 'create' enforces required fields, 'update' makes everything optional
400
+ */
401
+ function jsonSchemaToZodShape(schema, mode = "create") {
402
+ if (!schema || typeof schema !== "object") return void 0;
403
+ if (!schema.properties || typeof schema.properties !== "object") return void 0;
404
+ const requiredSet = new Set(schema.required ?? []);
405
+ const shape = {};
406
+ for (const [name, propSchema] of Object.entries(schema.properties)) {
407
+ if (!propSchema || typeof propSchema !== "object") continue;
408
+ const fieldZod = jsonSchemaPropertyToZod(propSchema);
409
+ if (!fieldZod) continue;
410
+ shape[name] = mode === "create" && requiredSet.has(name) ? fieldZod : fieldZod.optional();
411
+ }
412
+ return Object.keys(shape).length > 0 ? shape : void 0;
413
+ }
414
+ /**
415
+ * Convert one JSON Schema node to a Zod type.
416
+ * Handles primitives, arrays, nested objects, type unions, and composition.
417
+ */
418
+ function jsonSchemaPropertyToZod(prop) {
419
+ if (prop.$ref) return applyDescription(z.unknown(), prop);
420
+ if (Array.isArray(prop.oneOf) && prop.oneOf.length > 0) for (const branch of prop.oneOf) {
421
+ const z1 = jsonSchemaPropertyToZod(branch);
422
+ if (z1) return applyDescription(z1, prop);
423
+ }
424
+ if (Array.isArray(prop.anyOf) && prop.anyOf.length > 0) for (const branch of prop.anyOf) {
425
+ const z1 = jsonSchemaPropertyToZod(branch);
426
+ if (z1) return applyDescription(z1, prop);
427
+ }
428
+ if (Array.isArray(prop.allOf) && prop.allOf.length > 0) for (let i = prop.allOf.length - 1; i >= 0; i--) {
429
+ const branch = prop.allOf[i];
430
+ const z1 = jsonSchemaPropertyToZod(branch);
431
+ if (z1) return applyDescription(z1, prop);
432
+ }
433
+ if (Array.isArray(prop.enum) && prop.enum.length > 0) {
434
+ const stringValues = prop.enum.filter((v) => typeof v === "string");
435
+ if (stringValues.length > 0) return applyDescription(z.enum(stringValues), prop);
436
+ return applyDescription(z.number(), prop);
437
+ }
438
+ const typeCandidates = pickEffectiveType(prop.type);
439
+ for (const t of typeCandidates) switch (t) {
440
+ case "string": return applyStringConstraints(z.string(), prop);
441
+ case "number":
442
+ case "integer": return applyNumberConstraints(z.number(), prop);
443
+ case "boolean": return applyDescription(z.boolean(), prop);
444
+ case "array": return applyDescription(arrayToZod(prop), prop);
445
+ case "object": return applyDescription(objectToZod(prop), prop);
446
+ case "null": continue;
447
+ default: break;
448
+ }
449
+ return applyDescription(z.unknown(), prop);
450
+ }
451
+ function pickEffectiveType(rawType) {
452
+ if (!rawType) return [];
453
+ if (Array.isArray(rawType)) return rawType.filter((t) => t !== "null");
454
+ return rawType === "null" ? [] : [rawType];
455
+ }
456
+ function arrayToZod(prop) {
457
+ const items = prop.items;
458
+ if (items && typeof items === "object") {
459
+ const itemZod = jsonSchemaPropertyToZod(items);
460
+ if (itemZod) return z.array(itemZod);
461
+ }
462
+ return z.array(z.unknown());
463
+ }
464
+ function objectToZod(prop) {
465
+ if (prop.properties && typeof prop.properties === "object") {
466
+ const requiredSet = new Set(prop.required ?? []);
467
+ const innerShape = {};
468
+ for (const [k, v] of Object.entries(prop.properties)) {
469
+ if (!v || typeof v !== "object") continue;
470
+ const inner = jsonSchemaPropertyToZod(v);
471
+ if (!inner) continue;
472
+ innerShape[k] = requiredSet.has(k) ? inner : inner.optional();
473
+ }
474
+ if (Object.keys(innerShape).length > 0) return z.object(innerShape);
475
+ }
476
+ return z.record(z.string(), z.unknown());
477
+ }
478
+ function applyStringConstraints(base, prop) {
479
+ let s = base;
480
+ if (typeof prop.minLength === "number") s = s.min(prop.minLength);
481
+ if (typeof prop.maxLength === "number") s = s.max(prop.maxLength);
482
+ if (typeof prop.pattern === "string") try {
483
+ s = s.regex(new RegExp(prop.pattern));
484
+ } catch {}
485
+ if (prop.format === "email") s = s.email();
486
+ if (prop.format === "uuid") s = s.uuid();
487
+ if (prop.format === "uri" || prop.format === "url") s = s.url();
488
+ return applyDescription(s, prop);
489
+ }
490
+ function applyNumberConstraints(base, prop) {
491
+ let n = base;
492
+ if (typeof prop.minimum === "number") n = n.min(prop.minimum);
493
+ if (typeof prop.maximum === "number") n = n.max(prop.maximum);
494
+ return applyDescription(n, prop);
495
+ }
496
+ function applyDescription(zodType, prop) {
497
+ if (typeof prop.description === "string" && prop.description.length > 0) return zodType.describe(prop.description);
498
+ return zodType;
499
+ }
500
+ //#endregion
317
501
  //#region src/integrations/mcp/resourceToTools.ts
318
502
  /**
319
503
  * @classytic/arc — Resource → MCP Tools Generator
@@ -359,9 +543,11 @@ const ANNOTATIONS = {
359
543
  function resourceToTools(resource, config = {}) {
360
544
  const controller = resource.controller ?? (resource.adapter ? createMcpController(resource) : void 0);
361
545
  if (!controller) return [];
362
- const fieldRules = resource.schemaOptions?.fieldRules;
546
+ const explicitFieldRules = resource.schemaOptions?.fieldRules;
363
547
  const hiddenFields = resource.schemaOptions?.hiddenFields;
364
548
  const readonlyFields = resource.schemaOptions?.readonlyFields;
549
+ const adapterBodies = explicitFieldRules ? void 0 : getAdapterBodies(resource);
550
+ const fieldRules = explicitFieldRules ?? deriveFieldRulesFromAdapter(resource);
365
551
  const filterableFields = resource.schemaOptions?.filterableFields ?? resource.queryParser?.allowedFilterFields;
366
552
  const sortableFields = resource.queryParser?.allowedSortFields;
367
553
  const allowedOperators = resource.queryParser?.allowedOperators;
@@ -388,7 +574,8 @@ function resourceToTools(resource, config = {}) {
388
574
  readonlyFields,
389
575
  extraHideFields: config.hideFields,
390
576
  filterableFields,
391
- allowedOperators
577
+ allowedOperators,
578
+ adapterBodies
392
579
  }),
393
580
  handler: createHandler(op, controller, resource.name, resource.permissions)
394
581
  });
@@ -442,20 +629,57 @@ function buildInputSchema(op, fieldRules, opts) {
442
629
  ...opts
443
630
  });
444
631
  case "get": return { id: z.string().describe("Resource ID") };
445
- case "create": return fieldRulesToZod(fieldRules, {
446
- mode: "create",
447
- ...opts
448
- });
449
- case "update": return {
450
- id: z.string().describe("Resource ID"),
451
- ...fieldRulesToZod(fieldRules, {
452
- mode: "update",
632
+ case "create":
633
+ if (!fieldRules && opts.adapterBodies?.createBody) {
634
+ const shape = jsonSchemaToZodShape(opts.adapterBodies.createBody, "create");
635
+ if (shape) return shape;
636
+ }
637
+ return fieldRulesToZod(fieldRules, {
638
+ mode: "create",
453
639
  ...opts
454
- })
455
- };
640
+ });
641
+ case "update": {
642
+ const idShape = { id: z.string().describe("Resource ID") };
643
+ if (!fieldRules && opts.adapterBodies?.updateBody) {
644
+ const shape = jsonSchemaToZodShape(opts.adapterBodies.updateBody, "update");
645
+ if (shape) return {
646
+ ...idShape,
647
+ ...shape
648
+ };
649
+ }
650
+ return {
651
+ ...idShape,
652
+ ...fieldRulesToZod(fieldRules, {
653
+ mode: "update",
654
+ ...opts
655
+ })
656
+ };
657
+ }
456
658
  case "delete": return { id: z.string().describe("Resource ID") };
457
659
  }
458
660
  }
661
+ /**
662
+ * Pull the adapter's `createBody` / `updateBody` schemas, if any.
663
+ * Returns `undefined` when the adapter doesn't generate schemas or throws.
664
+ */
665
+ function getAdapterBodies(resource) {
666
+ const adapter = resource.adapter;
667
+ if (!adapter || typeof adapter.generateSchemas !== "function") return void 0;
668
+ try {
669
+ const generated = adapter.generateSchemas(resource.schemaOptions, {
670
+ idField: resource.idField,
671
+ resourceName: resource.name
672
+ });
673
+ if (!generated || typeof generated !== "object") return void 0;
674
+ const schemas = generated;
675
+ return {
676
+ createBody: schemas.createBody,
677
+ updateBody: schemas.updateBody
678
+ };
679
+ } catch {
680
+ return;
681
+ }
682
+ }
459
683
  function createHandler(op, controller, resourceName, permissions) {
460
684
  const ctrl = controller;
461
685
  return async (input, ctx) => {
@@ -468,15 +692,15 @@ function createHandler(op, controller, resourceName, permissions) {
468
692
  }],
469
693
  isError: true
470
694
  };
471
- const policyFilters = await evaluatePermission(permissions?.[op], ctx.session, resourceName, op, input);
472
- if (policyFilters === false) return {
695
+ const permResult = await evaluatePermission(permissions?.[op], ctx.session, resourceName, op, input);
696
+ if (permResult && !permResult.granted) return {
473
697
  content: [{
474
698
  type: "text",
475
- text: `Permission denied: ${op} on ${resourceName}`
699
+ text: `Permission denied: ${op} on ${resourceName}${permResult.reason ? ` — ${permResult.reason}` : ""}`
476
700
  }],
477
701
  isError: true
478
702
  };
479
- return toCallToolResult(await method(buildRequestContext(input, ctx.session, op, policyFilters || void 0)));
703
+ return toCallToolResult(await method(buildRequestContext(input, ctx.session, op, permResult?.filters, permResult?.scope)));
480
704
  } catch (err) {
481
705
  const msg = err instanceof Error ? err.message : String(err);
482
706
  ctx.log("error", `${resourceName}.${op}: ${msg}`).catch(() => {});
@@ -518,10 +742,13 @@ function createAdditionalRouteHandler(route, controller, hasId) {
518
742
  /**
519
743
  * Evaluate a resource's permission check in MCP context.
520
744
  *
521
- * Returns:
522
- * - `false` if permission denied
523
- * - `Record<string, unknown>` if granted with filters (ownership patterns)
524
- * - `null` if granted without filters (or no permission check defined)
745
+ * Returns the full normalized `PermissionResult` so the caller can honor
746
+ * ALL side-effects (filters + scope) consistently with CRUD/action routes.
747
+ * Returns `null` when no permission is defined (= allow, no side effects).
748
+ *
749
+ * Promoting booleans to `PermissionResult` via the shared `normalizePermissionResult`
750
+ * helper keeps the contract aligned with the rest of Arc — there is a single
751
+ * normalization path for every call site.
525
752
  */
526
753
  async function evaluatePermission(check, session, resource, action, input) {
527
754
  if (!check) return null;
@@ -530,7 +757,7 @@ async function evaluatePermission(check, session, resource, action, input) {
530
757
  _id: session.userId,
531
758
  ...session
532
759
  } : null;
533
- const result = await check({
760
+ return normalizePermissionResult(await check({
534
761
  user,
535
762
  request: {
536
763
  user,
@@ -544,11 +771,64 @@ async function evaluatePermission(check, session, resource, action, input) {
544
771
  resourceId: typeof input.id === "string" ? input.id : void 0,
545
772
  params: {},
546
773
  data: input
547
- });
548
- if (typeof result === "boolean") return result ? null : false;
549
- const permResult = result;
550
- if (!permResult.granted) return false;
551
- return permResult.filters ?? null;
774
+ }));
775
+ }
776
+ /**
777
+ * Derive a fieldRules-shaped object from the adapter's auto-generated body
778
+ * schemas. Used as a fallback when the resource doesn't supply explicit
779
+ * fieldRules — this lets MCP create/update tools accept the same body fields
780
+ * that the REST routes already accept.
781
+ *
782
+ * Returns `undefined` if no usable schema can be extracted, in which case
783
+ * `fieldRulesToZod` falls back to its own behavior (empty shape).
784
+ */
785
+ function deriveFieldRulesFromAdapter(resource) {
786
+ const adapter = resource.adapter;
787
+ if (!adapter || typeof adapter.generateSchemas !== "function") return void 0;
788
+ let generated;
789
+ try {
790
+ generated = adapter.generateSchemas(resource.schemaOptions, {
791
+ idField: resource.idField,
792
+ resourceName: resource.name
793
+ });
794
+ } catch {
795
+ return;
796
+ }
797
+ if (!generated || typeof generated !== "object") return void 0;
798
+ const schemas = generated;
799
+ const createBody = schemas.createBody;
800
+ const updateBody = schemas.updateBody;
801
+ const properties = createBody?.properties ?? updateBody?.properties;
802
+ if (!properties || typeof properties !== "object") return void 0;
803
+ const requiredSet = new Set(createBody?.required ?? []);
804
+ const rules = {};
805
+ for (const [name, propSchema] of Object.entries(properties)) {
806
+ if (!propSchema || typeof propSchema !== "object") continue;
807
+ const prop = propSchema;
808
+ const rawType = prop.type;
809
+ const rule = { type: mapJsonSchemaTypeToArcType((Array.isArray(rawType) ? rawType.filter((t) => typeof t === "string") : typeof rawType === "string" ? [rawType] : [])[0]) };
810
+ if (requiredSet.has(name)) rule.required = true;
811
+ if (typeof prop.description === "string") rule.description = prop.description;
812
+ if (Array.isArray(prop.enum)) rule.enum = prop.enum.filter((v) => typeof v === "string");
813
+ if (typeof prop.minLength === "number") rule.minLength = prop.minLength;
814
+ if (typeof prop.maxLength === "number") rule.maxLength = prop.maxLength;
815
+ if (typeof prop.minimum === "number") rule.min = prop.minimum;
816
+ if (typeof prop.maximum === "number") rule.max = prop.maximum;
817
+ if (typeof prop.pattern === "string") rule.pattern = prop.pattern;
818
+ rules[name] = rule;
819
+ }
820
+ return Object.keys(rules).length > 0 ? rules : void 0;
821
+ }
822
+ function mapJsonSchemaTypeToArcType(jsonType) {
823
+ switch (jsonType) {
824
+ case "string": return "string";
825
+ case "number":
826
+ case "integer": return "number";
827
+ case "boolean": return "boolean";
828
+ case "array": return "array";
829
+ case "object": return "object";
830
+ default: return "string";
831
+ }
552
832
  }
553
833
  function toCallToolResult(result) {
554
834
  if (!result.success) return {
@@ -1,4 +1,4 @@
1
- import { r as CircuitBreakerOptions } from "../circuitBreaker-JP2GdJ4b.mjs";
1
+ import { r as CircuitBreakerOptions } from "../circuitBreaker-DwxrljLB.mjs";
2
2
 
3
3
  //#region src/rpc/serviceClient.d.ts
4
4
  interface RetryConfig {
@@ -1,4 +1,4 @@
1
- import { t as CircuitBreaker } from "../circuitBreaker-BOBOpN2w.mjs";
1
+ import { t as CircuitBreaker } from "../circuitBreaker-l18oRgL5.mjs";
2
2
  //#region src/rpc/serviceClient.ts
3
3
  /**
4
4
  * Service Client — Resource-Oriented RPC
@@ -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-CNEbix8T.mjs";
2
+ import { i as elevationPlugin, n as ElevationOptions, r as _default, t as ElevationEvent } from "../elevation-Dm-HTBCt.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 { Bt as ResourceDefinition, Ht as CrudRepository, l as AnyRecord } from "../interface-CrN45qz1.mjs";
2
- import { d as ResourceLike, r as CreateAppOptions } from "../types-C1Z28coa.mjs";
1
+ import { Ut as CrudRepository, Vt as ResourceDefinition, u as AnyRecord } from "../interface-Dwzqt4mn.mjs";
2
+ import { d as ResourceLike, r as CreateAppOptions } from "../types-D0qf0Mf4.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-B_nvKNAQ.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 RegistryEntry, A as GracefulShutdownOptions, B as LookupOption, C as CrudSchemas, D as FastifyWithAuth, E as FastifyRequestExtras, F as InferResourceDoc, Ft as IControllerResponse, G as OwnershipCheck, Gt as PaginationParams, H as MiddlewareHandler, Ht as CrudRepository, I as IntrospectionData, It as IRequestContext, J as PresetFunction, K as ParsedQuery, Kt as QueryOptions, L as IntrospectionPluginOptions, Lt as RouteHandler, M as HealthOptions, Mt as ControllerLike, N as InferAdapterDoc, Nt as FastifyHandler, O as FastifyWithDecorators, P as InferDocType, Pt as IController, Q as RateLimitConfig, R as JWTPayload, S as CrudRouterOptions, St as getUserId, T as EventsDecorator, U as ObjectId, Ut as InferDoc, V as MiddlewareConfig, W as OpenApiSchemas, Wt as PaginatedResult, X as PresetResult, Y as PresetHook, Z as QueryParserInterface, _ as AuthenticatorContext, _t as UserLike, at as ResourceConfig, b as CrudController, bt as ValidationResult, c as AdditionalRoute, ct as ResourceMetadata, d as ArcDecorator, dt as RouteSchemaOptions, et as RegistryStats, f as ArcInternalMetadata, ft as ServiceContext, g as Authenticator, gt as TypedResourceConfig, h as AuthPluginOptions, ht as TypedRepository, it as ResourceCacheConfig, j as HealthCheck, jt as ControllerHandler, k as FieldRule, l as AnyRecord, lt as ResourcePermissions, m as AuthHelpers, mt as TypedController, nt as RequestIdOptions, ot as ResourceHookContext, p as ArcRequest, pt as TokenPair, q as PopulateOption, rt as RequestWithExtras, st as ResourceHooks, tt as RequestContext, u as ApiResponse, ut as RouteHandlerMethod, v as ConfigError, vt as UserOrganization, w as EventDefinition, wt as BaseControllerOptions, x as CrudRouteKey, xt as envelope, y as ControllerQueryOptions, yt as ValidateOptions, z as JwtContext } from "../interface-CrN45qz1.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-CNEbix8T.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-Dwzqt4mn.mjs";
3
+ import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "../types-DPsC0taJ.mjs";
4
+ import { n as ElevationOptions, t as ElevationEvent } from "../elevation-Dm-HTBCt.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.