@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.
- package/dist/{BaseController-BnLYgE9A.mjs → BaseController-BQ8KNvWC.mjs} +3 -2
- package/dist/{ResourceRegistry-7RnrEWNP.mjs → ResourceRegistry-y9Hnypus.mjs} +1 -0
- package/dist/{actionPermissions-ze70xXJi.mjs → actionPermissions-lszoJle1.mjs} +1 -1
- package/dist/applyPermissionResult-Tw4iXtlf.mjs +264 -0
- package/dist/audit/index.d.mts +2 -2
- package/dist/auth/index.d.mts +30 -2
- package/dist/auth/index.mjs +6 -3
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +3 -3
- package/dist/{core-DZ6Xe1jR.mjs → core-DQ6rDTyH.mjs} +126 -68
- package/dist/{createActionRouter-BWMDW-dL.mjs → createActionRouter-BuOv-m4Y.mjs} +10 -6
- package/dist/{createAggregationRouter-l5mNdYrZ.mjs → createAggregationRouter-CgJv_BU_.mjs} +3 -3
- package/dist/{createApp-Bi61XxqU.mjs → createApp-CjOeWJ9_.mjs} +252 -57
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +1 -1
- package/dist/encryption/index.mjs +9 -5
- package/dist/{errorHandler-Dxf6P_kV.mjs → errorHandler-Bq2OeEQL.mjs} +34 -10
- package/dist/{errorHandler-B0e-bq-O.d.mts → errorHandler-C6yv4ZTW.d.mts} +13 -0
- package/dist/events/index.mjs +5 -2
- package/dist/factory/index.d.mts +46 -9
- package/dist/factory/index.mjs +64 -13
- package/dist/{fastify-augmentation-DafigGQp.d.mts → fastify-augmentation-g_f9omSc.d.mts} +2 -2
- package/dist/fields-D3lhgzhD.d.mts +121 -0
- package/dist/health-ScyjIVo5.mjs +202 -0
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +7 -0
- package/dist/idempotency/index.mjs +7 -17
- package/dist/{index-Dtrj6XZk.d.mts → index-BBsvQt7U.d.mts} +1310 -1226
- package/dist/{types-DpxoNX5v.d.mts → index-Ba10fdKp.d.mts} +196 -66
- package/dist/{index-B5N-NaHs.d.mts → index-CC5ruDGh.d.mts} +3 -3
- package/dist/{index-B5PoNbfu.d.mts → index-wMoWBLkn.d.mts} +68 -2
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +6 -5
- package/dist/{init-0YhHkXGk.mjs → init-CjO4p_q1.mjs} +123 -4
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +67 -4
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/webhooks.d.mts +131 -7
- package/dist/integrations/webhooks.mjs +169 -10
- package/dist/interface-n5hpKg1d.mjs +16 -0
- package/dist/jsonBody-BlzAoGCe.mjs +43 -0
- package/dist/{loadResourcesFromEntry-OMCvIEE7.mjs → loadResourcesFromEntry-kvGT6EcO.mjs} +1 -1
- package/dist/logger/index.d.mts +26 -1
- package/dist/logger/index.mjs +39 -1
- package/dist/{mcpPlugin-B9XjjNVG.mjs → mcpPlugin-BtzIL_kM.mjs} +312 -39
- package/dist/middleware/index.d.mts +1 -1
- package/dist/{module-WeuU5jfd.d.mts → module-B4u10iOJ.d.mts} +26 -1
- package/dist/{openapi-Kyod_di6.mjs → openapi-jSDx-VDv.mjs} +3 -3
- package/dist/permissions/index.d.mts +4 -3
- package/dist/permissions/index.mjs +3 -2
- package/dist/{permissions-BJMuKMl7.mjs → permissions-tbxFHxjZ.mjs} +77 -264
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/plugins/index.d.mts +24 -7
- package/dist/plugins/index.mjs +14 -282
- package/dist/plugins/response-cache.mjs +1 -0
- package/dist/plugins/tracing-entry.mjs +7 -4
- package/dist/presets/filesUpload.d.mts +2 -2
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +1 -1
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-gw0ciIUD.mjs → presets-BOe4Ugkl.mjs} +1 -1
- package/dist/rateLimitKey-BoWRH3e7.mjs +14 -0
- package/dist/realtime-I8OrfnMR.mjs +375 -0
- package/dist/{registerRoute-oGAl0oA8.mjs → registerRoute-CWO6mdYe.mjs} +38 -18
- package/dist/registry/index.d.mts +2 -2
- package/dist/registry/index.mjs +1 -1
- package/dist/requestId-5BhTVzBv.mjs +113 -0
- package/dist/schemaConverter-DJvodiHj.mjs +171 -0
- package/dist/{schemaIR-ajetw3Fv.mjs → schemaIR-Ca7ySNPx.mjs} +2 -2
- package/dist/scim/index.mjs +6 -7
- package/dist/scope/index.mjs +2 -76
- package/dist/scope-LONQ3mfZ.mjs +37 -0
- package/dist/simpleEqualityMatcher-Cg05HPsn.mjs +68 -0
- package/dist/{sse-CfUjwjDk.mjs → sse-0u4P4-OI.mjs} +7 -30
- package/dist/sseStream-BQ7Qaynp.mjs +57 -0
- package/dist/testing/index.d.mts +83 -3
- package/dist/testing/index.mjs +70 -3
- package/dist/types/index.d.mts +2 -2
- package/dist/{types-DRj-Ut4n.d.mts → types-5OuqeTDX.d.mts} +37 -2
- package/dist/{fields-BGqrAa_u.d.mts → types-Csxga7d3.d.mts} +1 -121
- package/dist/usage/index.d.mts +142 -0
- package/dist/usage/index.mjs +0 -0
- package/dist/utils/index.d.mts +101 -19
- package/dist/utils/index.mjs +5 -3
- package/dist/{utils-CO8a3B_1.mjs → utils-CZyeRXTh.mjs} +80 -82
- package/dist/{versioning-DQ4mCvg0.d.mts → versioning-D6PvCwpq.d.mts} +43 -9
- package/llms.txt +39 -0
- package/package.json +513 -447
- package/skills/arc/SKILL.md +14 -8
- package/skills/arc/references/api-reference.md +34 -0
- package/skills/arc/references/auth.md +21 -4
- package/skills/arc/references/mcp.md +1 -1
- package/skills/arc/references/production.md +734 -654
- package/skills/arc-code-review/SKILL.md +1 -1
- package/skills/arc-code-review/references/anti-patterns.md +71 -18
- package/skills/arc-code-review/references/arc-cheatsheet.md +15 -2
- package/skills/arc-code-review/references/migration-recipes.md +7 -7
- package/skills/arc-code-review/references/mongokit-migration.md +4 -3
- package/skills/arc-module-publishing/SKILL.md +2 -1
- package/skills/arc-module-publishing/references/authoring-modules.md +55 -0
- package/skills/arc-module-publishing/references/package-manifest.md +4 -2
- package/dist/preloadResources-CHw3_oA_.mjs +0 -45
- 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-
|
|
4
|
-
import {
|
|
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-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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) =>
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
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)
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
3
|
-
import { t as resolveActionPermission } from "./actionPermissions-
|
|
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-
|
|
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
|
|
2
|
-
import {
|
|
3
|
-
|
|
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 {
|
|
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
|
-
|
|
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 };
|