@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,13 +1,14 @@
1
1
  import { p as isArcError, t as ArcError } from "./errors-DkO8Nk6-.mjs";
2
- import { c as getOrgId, g as getUserId } from "./types-bHblZ9YN.mjs";
3
- import { t as BaseController } from "./BaseController-BnLYgE9A.mjs";
4
- import { P as normalizePermissionResult } from "./permissions-BJMuKMl7.mjs";
2
+ import { b as isElevated, c as getOrgId, g as getUserId, x as isMember } from "./types-bHblZ9YN.mjs";
3
+ import { t as BaseController } from "./BaseController-BQ8KNvWC.mjs";
4
+ import { i as applyFieldReadPermissions, r as normalizePermissionResult, s as resolveEffectiveRoles } from "./applyPermissionResult-Tw4iXtlf.mjs";
5
5
  import { t as executePipeline } from "./pipe-BOLmGIxa.mjs";
6
- import { i as resolvePipelineSteps, t as resolveActionPermission } from "./actionPermissions-ze70xXJi.mjs";
6
+ import { d as buildRequestScopeProjection, i as resolvePipelineSteps, t as resolveActionPermission } from "./actionPermissions-lszoJle1.mjs";
7
7
  import { n as validateAggregations } from "./validate-C2mGgSXg.mjs";
8
8
  import { n as executeAggregation } from "./buildHandler-D_2ULWxZ.mjs";
9
9
  import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
10
- import { r as shouldRejectAdditionalProperties, t as normalizeSchemaIR } from "./schemaIR-ajetw3Fv.mjs";
10
+ import { t as createIdempotencyResult } from "./interface-n5hpKg1d.mjs";
11
+ import { r as shouldRejectAdditionalProperties, t as normalizeSchemaIR } from "./schemaIR-Ca7ySNPx.mjs";
11
12
  import { createHash, randomUUID } from "node:crypto";
12
13
  import { isHttpError, toErrorContract } from "@classytic/repo-core/errors";
13
14
  import fp from "fastify-plugin";
@@ -160,6 +161,13 @@ function registerPrompt(server, prompt) {
160
161
  //#endregion
161
162
  //#region src/integrations/mcp/buildRequestContext.ts
162
163
  /**
164
+ * @classytic/arc — MCP → IRequestContext Bridge
165
+ *
166
+ * Builds an IRequestContext from MCP tool input + session identity.
167
+ * Ensures MCP tool handlers go through the same BaseController pipeline
168
+ * as REST requests (AccessControl, BodySanitizer, QueryResolver, HookSystem).
169
+ */
170
+ /**
163
171
  * Build an IRequestContext from MCP tool input and session auth.
164
172
  *
165
173
  * | Operation | params | query | body |
@@ -177,7 +185,7 @@ function registerPrompt(server, prompt) {
177
185
  * the session-derived scope is `public` (i.e. MCP called with `auth: false`).
178
186
  * An authenticated session scope is never overwritten.
179
187
  */
180
- function buildRequestContext(input, auth, operation, policyFilters, scopeOverride) {
188
+ function buildRequestContext(input, auth, operation, policyFilters, scopeOverride, extras) {
181
189
  const sessionScope = buildScope(auth);
182
190
  const scope = scopeOverride && sessionScope.kind === "public" ? scopeOverride : sessionScope;
183
191
  const base = {
@@ -188,10 +196,13 @@ function buildRequestContext(input, auth, operation, policyFilters, scopeOverrid
188
196
  } : null,
189
197
  headers: {},
190
198
  context: {},
199
+ scope: buildRequestScopeProjection(scope),
191
200
  metadata: {
192
201
  _scope: scope,
193
- _policyFilters: policyFilters ?? {}
194
- }
202
+ _policyFilters: policyFilters ?? {},
203
+ ...extras?.arc ? { arc: extras.arc } : {}
204
+ },
205
+ ...extras?.server ? { server: extras.server } : {}
195
206
  };
196
207
  switch (operation) {
197
208
  case "list": return {
@@ -375,6 +386,42 @@ async function evaluatePermission(check, session, resource, action, input) {
375
386
  }));
376
387
  }
377
388
  /**
389
+ * Apply field-level READ permissions to an MCP tool payload — the same
390
+ * masking `sendControllerResponse` applies on the HTTP wire and the
391
+ * realtime plugin applies per frame. Without this, a resource declaring
392
+ * `fields: { salary: fields.visibleTo(['admin']) }` masked salary over
393
+ * REST and SSE but leaked it verbatim through every MCP tool.
394
+ *
395
+ * Mirrors the HTTP adapter's semantics exactly:
396
+ * - Elevated scope (platform admin) bypasses masking — consistent with
397
+ * `requireOrgRole()` and `BodySanitizer` bypass logic.
398
+ * - Effective roles = session roles ∪ org roles (member scope only),
399
+ * via the shared `resolveEffectiveRoles`.
400
+ * - `scopeOverride` (a `PermissionResult.scope`) follows the same
401
+ * non-downgrade rule as `buildRequestContext`: honored only when the
402
+ * session-derived scope is `public`.
403
+ *
404
+ * Handles the three payload shapes MCP tools emit: a single record, an
405
+ * array of records, and a paginated result object carrying an inner
406
+ * `data: T[]`. Scalars and `null` pass through untouched.
407
+ */
408
+ function applyMcpReadMasking(data, options) {
409
+ const { fields, session, scopeOverride } = options;
410
+ if (!fields || data === null || typeof data !== "object") return data;
411
+ const sessionScope = buildScope(session);
412
+ const scope = scopeOverride && sessionScope.kind === "public" ? scopeOverride : sessionScope;
413
+ if (isElevated(scope)) return data;
414
+ const roles = resolveEffectiveRoles(session?.roles ?? [], isMember(scope) ? scope.orgRoles : []);
415
+ const maskItem = (item) => item !== null && typeof item === "object" && !Array.isArray(item) ? applyFieldReadPermissions(item, fields, roles) : item;
416
+ if (Array.isArray(data)) return data.map(maskItem);
417
+ const inner = data.data;
418
+ if (Array.isArray(inner)) return {
419
+ ...data,
420
+ data: inner.map(maskItem)
421
+ };
422
+ return maskItem(data);
423
+ }
424
+ /**
378
425
  * Convert a controller response envelope into an MCP `CallToolResult`.
379
426
  * Carries `meta` into the serialized payload so consumers see pagination
380
427
  * totals, stripped-field arrays, etc.
@@ -476,6 +523,78 @@ function createMcpController(resource) {
476
523
  //#endregion
477
524
  //#region src/integrations/mcp/invokeController.ts
478
525
  /**
526
+ * @classytic/arc — Non-HTTP controller invocation for MCP / jobs / workflows.
527
+ *
528
+ * Internal callers (MCP tools, scheduled jobs, workflow steps) need to invoke
529
+ * controller methods without going through Fastify's preHandler chain.
530
+ * Before this module landed, every call site reinvented the same shim:
531
+ * fabricate `params` / `body` / `headers`, project the session into a
532
+ * `RequestScope`, run the permission check by hand, translate thrown errors
533
+ * to the MCP `CallToolResult` shape. The drift across those copies is what
534
+ * the mentora review flagged as the "buildCtx synthetic-context hack."
535
+ *
536
+ * Two public surfaces, layered so callers reach for the smallest piece that
537
+ * does the job:
538
+ *
539
+ * - {@link invokeController} full pipeline: permission → context →
540
+ * dispatch → canonical envelope/error
541
+ * conversion. Returns `CallToolResult`.
542
+ * - {@link mcpHandlerAdapter} thin try/catch wrapper that turns any
543
+ * async function into a `ToolDefinition`
544
+ * handler with canonical error shape. Use
545
+ * when you want to compose multiple
546
+ * controller calls or weave in custom logic
547
+ * between them.
548
+ *
549
+ * Both honor the same {@link buildRequestContext} primitive — re-exported
550
+ * from this module so authors who want the synthetic context as data (e.g.
551
+ * to pass into `executePipeline`) can grab it without depending on an
552
+ * internal subpath.
553
+ */
554
+ /**
555
+ * Assemble the {@link McpContextExtras} for a controller invocation from
556
+ * resource-scoped metadata + app-level wiring. Mirrors what
557
+ * `buildArcDecorator` (metadata.arc) and `createRequestContext` (server
558
+ * accessor) assemble on the HTTP path.
559
+ */
560
+ function buildContextExtras(options) {
561
+ const { wiring, resourceName, permissions, fields, schemaOptions, idField } = options;
562
+ if (!wiring) return void 0;
563
+ return {
564
+ arc: {
565
+ resourceName,
566
+ schemaOptions,
567
+ permissions,
568
+ hooks: wiring.hooks,
569
+ events: wiring.events,
570
+ fields,
571
+ idField
572
+ },
573
+ server: {
574
+ events: wiring.events,
575
+ audit: wiring.audit,
576
+ log: wiring.log
577
+ }
578
+ };
579
+ }
580
+ /**
581
+ * Stable fingerprint of a tool invocation — sorted-key JSON, hashed.
582
+ * Scopes an idempotency key to (resource, action, input, caller) so a
583
+ * reused key with DIFFERENT input is a fresh execution, matching the HTTP
584
+ * plugin's method+url+bodyHash+user fingerprint semantics.
585
+ */
586
+ function invocationFingerprint(resourceName, actionName, input, session) {
587
+ const sortKeys = (value) => {
588
+ if (Array.isArray(value)) return value.map(sortKeys);
589
+ if (value !== null && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().map((k) => [k, sortKeys(value[k])]));
590
+ return value;
591
+ };
592
+ return `mcp:${resourceName}:${actionName}:${createHash("sha256").update(JSON.stringify(sortKeys(input))).digest("hex").substring(0, 16)}:u=${session?.userId ?? session?.clientId ?? "anon"}`;
593
+ }
594
+ /** TTLs matching the HTTP idempotency plugin's defaults. */
595
+ const MCP_IDEMPOTENCY_TTL_MS = 1440 * 60 * 1e3;
596
+ const MCP_IDEMPOTENCY_LOCK_MS = 1e4;
597
+ /**
479
598
  * Invoke a controller method through the MCP synthetic-context path.
480
599
  *
481
600
  * Runs the same chain CRUD MCP tools run:
@@ -508,7 +627,7 @@ function createMcpController(resource) {
508
627
  * checks compose.
509
628
  */
510
629
  async function invokeController(controller, op, input, options) {
511
- const { session, resourceName, actionName = op, permissions, methodName = op } = options;
630
+ const { session, resourceName, actionName = op, permissions, methodName = op, fields, wiring, idempotencyKey } = options;
512
631
  const ctrl = controller;
513
632
  try {
514
633
  const method = ctrl[methodName];
@@ -524,7 +643,39 @@ async function invokeController(controller, op, input, options) {
524
643
  reason: permResult.reason,
525
644
  session
526
645
  });
527
- return toCallToolResult(await method(buildRequestContext(input, session, op, permResult?.filters, permResult?.scope)));
646
+ const dispatch = async () => {
647
+ const reqCtx = buildRequestContext(input, session, op, permResult?.filters, permResult?.scope, buildContextExtras(options));
648
+ const response = await method(reqCtx);
649
+ const data = applyMcpReadMasking(response.data, {
650
+ fields,
651
+ session,
652
+ scopeOverride: permResult?.scope
653
+ });
654
+ return toCallToolResult(data === response.data ? response : {
655
+ ...response,
656
+ data
657
+ });
658
+ };
659
+ const store = wiring?.idempotencyStore;
660
+ if (idempotencyKey && store) {
661
+ const fullKey = `${idempotencyKey}:${invocationFingerprint(resourceName, actionName, input, session)}`;
662
+ const cached = await store.get(fullKey);
663
+ if (cached) return cached.body;
664
+ const lockId = randomUUID();
665
+ if (!await store.tryLock(fullKey, lockId, MCP_IDEMPOTENCY_LOCK_MS)) return toCallToolError({
666
+ code: "arc.idempotency_conflict",
667
+ message: "A call with this idempotency key is already in progress",
668
+ status: 409
669
+ });
670
+ try {
671
+ const result = await dispatch();
672
+ if (!result.isError) await store.set(fullKey, createIdempotencyResult(200, result, {}, MCP_IDEMPOTENCY_TTL_MS));
673
+ return result;
674
+ } finally {
675
+ await store.unlock(fullKey, lockId);
676
+ }
677
+ }
678
+ return await dispatch();
528
679
  } catch (err) {
529
680
  return toCallToolError(err instanceof Error ? err : new Error(String(err)));
530
681
  }
@@ -605,13 +756,33 @@ const CRUD_ANNOTATIONS = {
605
756
  * build + envelope/error conversion all live in one place — this factory
606
757
  * only resolves the op-specific permission and threads it through.
607
758
  */
608
- function createCrudHandler(op, controller, resourceName, permissions) {
759
+ /** Ops where an idempotency key is meaningful (mutations). */
760
+ const MUTATING_CRUD_OPS = /* @__PURE__ */ new Set([
761
+ "create",
762
+ "update",
763
+ "delete"
764
+ ]);
765
+ function createCrudHandler(op, controller, resourceName, permissions, fields, extras) {
609
766
  const permission = permissions?.[op];
610
- return (input, ctx) => invokeController(controller, op, input, {
611
- session: ctx.session,
612
- resourceName,
613
- permissions: permission
614
- });
767
+ return (input, ctx) => {
768
+ let idempotencyKey;
769
+ let payload = input;
770
+ if ("_idempotencyKey" in input) {
771
+ const { _idempotencyKey, ...rest } = input;
772
+ payload = rest;
773
+ if (MUTATING_CRUD_OPS.has(op) && typeof _idempotencyKey === "string" && _idempotencyKey) idempotencyKey = _idempotencyKey;
774
+ }
775
+ return invokeController(controller, op, payload, {
776
+ session: ctx.session,
777
+ resourceName,
778
+ permissions: permission,
779
+ fields,
780
+ wiring: extras?.wiring,
781
+ schemaOptions: extras?.schemaOptions,
782
+ idField: extras?.idField,
783
+ idempotencyKey
784
+ });
785
+ };
615
786
  }
616
787
  /**
617
788
  * Default description for a CRUD tool. Enriches list descriptions with the
@@ -630,6 +801,7 @@ function defaultCrudDescription(op, displayName, softDelete, queryMeta) {
630
801
  if (queryMeta?.filterableFields?.length) parts.push(`Filterable fields: ${queryMeta.filterableFields.join(", ")}.`);
631
802
  if (queryMeta?.allowedOperators?.length) parts.push(`Filter operators: ${queryMeta.allowedOperators.join(", ")} (use field[op]=value syntax).`);
632
803
  if (queryMeta?.sortableFields?.length) parts.push(`Sortable fields: ${queryMeta.sortableFields.join(", ")}.`);
804
+ parts.push("Set _count: true for a count-only result, _exists: true for a boolean existence check, or _distinct: '<field>' for distinct values — all honor the same filters.");
633
805
  return parts.join(" ");
634
806
  }
635
807
  case "get": return `Get a single ${singular} by ID`;
@@ -772,6 +944,9 @@ function buildListShape(fieldRules, options) {
772
944
  const { filterableFields = [], hiddenFields = [], extraHideFields = [], allowedOperators } = options;
773
945
  const allHidden = /* @__PURE__ */ new Set([...hiddenFields, ...extraHideFields]);
774
946
  const shape = { ...PAGINATION_SHAPE };
947
+ shape._count = z.boolean().optional().describe("Return only { count } of records matching the filters — no documents fetched. Cheapest way to answer 'how many'.");
948
+ shape._exists = z.boolean().optional().describe("Return only whether ANY record matches the filters (boolean existence check).");
949
+ shape._distinct = z.string().optional().describe("Return the distinct values of this field across records matching the filters.");
775
950
  if (!fieldRules) return shape;
776
951
  for (const name of filterableFields) {
777
952
  if (allHidden.has(name)) continue;
@@ -1004,7 +1179,24 @@ function convertActionSchemaToZod(raw) {
1004
1179
  * in the 2.10.8 review: REST and MCP action tools share identical
1005
1180
  * context-building machinery.
1006
1181
  */
1007
- function createActionToolHandler(actionName, handler, permissions, resourceName, _resourcePermissions, rawSchema, idLess = false) {
1182
+ function createActionToolHandler(actionName, handler, permissions, resourceName, _resourcePermissions, rawSchema, idLess = false, fields, extras) {
1183
+ const wiring = extras?.wiring;
1184
+ const contextExtras = wiring ? {
1185
+ arc: {
1186
+ resourceName,
1187
+ schemaOptions: extras?.schemaOptions,
1188
+ permissions,
1189
+ hooks: wiring.hooks,
1190
+ events: wiring.events,
1191
+ fields,
1192
+ idField: extras?.idField
1193
+ },
1194
+ server: {
1195
+ events: wiring.events,
1196
+ audit: wiring.audit,
1197
+ log: wiring.log
1198
+ }
1199
+ } : void 0;
1008
1200
  const ir = rawSchema ? normalizeSchemaIR(rawSchema) : void 0;
1009
1201
  const allowedKeys = (ir ? shouldRejectAdditionalProperties(ir) : false) && ir ? /* @__PURE__ */ new Set([...idLess ? [] : ["id"], ...Object.keys(ir.properties)]) : void 0;
1010
1202
  return async (input, ctx) => {
@@ -1032,11 +1224,15 @@ function createActionToolHandler(actionName, handler, permissions, resourceName,
1032
1224
  const reqCtx = buildRequestContext({
1033
1225
  ...input,
1034
1226
  action: actionName
1035
- }, session, "action", permResult?.filters, permResult?.scope);
1227
+ }, session, "action", permResult?.filters, permResult?.scope, contextExtras);
1036
1228
  const id = idLess ? "" : typeof input.id === "string" ? input.id : "";
1037
1229
  const { id: _discardId, ...data } = input;
1038
1230
  try {
1039
- return toCallToolSuccess(await handler(id, data, reqCtx));
1231
+ return toCallToolSuccess(applyMcpReadMasking(await handler(id, data, reqCtx), {
1232
+ fields,
1233
+ session,
1234
+ scopeOverride: permResult?.scope
1235
+ }));
1040
1236
  } catch (err) {
1041
1237
  return toCallToolError(err instanceof Error ? err : new Error(String(err)));
1042
1238
  }
@@ -1051,7 +1247,7 @@ function createActionToolHandler(actionName, handler, permissions, resourceName,
1051
1247
  * every aggregation opts out via `mcp: false`.
1052
1248
  */
1053
1249
  function buildAggregationTools(args) {
1054
- const { resourceName, displayName, aggregations, schemaOptions, repo, buildOptionsFromSession, prefix } = args;
1250
+ const { resourceName, displayName, aggregations, schemaOptions, repo, buildOptionsFromSession, prefix, fields } = args;
1055
1251
  if (!aggregations || Object.keys(aggregations).length === 0) return [];
1056
1252
  const normalized = validateAggregations(resourceName, aggregations, schemaOptions);
1057
1253
  const tools = [];
@@ -1075,7 +1271,8 @@ function buildAggregationTools(args) {
1075
1271
  permissions: config.permissions,
1076
1272
  resourceName,
1077
1273
  repo,
1078
- buildOptionsFromSession
1274
+ buildOptionsFromSession,
1275
+ fields
1079
1276
  })
1080
1277
  });
1081
1278
  }
@@ -1117,7 +1314,7 @@ function buildAggregationInputSchema(norm) {
1117
1314
  return shape;
1118
1315
  }
1119
1316
  function createAggregationToolHandler(args) {
1120
- const { normalized, permissions, resourceName, repo, buildOptionsFromSession } = args;
1317
+ const { normalized, permissions, resourceName, repo, buildOptionsFromSession, fields } = args;
1121
1318
  return async (input, ctx) => {
1122
1319
  const permResult = await evaluatePermission(permissions, ctx.session, resourceName, `aggregation:${normalized.name}`, input);
1123
1320
  if (permResult && !permResult.granted) return permissionDeniedResult({
@@ -1136,7 +1333,21 @@ function createAggregationToolHandler(args) {
1136
1333
  query: filterInput,
1137
1334
  tenantOptions
1138
1335
  });
1139
- if (result.status === 200) return toCallToolSuccess(result.body);
1336
+ if (result.status === 200) {
1337
+ const body = result.body;
1338
+ if (fields && Array.isArray(body?.rows)) {
1339
+ const rows = applyMcpReadMasking(body.rows, {
1340
+ fields,
1341
+ session: ctx.session,
1342
+ scopeOverride: permResult?.scope
1343
+ });
1344
+ return toCallToolSuccess({
1345
+ ...body,
1346
+ rows
1347
+ });
1348
+ }
1349
+ return toCallToolSuccess(result.body);
1350
+ }
1140
1351
  return toCallToolError(result.body);
1141
1352
  };
1142
1353
  }
@@ -1476,8 +1687,24 @@ function operationKindForRoute(method, hasId) {
1476
1687
  function createCustomRouteHandler(route, controller, hasId, options) {
1477
1688
  const ctrl = controller;
1478
1689
  const handlerName = typeof route.handler === "string" ? route.handler : route.operation ?? slugifyRoute(route.method, route.path);
1479
- const { resourceName, operationName, permissions, pipeline } = options;
1690
+ const { resourceName, operationName, permissions, pipeline, fields, wiring } = options;
1480
1691
  const pipelineSteps = resolvePipelineSteps(pipeline, operationName);
1692
+ const contextExtras = wiring ? {
1693
+ arc: {
1694
+ resourceName,
1695
+ schemaOptions: options.schemaOptions,
1696
+ permissions,
1697
+ hooks: wiring.hooks,
1698
+ events: wiring.events,
1699
+ fields,
1700
+ idField: options.idField
1701
+ },
1702
+ server: {
1703
+ events: wiring.events,
1704
+ audit: wiring.audit,
1705
+ log: wiring.log
1706
+ }
1707
+ } : void 0;
1481
1708
  return async (input, _ctx) => {
1482
1709
  const session = _ctx.session;
1483
1710
  const permResult = await evaluatePermission(permissions, session, resourceName, operationName, input);
@@ -1488,7 +1715,18 @@ function createCustomRouteHandler(route, controller, hasId, options) {
1488
1715
  session
1489
1716
  });
1490
1717
  try {
1491
- const reqCtx = buildRequestContext(input, session, operationKindForRoute(route.method, hasId), permResult?.filters, permResult?.scope);
1718
+ const reqCtx = buildRequestContext(input, session, operationKindForRoute(route.method, hasId), permResult?.filters, permResult?.scope, contextExtras);
1719
+ const emit = (envelope) => {
1720
+ const data = applyMcpReadMasking(envelope.data, {
1721
+ fields,
1722
+ session,
1723
+ scopeOverride: permResult?.scope
1724
+ });
1725
+ return toCallToolResult(data === envelope.data ? envelope : {
1726
+ ...envelope,
1727
+ data
1728
+ });
1729
+ };
1492
1730
  if (typeof route.handler === "function") {
1493
1731
  const fn = route.handler;
1494
1732
  if (pipelineSteps.length > 0) {
@@ -1497,13 +1735,13 @@ function createCustomRouteHandler(route, controller, hasId, options) {
1497
1735
  resource: resourceName,
1498
1736
  operation: operationName
1499
1737
  };
1500
- return toCallToolResult(await executePipeline(pipelineSteps, pipeCtx, async (ctx) => {
1738
+ return emit(await executePipeline(pipelineSteps, pipeCtx, async (ctx) => {
1501
1739
  const raw = await fn(ctx);
1502
1740
  return raw !== null && typeof raw === "object" && "data" in raw ? raw : { data: raw };
1503
1741
  }, operationName));
1504
1742
  }
1505
1743
  const out = await fn(reqCtx);
1506
- return toCallToolResult(out !== null && typeof out === "object" && "data" in out ? out : { data: out });
1744
+ return emit(out !== null && typeof out === "object" && "data" in out ? out : { data: out });
1507
1745
  }
1508
1746
  if (!ctrl) return {
1509
1747
  content: [{
@@ -1520,7 +1758,7 @@ function createCustomRouteHandler(route, controller, hasId, options) {
1520
1758
  }],
1521
1759
  isError: true
1522
1760
  };
1523
- return toCallToolResult(await method(reqCtx));
1761
+ return emit(await method(reqCtx));
1524
1762
  } catch (err) {
1525
1763
  return toCallToolError(err instanceof Error ? err : new Error(String(err)));
1526
1764
  }
@@ -1594,6 +1832,7 @@ function resourceToTools(resource, config = {}) {
1594
1832
  const hasSoftDelete = resource._appliedPresets?.includes("softDelete") ?? false;
1595
1833
  const tools = [];
1596
1834
  const prefix = config.toolNamePrefix;
1835
+ const wiring = config.wiring;
1597
1836
  if (controller) {
1598
1837
  let ops = ALL_CRUD_OPS.filter((op) => !resource.disabledRoutes?.includes(op));
1599
1838
  if (config.operations) ops = ops.filter((op) => config.operations?.includes(op));
@@ -1604,6 +1843,15 @@ function resourceToTools(resource, config = {}) {
1604
1843
  allowedOperators,
1605
1844
  sortableFields
1606
1845
  });
1846
+ const inputSchema = buildInputSchema(op, fieldRules, {
1847
+ hiddenFields,
1848
+ readonlyFields,
1849
+ extraHideFields: config.hideFields,
1850
+ filterableFields,
1851
+ allowedOperators,
1852
+ adapterBodies
1853
+ });
1854
+ if (wiring?.idempotencyStore && op !== "list" && op !== "get") inputSchema._idempotencyKey = z.string().optional().describe("Optional idempotency key — retrying with the same key and input replays the first successful result instead of re-executing.");
1607
1855
  tools.push({
1608
1856
  name,
1609
1857
  description: resolveCrudDescription(config.descriptions?.[op], {
@@ -1616,15 +1864,12 @@ function resourceToTools(resource, config = {}) {
1616
1864
  sortableFields
1617
1865
  }),
1618
1866
  annotations: CRUD_ANNOTATIONS[op],
1619
- inputSchema: buildInputSchema(op, fieldRules, {
1620
- hiddenFields,
1621
- readonlyFields,
1622
- extraHideFields: config.hideFields,
1623
- filterableFields,
1624
- allowedOperators,
1625
- adapterBodies
1867
+ inputSchema,
1868
+ handler: createCrudHandler(op, controller, resource.name, resource.permissions, resource.fields, {
1869
+ wiring,
1870
+ schemaOptions: resource.schemaOptions,
1871
+ idField: resource.idField
1626
1872
  }),
1627
- handler: createCrudHandler(op, controller, resource.name, resource.permissions),
1628
1873
  source: `crud:${resource.name}:${op}`
1629
1874
  });
1630
1875
  }
@@ -1676,7 +1921,11 @@ function resourceToTools(resource, config = {}) {
1676
1921
  resourceName: resource.name,
1677
1922
  operationName: opName,
1678
1923
  permissions: route.permissions,
1679
- pipeline: resource.pipe
1924
+ pipeline: resource.pipe,
1925
+ fields: resource.fields,
1926
+ wiring,
1927
+ schemaOptions: resource.schemaOptions,
1928
+ idField: resource.idField
1680
1929
  })
1681
1930
  });
1682
1931
  }
@@ -1707,7 +1956,11 @@ function resourceToTools(resource, config = {}) {
1707
1956
  annotations,
1708
1957
  inputSchema: inputShape,
1709
1958
  source: `action:${resource.name}:${actionName}`,
1710
- handler: createActionToolHandler(actionName, handler, actionPerms, resource.name, resource.permissions, rawSchema, idLess)
1959
+ handler: createActionToolHandler(actionName, handler, actionPerms, resource.name, resource.permissions, rawSchema, idLess, resource.fields, {
1960
+ wiring,
1961
+ schemaOptions: resource.schemaOptions,
1962
+ idField: resource.idField
1963
+ })
1711
1964
  });
1712
1965
  }
1713
1966
  if (resource.aggregations && Object.keys(resource.aggregations).length > 0) {
@@ -1734,7 +1987,8 @@ function resourceToTools(resource, config = {}) {
1734
1987
  schemaOptions: resource.schemaOptions,
1735
1988
  repo: repoForAgg,
1736
1989
  buildOptionsFromSession,
1737
- prefix
1990
+ prefix,
1991
+ fields: resource.fields
1738
1992
  }));
1739
1993
  }
1740
1994
  return tools;
@@ -1944,10 +2198,29 @@ const mcpPluginImpl = async (fastify, options) => {
1944
2198
  include: options.include,
1945
2199
  exclude: options.exclude
1946
2200
  });
2201
+ const fastifyAny = fastify;
2202
+ const wiring = {
2203
+ get hooks() {
2204
+ return fastifyAny.arc?.hooks;
2205
+ },
2206
+ get events() {
2207
+ return fastifyAny.events;
2208
+ },
2209
+ get audit() {
2210
+ return fastifyAny.audit;
2211
+ },
2212
+ get log() {
2213
+ return fastify.log;
2214
+ },
2215
+ get idempotencyStore() {
2216
+ return fastifyAny.idempotency?.store;
2217
+ }
2218
+ };
1947
2219
  const overrides = options.overrides ?? {};
1948
2220
  const allTools = enabledResources.flatMap((r) => {
1949
2221
  const resOverrides = overrides[r.name] ?? {};
1950
2222
  return resourceToTools(r, {
2223
+ wiring,
1951
2224
  ...resOverrides,
1952
2225
  toolNamePrefix: resOverrides.toolNamePrefix ?? options.toolNamePrefix
1953
2226
  });
@@ -1,4 +1,4 @@
1
- import { I as MiddlewareHandler, L as RequestWithExtras, Q as MiddlewareConfig } from "../index-Dtrj6XZk.mjs";
1
+ import { I as MiddlewareHandler, L as RequestWithExtras, Q as MiddlewareConfig } from "../index-BBsvQt7U.mjs";
2
2
  import { RouteHandlerMethod } from "fastify";
3
3
  //#region src/middleware/middleware.d.ts
4
4
  interface NamedMiddleware {
@@ -1,4 +1,4 @@
1
- import { n as ErrorMapper } from "./errorHandler-B0e-bq-O.mjs";
1
+ import { n as ErrorMapper } from "./errorHandler-C6yv4ZTW.mjs";
2
2
  import { FastifyInstance } from "fastify";
3
3
  //#region src/factory/loadResources.d.ts
4
4
  /**
@@ -306,6 +306,31 @@ interface ArcModule<TExports = unknown> {
306
306
  * ```
307
307
  */
308
308
  bootstrap?: (fastify: FastifyInstance) => TExports | Promise<TExports>;
309
+ /**
310
+ * App-level resource NAMES this module authoritatively SUPERSEDES. When the
311
+ * host also lists (or `resourceDir`-discovers) a resource of the same name,
312
+ * arc DROPS the app copy and registers THIS module's version instead — so the
313
+ * host keeps NO hand-maintained "which resources did modules take over" filter
314
+ * set. Ownership lives on the atom that provides it (colocated, drift-proof):
315
+ *
316
+ * ```ts
317
+ * defineModule({ name: "order", owns: ["order", "quotation", "rfq"], resources: () => [...] })
318
+ * ```
319
+ *
320
+ * Semantics:
321
+ * - Purely a supersede-the-app-fork switch — it filters the *app* resource
322
+ * list, never the module's own `resources` (those always register).
323
+ * - Static + declarative: read at compose time, so it works regardless of
324
+ * whether `resources` is an array or a post-bootstrap factory (no early
325
+ * factory resolution, no boot-order coupling).
326
+ * - Idempotent + tolerant: an `owns` entry with no matching app resource is
327
+ * a silent no-op — a module may pre-declare a name before any fork exists.
328
+ * - Collected across ALL modules; the app-side supersession is their union.
329
+ *
330
+ * Contract: if you `owns` a name, PROVIDE it (in this module's `resources`).
331
+ * Dropping the app fork without supplying a replacement removes the route.
332
+ */
333
+ readonly owns?: readonly string[];
309
334
  /**
310
335
  * The module's resources. Array or factory — the factory form runs AFTER all
311
336
  * bootstraps, so `defineResource(...)` receives fully-booted engines. Flows
@@ -1,8 +1,8 @@
1
1
  import { t as getUserRoles } from "./types-XTApa8b6.mjs";
2
- import { n as convertRouteSchema } from "./schemaConverter-U0MnO9vd.mjs";
3
- import { t as resolveActionPermission } from "./actionPermissions-ze70xXJi.mjs";
2
+ import { n as convertRouteSchema } from "./schemaConverter-DJvodiHj.mjs";
3
+ import { t as resolveActionPermission } from "./actionPermissions-lszoJle1.mjs";
4
4
  import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
5
- import { t as buildActionBodySchema } from "./createActionRouter-BWMDW-dL.mjs";
5
+ import { t as buildActionBodySchema } from "./createActionRouter-BuOv-m4Y.mjs";
6
6
  import fp from "fastify-plugin";
7
7
  //#region src/docs/openapi/canonical-schemas.ts
8
8
  /**
@@ -1,3 +1,4 @@
1
- import { a as applyFieldWritePermissions, c as PermissionCheck, d as UserBase, f as getUserRoles, i as applyFieldReadPermissions, l as PermissionContext, n as FieldPermissionMap, o as fields, p as normalizeRoles, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission, u as PermissionResult } from "../fields-BGqrAa_u.mjs";
2
- import { A as requireOwnership, B as requireMandate, C as createOrgPermissions, D as denyAll, E as anyOf, F as normalizePermissionResult, I as RequireAgentScopeOptions, L as RequireMandateOptions, M as roles, N as when, O as not, P as applyPermissionResult, R as requireAgentScope, S as createDynamicPermissionMatrix, T as allowPublic, _ as createRoleHierarchy, a as permissionMatrix, b as DynamicPermissionMatrixConfig, c as publicReadAdminWrite, d as requireOrgMembership, f as requireOrgRole, g as RoleHierarchy, h as requireTeamMembership, i as ownerWithAdminBypass, j as requireRoles, k as requireAuth, l as readOnly, m as requireServiceScope, n as authenticated, o as presets_d_exports, p as requireScopeContext, r as fullPublic, s as publicRead, t as adminOnly, u as requireOrgInScope, v as ConnectEventsOptions, w as allOf, x as PermissionEventBus, y as DynamicPermissionMatrix, z as requireDPoP } from "../index-B5PoNbfu.mjs";
3
- export { type ConnectEventsOptions, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type FieldPermission, type FieldPermissionMap, type FieldPermissionType, type PermissionCheck, type PermissionContext, type PermissionEventBus, type PermissionResult, type RequireAgentScopeOptions, type RequireMandateOptions, type RoleHierarchy, type UserBase, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizePermissionResult, normalizeRoles, not, ownerWithAdminBypass, permissionMatrix, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
1
+ import { a as getUserRoles, i as UserBase, n as PermissionContext, o as normalizeRoles, r as PermissionResult, t as PermissionCheck } from "../types-Csxga7d3.mjs";
2
+ import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-D3lhgzhD.mjs";
3
+ import { A as allOf, B as applyPermissionResult, C as requireGrant, D as PermissionEventBus, E as DynamicPermissionMatrixConfig, F as requireAuth, G as requireDPoP, H as RequireAgentScopeOptions, I as requireOwnership, K as requireMandate, L as requireRoles, M as anyOf, N as denyAll, O as createDynamicPermissionMatrix, P as not, R as roles, S as modeSatisfies, T as DynamicPermissionMatrix, U as RequireMandateOptions, V as normalizePermissionResult, W as requireAgentScope, _ as createRoleHierarchy, a as permissionMatrix, b as GrantResolution, c as publicReadAdminWrite, d as requireOrgMembership, f as requireOrgRole, g as RoleHierarchy, h as requireTeamMembership, i as ownerWithAdminBypass, j as allowPublic, k as createOrgPermissions, l as readOnly, m as requireServiceScope, n as authenticated, o as presets_d_exports, p as requireScopeContext, r as fullPublic, s as publicRead, t as adminOnly, u as requireOrgInScope, v as GRANT_MODES, w as ConnectEventsOptions, x as RequireGrantOptions, y as GrantMode, z as when } from "../index-wMoWBLkn.mjs";
4
+ export { type ConnectEventsOptions, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type FieldPermission, type FieldPermissionMap, type FieldPermissionType, GRANT_MODES, type GrantMode, type GrantResolution, type PermissionCheck, type PermissionContext, type PermissionEventBus, type PermissionResult, type RequireAgentScopeOptions, type RequireGrantOptions, type RequireMandateOptions, type RoleHierarchy, type UserBase, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, modeSatisfies, normalizePermissionResult, normalizeRoles, not, ownerWithAdminBypass, permissionMatrix, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
@@ -1,3 +1,4 @@
1
- import { A as requireDPoP, C as not, D as roles, E as requireRoles, F as applyFieldReadPermissions, I as applyFieldWritePermissions, L as fields, M as applyPermissionResult, O as when, P as normalizePermissionResult, R as resolveEffectiveRoles, S as denyAll, T as requireOwnership, _ as requireServiceScope, a as permissionMatrix, b as allowPublic, c as publicReadAdminWrite, d as createDynamicPermissionMatrix, f as createOrgPermissions, g as requireScopeContext, h as requireOrgRole, i as ownerWithAdminBypass, j as requireMandate, k as requireAgentScope, l as readOnly, m as requireOrgMembership, n as authenticated, o as presets_exports, p as requireOrgInScope, r as fullPublic, s as publicRead, t as adminOnly, u as createRoleHierarchy, v as requireTeamMembership, w as requireAuth, x as anyOf, y as allOf } from "../permissions-BJMuKMl7.mjs";
1
+ import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, o as fields, r as normalizePermissionResult, s as resolveEffectiveRoles, t as applyPermissionResult } from "../applyPermissionResult-Tw4iXtlf.mjs";
2
2
  import { n as normalizeRoles, t as getUserRoles } from "../types-XTApa8b6.mjs";
3
- export { adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizePermissionResult, normalizeRoles, not, ownerWithAdminBypass, permissionMatrix, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
3
+ import { A as roles, C as allowPublic, D as requireAuth, E as not, M as requireAgentScope, N as requireDPoP, O as requireOwnership, P as requireMandate, S as allOf, T as denyAll, _ as requireOrgMembership, a as permissionMatrix, b as requireServiceScope, c as publicReadAdminWrite, d as GRANT_MODES, f as modeSatisfies, g as requireOrgInScope, h as createOrgPermissions, i as ownerWithAdminBypass, j as when, k as requireRoles, l as readOnly, m as createDynamicPermissionMatrix, n as authenticated, o as presets_exports, p as requireGrant, r as fullPublic, s as publicRead, t as adminOnly, u as createRoleHierarchy, v as requireOrgRole, w as anyOf, x as requireTeamMembership, y as requireScopeContext } from "../permissions-tbxFHxjZ.mjs";
4
+ export { GRANT_MODES, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, modeSatisfies, normalizePermissionResult, normalizeRoles, not, ownerWithAdminBypass, permissionMatrix, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };