@peers-app/peers-sdk 0.25.18 → 0.25.20

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 (33) hide show
  1. package/README.md +9 -1
  2. package/dist/contracts/__tests__/action-dispatch.test.d.ts +1 -0
  3. package/dist/contracts/__tests__/action-dispatch.test.js +339 -0
  4. package/dist/contracts/__tests__/generic-tool-dispatch.test.d.ts +1 -0
  5. package/dist/contracts/__tests__/generic-tool-dispatch.test.js +173 -0
  6. package/dist/contracts/action-dispatch.d.ts +12 -0
  7. package/dist/contracts/action-dispatch.js +73 -0
  8. package/dist/contracts/contract-provider-router.js +7 -1
  9. package/dist/contracts/contract-proxy.d.ts +47 -0
  10. package/dist/contracts/contract-proxy.js +152 -16
  11. package/dist/contracts/index.d.ts +2 -1
  12. package/dist/contracts/index.js +5 -2
  13. package/dist/contracts/system/contract-catalog-contract.d.ts +2 -0
  14. package/dist/data/messages.d.ts +3 -3
  15. package/dist/data/package-versions.d.ts +10 -10
  16. package/dist/data/tool-access.d.ts +3 -1
  17. package/dist/data/tool-access.js +5 -2
  18. package/dist/data/tool-access.test.js +7 -0
  19. package/dist/data/tools.d.ts +7 -3
  20. package/dist/data/tools.js +7 -1
  21. package/dist/invites/invite-messages.d.ts +2 -2
  22. package/dist/package-loader/host-authority-loading.test.d.ts +1 -0
  23. package/dist/package-loader/host-authority-loading.test.js +87 -0
  24. package/dist/package-loader/host-dispatch-policy.test.d.ts +1 -0
  25. package/dist/package-loader/host-dispatch-policy.test.js +56 -0
  26. package/dist/package-loader/isolated-artifact.d.ts +16 -2
  27. package/dist/package-loader/isolated-artifact.js +40 -3
  28. package/dist/package-loader/isolated-artifact.test.js +38 -0
  29. package/dist/package-loader/isolated-runtime.d.ts +15 -0
  30. package/dist/package-loader/package-loader.d.ts +2 -0
  31. package/dist/package-loader/package-loader.js +60 -0
  32. package/dist/package-loader/package-loader.test.js +1 -1
  33. package/package.json +1 -1
@@ -3,6 +3,7 @@ import type { Table } from "../data/orm/table";
3
3
  import type { IToolInstance } from "../data/tools";
4
4
  import type { Event, ISubscriptionResult } from "../events";
5
5
  import { type Observable } from "../observable";
6
+ import type { IIsolatedCallPrincipal } from "../package-loader/isolated-runtime";
6
7
  import { type IContractTransport } from "./contract-transport";
7
8
  import type { IContractDefinition, IRemoteContractConsumer } from "./types";
8
9
  /**
@@ -233,6 +234,18 @@ export interface IContractToolContext {
233
234
  * Absent for trusted local callers (the signed-in UI session and the CLI).
234
235
  */
235
236
  callerPackageId?: string;
237
+ /** Trusted frame, retained across host-backed action dispatch; never from arguments. */
238
+ authority?: IIsolatedCallPrincipal;
239
+ /** Select a target under this tool’s trusted frame; authority never belongs in arguments. */
240
+ dispatchTool?: (target: IContractToolTarget, args: unknown) => Promise<any>;
241
+ /** Checked alias dispatch supplied only by the host provider. */
242
+ dispatchAction?: (name: string, args: unknown) => Promise<any>;
243
+ /** Signed actor selected by the host. */
244
+ actorUserId?: string;
245
+ /** Incoming host frame for read-only infrastructure projections; preserves the turn ceiling. */
246
+ callContext?: IContractCallContext;
247
+ /** Original turn context for read-only catalog projection, before infrastructure admission. */
248
+ incomingCallContext?: IContractCallContext;
236
249
  }
237
250
  /**
238
251
  * Build the **consumer** side of a contract proxy from a contract definition and a
@@ -304,6 +317,12 @@ export interface IContractResolution {
304
317
  version: number;
305
318
  tables?: Record<string, Table<any>>;
306
319
  tools?: Record<string, IToolInstance>;
320
+ /** Tool used for alias catalog admission; defaults to a tool requesting preservation. */
321
+ actionDispatcher?: string;
322
+ /** Private canonical tools; selectors never carry their own numeric permissions. */
323
+ actionTools?: Record<string, IToolInstance>;
324
+ /** Package-owned selector-to-tool mapping, validated by the host. */
325
+ actionAliases?: Record<string, string>;
307
326
  /**
308
327
  * Host-only capabilities appended as the final argument to provider tool functions.
309
328
  * Omit this for remote or otherwise untrusted provider routes.
@@ -366,6 +385,8 @@ export interface IContractCallContext {
366
385
  * In-process only — never serialized across a connection.
367
386
  */
368
387
  dataContext?: DataContext;
388
+ /** In-process delegated execution frame. Never serialized or read from a call payload. */
389
+ authority?: IIsolatedCallPrincipal;
369
390
  }
370
391
  /**
371
392
  * A gate that decides whether a given call is allowed. Runs before dispatch on the
@@ -380,6 +401,25 @@ export type ContractPermissionCheck = (call: IContractCall, context: IContractCa
380
401
  * for compatibility and isolated in-process providers that intentionally need the old gate.
381
402
  */
382
403
  export declare const sameUserContractPermissionCheck: ContractPermissionCheck;
404
+ /** Validate private alias registrations before exposing any action wrapper. */
405
+ export declare function validateContractActions(resolution: IContractResolution): void;
406
+ /**
407
+ * Project executable aliases using live tool metadata and trusted caller identity.
408
+ *
409
+ * Catalog filtering is advisory; execution rechecks every target.
410
+ */
411
+ export declare function authorizedContractActionNames(resolution: IContractResolution, context: IContractCallContext): Promise<string[]>;
412
+ /** Dynamic local tool reference; provider pinning is required for package-owned actions. */
413
+ export interface IContractToolTarget {
414
+ contractId: string;
415
+ version: number;
416
+ toolName: string;
417
+ providerPackageId?: string;
418
+ dataContextId?: string;
419
+ targetDeviceId?: string;
420
+ }
421
+ /** Host dispatch bridge invoked only with a frame bound by the provider. */
422
+ export type ContractToolDispatch = (target: IContractToolTarget, args: unknown, context: IContractCallContext) => Promise<any>;
383
423
  /**
384
424
  * Build the **provider** side of a contract proxy: an async handler that permission-checks
385
425
  * an {@link IContractCall} and dispatches it to the live table method / tool fn / observable
@@ -390,12 +430,17 @@ export declare const sameUserContractPermissionCheck: ContractPermissionCheck;
390
430
  *
391
431
  * @param resolution The live contract implementation to dispatch to.
392
432
  * @param opts.permissionCheck Optional gate run before every dispatch.
433
+ * @param opts.dispatchTool Trusted runtime target resolver and invoker for `context.dispatchTool`.
393
434
  */
394
435
  export declare function createContractProvider(resolution: IContractResolution, opts?: {
395
436
  permissionCheck?: ContractPermissionCheck;
437
+ /** Trusted runtime target resolver and invoker. */
438
+ dispatchTool?: ContractToolDispatch;
396
439
  }): (call: IContractCall, context?: IContractCallContext) => Promise<any>;
397
440
  /** Options for {@link createContractProviderSession}. */
398
441
  export interface IContractProviderSessionOptions {
442
+ /** Trusted runtime target resolver and invoker. */
443
+ dispatchTool?: ContractToolDispatch;
399
444
  /** Gate run before every request and every event `subscribe` (see {@link ContractPermissionCheck}). */
400
445
  permissionCheck?: ContractPermissionCheck;
401
446
  /**
@@ -427,6 +472,8 @@ export interface IContractProviderSession {
427
472
  export type ContractNotificationSink = (notification: IContractNotification) => Promise<unknown>;
428
473
  /** Options for {@link createContractProviderEndpoint}. */
429
474
  export interface IContractProviderEndpointOptions {
475
+ /** Trusted runtime target resolver and invoker. */
476
+ dispatchTool?: ContractToolDispatch;
430
477
  /** Delivers subscription payloads without binding the endpoint to a transport. */
431
478
  notify: ContractNotificationSink;
432
479
  /** Optional defense-in-depth gate run before calls and subscription creation. */
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sameUserContractPermissionCheck = exports.CONTRACT_CALL_RPC = void 0;
4
4
  exports.createContractConsumer = createContractConsumer;
5
5
  exports.createRemoteContractConsumer = createRemoteContractConsumer;
6
+ exports.validateContractActions = validateContractActions;
7
+ exports.authorizedContractActionNames = authorizedContractActionNames;
6
8
  exports.createContractProvider = createContractProvider;
7
9
  exports.createContractProviderEndpoint = createContractProviderEndpoint;
8
10
  exports.createContractProviderSession = createContractProviderSession;
@@ -11,6 +13,7 @@ const group_permissions_1 = require("../data/group-permissions");
11
13
  const decorators_1 = require("../data/orm/decorators");
12
14
  const observable_1 = require("../observable");
13
15
  const utils_1 = require("../utils");
16
+ const action_dispatch_1 = require("./action-dispatch");
14
17
  const contract_transport_1 = require("./contract-transport");
15
18
  const STANDARD_REMOTE_TABLE_METHODS = new Set([
16
19
  "get",
@@ -456,8 +459,9 @@ exports.sameUserContractPermissionCheck = sameUserContractPermissionCheck;
456
459
  /**
457
460
  * Deny a contract tool when the caller’s group/personal access is below the tool.
458
461
  *
459
- * Tools at {@link AccessLevel.None} are unrestricted and do not need a caller
460
- * identity. Higher levels fail closed if the transport omitted `callerUserId`
462
+ * Ordinary infrastructure tools at {@link AccessLevel.None} need no caller identity.
463
+ * Strict dispatch requires trusted identity/context even at None. Higher levels
464
+ * fail closed if the transport omitted `callerUserId`
461
465
  * and `localUserId`. Role lookup uses {@link IContractCallContext.dataContext}
462
466
  * when the host attached one, so multi-device processes do not wait on the
463
467
  * user-context singleton.
@@ -469,20 +473,97 @@ exports.sameUserContractPermissionCheck = sameUserContractPermissionCheck;
469
473
  * @param context - Caller identity from the transport.
470
474
  */
471
475
  async function assertContractToolAccess(tool, call, context) {
472
- const required = (0, access_level_1.resolveAccessLevel)(tool.tool.accessLevel);
473
- if (required <= access_level_1.AccessLevel.None) {
474
- return;
475
- }
476
+ const mode = tool.tool.authorityPropagation ?? "cap";
477
+ const required = (0, action_dispatch_1.dispatchAdmissionLevel)(tool.tool.accessLevel, tool.tool.authorityPropagation);
478
+ const strict = mode === "preserve" || context.authority?.strictActionScope === true;
479
+ if (strict && call.dataContextId && call.dataContextId !== context.dataContext?.dataContextId)
480
+ throw new Error("Cross-context action dispatch is denied");
481
+ if (strict && call.targetDeviceId)
482
+ throw new Error("Strict delegated calls cannot target another device until authority transport is supported");
476
483
  const userId = context.callerUserId ?? context.localUserId;
477
- if (!userId) {
478
- throw new Error(`Permission denied: missing caller identity for tool '${tool.tool.name}'`);
484
+ // Preserve unrestricted infrastructure calls outside the bounded action scope.
485
+ if (!strict && required === access_level_1.AccessLevel.None)
486
+ return {
487
+ ...context.authority,
488
+ userId,
489
+ userAccessLevel: context.authority?.userAccessLevel ?? access_level_1.AccessLevel.None,
490
+ strictActionScope: false,
491
+ callingToolAccessLevel: required,
492
+ authorityPropagation: "cap",
493
+ };
494
+ if ((!userId || (strict && !context.dataContext)) && (strict || required > access_level_1.AccessLevel.None)) {
495
+ throw new Error(`Permission denied: missing caller identity or trusted context for tool '${tool.tool.name}'`);
496
+ }
497
+ const userLevel = userId
498
+ ? context.dataContext
499
+ ? await (0, group_permissions_1.getUserAccessLevel)(context.dataContext, userId)
500
+ : (0, access_level_1.accessLevelFromGroupRole)(await (0, group_permissions_1.getUserRole)(call.dataContextId || context.localUserId || userId, userId))
501
+ : access_level_1.AccessLevel.None;
502
+ return (0, action_dispatch_1.authorizeToolDispatch)({ ...context.authority, userId, userAccessLevel: userLevel }, required, mode, strict);
503
+ }
504
+ /** Validate private alias registrations before exposing any action wrapper. */
505
+ function validateContractActions(resolution) {
506
+ for (const [name, target] of Object.entries(resolution.actionAliases ?? {})) {
507
+ const tool = resolution.actionTools?.[target];
508
+ if (!name || !tool || tool.tool.name !== target || target === resolution.actionDispatcher)
509
+ throw new Error(`Unregistered action target: ${name} -> ${target}`);
510
+ }
511
+ }
512
+ /**
513
+ * Project executable aliases using live tool metadata and trusted caller identity.
514
+ *
515
+ * Catalog filtering is advisory; execution rechecks every target.
516
+ */
517
+ async function authorizedContractActionNames(resolution, context) {
518
+ validateContractActions(resolution);
519
+ if (!(context.callerUserId ?? context.localUserId) || !context.dataContext)
520
+ return [];
521
+ const wrapperName = resolution.actionDispatcher ??
522
+ Object.keys(resolution.tools ?? {}).find((name) => resolution.tools?.[name].tool.authorityPropagation === "preserve");
523
+ const wrapper = wrapperName ? resolution.tools?.[wrapperName] : undefined;
524
+ if (!wrapper)
525
+ return [];
526
+ let wrapperAuthority;
527
+ try {
528
+ wrapperAuthority = await assertContractToolAccess(wrapper, {
529
+ contractId: resolution.contractId,
530
+ version: resolution.version,
531
+ member: "tool",
532
+ name: wrapperName,
533
+ operation: "run",
534
+ args: [],
535
+ }, context);
479
536
  }
480
- const userLevel = context.dataContext
481
- ? await (0, group_permissions_1.getUserAccessLevel)(context.dataContext, userId)
482
- : (0, access_level_1.accessLevelFromGroupRole)(await (0, group_permissions_1.getUserRole)(call.dataContextId || context.localUserId || userId, userId));
483
- if (userLevel < required) {
484
- throw new Error(`Permission denied: ${tool.tool.name} requires ${(0, access_level_1.getAccessLevelLabel)(required)} (${required})`);
537
+ catch {
538
+ return [];
485
539
  }
540
+ const allowed = [];
541
+ for (const [name, target] of Object.entries(resolution.actionAliases ?? {})) {
542
+ try {
543
+ const action = resolution.actionTools?.[target];
544
+ if (!action)
545
+ continue;
546
+ await assertContractToolAccess(action, {
547
+ contractId: resolution.contractId,
548
+ version: resolution.version,
549
+ member: "tool",
550
+ name: target,
551
+ operation: "run",
552
+ args: [],
553
+ }, {
554
+ ...context,
555
+ authority: {
556
+ ...wrapperAuthority,
557
+ strictActionScope: true,
558
+ },
559
+ });
560
+ allowed.push(name);
561
+ }
562
+ catch {
563
+ /* Denied aliases are not executable. */
564
+ }
565
+ }
566
+ return allowed;
486
567
  }
487
568
  /**
488
569
  * Build the **provider** side of a contract proxy: an async handler that permission-checks
@@ -494,9 +575,11 @@ async function assertContractToolAccess(tool, call, context) {
494
575
  *
495
576
  * @param resolution The live contract implementation to dispatch to.
496
577
  * @param opts.permissionCheck Optional gate run before every dispatch.
578
+ * @param opts.dispatchTool Trusted runtime target resolver and invoker for `context.dispatchTool`.
497
579
  */
498
580
  function createContractProvider(resolution, opts = {}) {
499
581
  const { permissionCheck } = opts;
582
+ validateContractActions(resolution);
500
583
  return async (call, context = {}) => {
501
584
  if (call.contractId !== resolution.contractId || call.version !== resolution.version) {
502
585
  throw new Error(`Contract mismatch: resolution provides ${resolution.contractId} v${resolution.version} ` +
@@ -538,8 +621,13 @@ function createContractProvider(resolution, opts = {}) {
538
621
  if (!tool) {
539
622
  throw new Error(`Contract ${call.contractId} does not provide tool '${call.name}'`);
540
623
  }
541
- await assertContractToolAccess(tool, call, context);
542
- if (resolution.toolContext || resolution.forwardCallContext) {
624
+ if (resolution.actionTools && !Object.keys(resolution.actionAliases ?? {}).length)
625
+ throw new Error("Action dispatcher requires registered checked actions");
626
+ const authority = await assertContractToolAccess(tool, call, context);
627
+ if (resolution.toolContext ||
628
+ resolution.forwardCallContext ||
629
+ resolution.actionAliases ||
630
+ authority.strictActionScope) {
543
631
  if (call.args.length > 1) {
544
632
  throw new Error("Permission denied: tool runs accept a single argument when host context is forwarded");
545
633
  }
@@ -549,9 +637,54 @@ function createContractProvider(resolution, opts = {}) {
549
637
  throw new Error("Persistent variables are not available to this contract tool");
550
638
  },
551
639
  };
640
+ const dispatchTool = (frame) => async (target, args) => {
641
+ if (target.dataContextId &&
642
+ target.dataContextId !== context.dataContext?.dataContextId)
643
+ throw new Error("Cross-context action dispatch is denied");
644
+ if (target.targetDeviceId)
645
+ throw new Error("Strict delegated calls cannot target another device until authority transport is supported");
646
+ if (!context.dataContext || !frame.userId)
647
+ throw new Error("Missing trusted execution context");
648
+ if (!opts.dispatchTool)
649
+ throw new Error("Runtime tool dispatch is unavailable");
650
+ return opts.dispatchTool(target, args, {
651
+ ...context,
652
+ authority: (0, action_dispatch_1.narrowActionPrincipal)(frame, true),
653
+ });
654
+ };
655
+ const checkedActionDispatcher = (frame, capabilities) => async (name, args) => {
656
+ const target = resolution.actionAliases?.[name];
657
+ const action = target ? resolution.actionTools?.[target] : undefined;
658
+ if (!target || !action)
659
+ throw new Error(`Unknown action selector: ${name}`);
660
+ const actionCall = { ...call, name: target, args: [args] };
661
+ const actionContext = {
662
+ ...context,
663
+ authority: { ...frame, strictActionScope: true },
664
+ };
665
+ const checked = await assertContractToolAccess(action, actionCall, actionContext);
666
+ return action.toolFn(args, {
667
+ ...capabilities,
668
+ callerPackageId: context.callerPackageId,
669
+ actorUserId: checked.userId,
670
+ authority: checked,
671
+ callContext: { ...context, authority: checked },
672
+ incomingCallContext: actionContext,
673
+ dispatchAction: checkedActionDispatcher(checked, capabilities),
674
+ dispatchTool: dispatchTool(checked),
675
+ });
676
+ };
552
677
  return tool.toolFn(call.args[0], {
553
678
  ...base,
554
679
  callerPackageId: context.callerPackageId,
680
+ actorUserId: authority.userId,
681
+ callContext: { ...context, authority },
682
+ incomingCallContext: context,
683
+ dispatchTool: dispatchTool(authority),
684
+ authority,
685
+ dispatchAction: resolution.actionAliases
686
+ ? checkedActionDispatcher(authority, base)
687
+ : undefined,
555
688
  });
556
689
  }
557
690
  return tool.toolFn(...call.args);
@@ -600,7 +733,10 @@ function createContractProvider(resolution, opts = {}) {
600
733
  */
601
734
  function createContractProviderEndpoint(resolution, opts) {
602
735
  const { notify, permissionCheck, context: defaultContext } = opts;
603
- const dispatch = createContractProvider(resolution, { permissionCheck });
736
+ const dispatch = createContractProvider(resolution, {
737
+ permissionCheck,
738
+ dispatchTool: opts.dispatchTool,
739
+ });
604
740
  // One live subscription per resolved subscription key, refcounted by the subscribers
605
741
  // currently attached to it, plus a reverse index for unsubscribe. Each subscriber keeps
606
742
  // the caller context from its subscribe call so event filters can differ per consumer.
@@ -1,7 +1,8 @@
1
+ export * from "./action-dispatch";
1
2
  export { ContractBuilder, definePackage, PackageBuilder } from "./builder";
2
3
  export { type ContractCallAuthorizer, type ContractProviderEndpointResolver, type ContractProviderPackageResolver, createContractProviderRouter, type IAuthorizedContractRoute, type IContractProviderEndpointRequest, type IContractProviderRouter, type IContractProviderRouterOptions, } from "./contract-provider-router";
3
4
  export { ContractProviders, ContractProvidersTable, contractProvidersMetaData, contractProvidersSchema, type IContractProviderRecord, } from "./contract-providers.table";
4
- export { CONTRACT_CALL_RPC, type ContractMemberType, type ContractNotificationSink, type ContractPermissionCheck, createContractConsumer, createContractProvider, createContractProviderEndpoint, createContractProviderSession, createRemoteContractConsumer, type IContractCall, type IContractCallContext, type IContractConsumer, type IContractConsumerBase, type IContractNotification, type IContractProviderEndpoint, type IContractProviderEndpointOptions, type IContractProviderSession, type IContractProviderSessionOptions, type IContractResolution, type IContractTableProxy, type IContractToolContext, type ITableProxy, sameUserContractPermissionCheck, } from "./contract-proxy";
5
+ export { authorizedContractActionNames, CONTRACT_CALL_RPC, type ContractMemberType, type ContractNotificationSink, type ContractPermissionCheck, type ContractToolDispatch, createContractConsumer, createContractProvider, createContractProviderEndpoint, createContractProviderSession, createRemoteContractConsumer, type IContractCall, type IContractCallContext, type IContractConsumer, type IContractConsumerBase, type IContractNotification, type IContractProviderEndpoint, type IContractProviderEndpointOptions, type IContractProviderSession, type IContractProviderSessionOptions, type IContractResolution, type IContractTableProxy, type IContractToolContext, type IContractToolTarget, type ITableProxy, sameUserContractPermissionCheck, validateContractActions, } from "./contract-proxy";
5
6
  export { authorizeRemoteContractCall, type ContractRemoteIdentity, type ContractResolver, createLocalUserContextContractProviderRouter, createUserContextContractProviderRouter, getContractResolver, handleContractCall, type IContractResolverRegistrationOptions, type ILocalContractVariableRequest, isSelfTrustedContractCaller, type LocalContractVariableResolver, registerContractResolver, verifyRemoteContractIdentity, } from "./contract-resolvers";
6
7
  export { CONTRACT_NOTIFY_CHANNEL, CONTRACT_REQUEST_CHANNEL, connectionContractTransport, type IContractTransport, type IDuplexEmitter, inProcessTransportPair, } from "./contract-transport";
7
8
  export { Contracts, ContractsTable, contractsMetaData, contractsSchema, type IContractRecord, } from "./contracts.table";
@@ -14,8 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.DEVICE_OPERATIONS_CONTRACT_VERSION = exports.getContractCatalogDefinition = exports.contractCatalogProviderPackageId = exports.CONTRACT_CATALOG_VERSION = exports.setRemoteContractTransportFactory = exports.resolveRemoteTargetEndpoint = exports.getRemoteContractTransportFactory = exports.createRemoteContractEndpoint = exports.ContractRegistry = exports.PersistentContractRegistry = exports.waitForHostContractTransport = exports.subscribeHostContractTransport = exports.registerHostContractTransport = exports.getHostContractTransport = exports.hostContractConsumer = exports.setSchemaToFieldsFn = exports.extractToolShape = exports.extractTableShape = exports.createLocalContractConsumer = exports.contractsSchema = exports.contractsMetaData = exports.ContractsTable = exports.Contracts = exports.inProcessTransportPair = exports.connectionContractTransport = exports.CONTRACT_REQUEST_CHANNEL = exports.CONTRACT_NOTIFY_CHANNEL = exports.verifyRemoteContractIdentity = exports.registerContractResolver = exports.isSelfTrustedContractCaller = exports.handleContractCall = exports.getContractResolver = exports.createUserContextContractProviderRouter = exports.createLocalUserContextContractProviderRouter = exports.authorizeRemoteContractCall = exports.sameUserContractPermissionCheck = exports.createRemoteContractConsumer = exports.createContractProviderSession = exports.createContractProviderEndpoint = exports.createContractProvider = exports.createContractConsumer = exports.CONTRACT_CALL_RPC = exports.contractProvidersSchema = exports.contractProvidersMetaData = exports.ContractProvidersTable = exports.ContractProviders = exports.createContractProviderRouter = exports.PackageBuilder = exports.definePackage = exports.ContractBuilder = void 0;
18
- exports.validateProviderSatisfiesContract = exports.validateImmutability = exports.validateAlsoImplements = exports.contractKey = exports.registerSystemContract = exports.listSystemContracts = exports.installSystemContracts = exports.TOOL_ACCESS_CONTROL_CONTRACT_VERSION = exports.getToolAccessControlContractDefinition = exports.schedulerProviderPackageId = exports.SCHEDULER_MAX_DELAY_MS = exports.SCHEDULER_CONTRACT_VERSION = exports.getSchedulerContractDefinition = exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.localFoldersProviderPackageId = exports.LOCAL_FOLDERS_RESERVED_DIR = exports.LOCAL_FOLDERS_READ_RANGE_MAX = exports.LOCAL_FOLDERS_JOB_TTL_MS = exports.LOCAL_FOLDERS_HAVE_BATCH = exports.LOCAL_FOLDERS_GETBLOCKS_MAX_BYTES = exports.LOCAL_FOLDERS_GETBLOCKS_MAX_BLOCKS = exports.LOCAL_FOLDERS_CONTRACT_VERSION = exports.LOCAL_FOLDERS_CHUNK_MIN = exports.LOCAL_FOLDERS_CHUNK_MAX = exports.LOCAL_FOLDERS_CHUNK_AVG = exports.LOCAL_FOLDERS_ASSEMBLE_STALL_MS = exports.getLocalFoldersContractDefinition = exports.INVITES_CONTRACT_VERSION = exports.getInvitesContractDefinition = exports.IDENTITY_CONTRACT_VERSION = exports.getIdentityContractDefinition = exports.httpProviderPackageId = exports.HTTP_MAX_TIMEOUT_MS = exports.HTTP_MAX_BODY_BYTES = exports.HTTP_DEFAULT_TIMEOUT_MS = exports.HTTP_CONTRACT_VERSION = exports.getHttpContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = exports.DEVICE_OPERATIONS_MAX_TOOLS = exports.DEVICE_OPERATIONS_MAX_ROWS = exports.DEVICE_OPERATIONS_MAX_RESULT_BYTES = exports.DEVICE_OPERATIONS_MAX_QUERY_LENGTH = void 0;
17
+ exports.contractCatalogProviderPackageId = exports.CONTRACT_CATALOG_VERSION = exports.setRemoteContractTransportFactory = exports.resolveRemoteTargetEndpoint = exports.getRemoteContractTransportFactory = exports.createRemoteContractEndpoint = exports.ContractRegistry = exports.PersistentContractRegistry = exports.waitForHostContractTransport = exports.subscribeHostContractTransport = exports.registerHostContractTransport = exports.getHostContractTransport = exports.hostContractConsumer = exports.setSchemaToFieldsFn = exports.extractToolShape = exports.extractTableShape = exports.createLocalContractConsumer = exports.contractsSchema = exports.contractsMetaData = exports.ContractsTable = exports.Contracts = exports.inProcessTransportPair = exports.connectionContractTransport = exports.CONTRACT_REQUEST_CHANNEL = exports.CONTRACT_NOTIFY_CHANNEL = exports.verifyRemoteContractIdentity = exports.registerContractResolver = exports.isSelfTrustedContractCaller = exports.handleContractCall = exports.getContractResolver = exports.createUserContextContractProviderRouter = exports.createLocalUserContextContractProviderRouter = exports.authorizeRemoteContractCall = exports.validateContractActions = exports.sameUserContractPermissionCheck = exports.createRemoteContractConsumer = exports.createContractProviderSession = exports.createContractProviderEndpoint = exports.createContractProvider = exports.createContractConsumer = exports.CONTRACT_CALL_RPC = exports.authorizedContractActionNames = exports.contractProvidersSchema = exports.contractProvidersMetaData = exports.ContractProvidersTable = exports.ContractProviders = exports.createContractProviderRouter = exports.PackageBuilder = exports.definePackage = exports.ContractBuilder = void 0;
18
+ exports.validateProviderSatisfiesContract = exports.validateImmutability = exports.validateAlsoImplements = exports.contractKey = exports.registerSystemContract = exports.listSystemContracts = exports.installSystemContracts = exports.TOOL_ACCESS_CONTROL_CONTRACT_VERSION = exports.getToolAccessControlContractDefinition = exports.schedulerProviderPackageId = exports.SCHEDULER_MAX_DELAY_MS = exports.SCHEDULER_CONTRACT_VERSION = exports.getSchedulerContractDefinition = exports.resolveLogsContract = exports.LOGS_CONTRACT_VERSION = exports.getLogsContractDefinition = exports.localFoldersProviderPackageId = exports.LOCAL_FOLDERS_RESERVED_DIR = exports.LOCAL_FOLDERS_READ_RANGE_MAX = exports.LOCAL_FOLDERS_JOB_TTL_MS = exports.LOCAL_FOLDERS_HAVE_BATCH = exports.LOCAL_FOLDERS_GETBLOCKS_MAX_BYTES = exports.LOCAL_FOLDERS_GETBLOCKS_MAX_BLOCKS = exports.LOCAL_FOLDERS_CONTRACT_VERSION = exports.LOCAL_FOLDERS_CHUNK_MIN = exports.LOCAL_FOLDERS_CHUNK_MAX = exports.LOCAL_FOLDERS_CHUNK_AVG = exports.LOCAL_FOLDERS_ASSEMBLE_STALL_MS = exports.getLocalFoldersContractDefinition = exports.INVITES_CONTRACT_VERSION = exports.getInvitesContractDefinition = exports.IDENTITY_CONTRACT_VERSION = exports.getIdentityContractDefinition = exports.httpProviderPackageId = exports.HTTP_MAX_TIMEOUT_MS = exports.HTTP_MAX_BODY_BYTES = exports.HTTP_DEFAULT_TIMEOUT_MS = exports.HTTP_CONTRACT_VERSION = exports.getHttpContractDefinition = exports.getDeviceOperationsContractDefinition = exports.deviceOperationsToolIds = exports.deviceOperationsProviderPackageId = exports.DEVICE_OPERATIONS_MAX_TOOLS = exports.DEVICE_OPERATIONS_MAX_ROWS = exports.DEVICE_OPERATIONS_MAX_RESULT_BYTES = exports.DEVICE_OPERATIONS_MAX_QUERY_LENGTH = exports.DEVICE_OPERATIONS_CONTRACT_VERSION = exports.getContractCatalogDefinition = void 0;
19
+ __exportStar(require("./action-dispatch"), exports);
19
20
  var builder_1 = require("./builder");
20
21
  Object.defineProperty(exports, "ContractBuilder", { enumerable: true, get: function () { return builder_1.ContractBuilder; } });
21
22
  Object.defineProperty(exports, "definePackage", { enumerable: true, get: function () { return builder_1.definePackage; } });
@@ -28,6 +29,7 @@ Object.defineProperty(exports, "ContractProvidersTable", { enumerable: true, get
28
29
  Object.defineProperty(exports, "contractProvidersMetaData", { enumerable: true, get: function () { return contract_providers_table_1.contractProvidersMetaData; } });
29
30
  Object.defineProperty(exports, "contractProvidersSchema", { enumerable: true, get: function () { return contract_providers_table_1.contractProvidersSchema; } });
30
31
  var contract_proxy_1 = require("./contract-proxy");
32
+ Object.defineProperty(exports, "authorizedContractActionNames", { enumerable: true, get: function () { return contract_proxy_1.authorizedContractActionNames; } });
31
33
  Object.defineProperty(exports, "CONTRACT_CALL_RPC", { enumerable: true, get: function () { return contract_proxy_1.CONTRACT_CALL_RPC; } });
32
34
  Object.defineProperty(exports, "createContractConsumer", { enumerable: true, get: function () { return contract_proxy_1.createContractConsumer; } });
33
35
  Object.defineProperty(exports, "createContractProvider", { enumerable: true, get: function () { return contract_proxy_1.createContractProvider; } });
@@ -35,6 +37,7 @@ Object.defineProperty(exports, "createContractProviderEndpoint", { enumerable: t
35
37
  Object.defineProperty(exports, "createContractProviderSession", { enumerable: true, get: function () { return contract_proxy_1.createContractProviderSession; } });
36
38
  Object.defineProperty(exports, "createRemoteContractConsumer", { enumerable: true, get: function () { return contract_proxy_1.createRemoteContractConsumer; } });
37
39
  Object.defineProperty(exports, "sameUserContractPermissionCheck", { enumerable: true, get: function () { return contract_proxy_1.sameUserContractPermissionCheck; } });
40
+ Object.defineProperty(exports, "validateContractActions", { enumerable: true, get: function () { return contract_proxy_1.validateContractActions; } });
38
41
  var contract_resolvers_1 = require("./contract-resolvers");
39
42
  Object.defineProperty(exports, "authorizeRemoteContractCall", { enumerable: true, get: function () { return contract_resolvers_1.authorizeRemoteContractCall; } });
40
43
  Object.defineProperty(exports, "createLocalUserContextContractProviderRouter", { enumerable: true, get: function () { return contract_resolvers_1.createLocalUserContextContractProviderRouter; } });
@@ -11,6 +11,8 @@ export interface IContractProviderInfo {
11
11
  name: string;
12
12
  /** True when this package is the active provider for the contract version. */
13
13
  active: boolean;
14
+ /** Executable package selectors for this trusted turn. Missing metadata grants no actions. */
15
+ authorizedActions?: string[];
14
16
  }
15
17
  /** Input for listing providers of one contract version. */
16
18
  export interface IListContractProvidersInput {
@@ -18,8 +18,8 @@ export declare const messageSchema: z.ZodObject<{
18
18
  channelId: string;
19
19
  messageId: string;
20
20
  assistantId?: string | undefined;
21
- vars?: z.objectOutputType<{}, z.ZodAny, "strip"> | undefined;
22
21
  messageParentId?: string | undefined;
22
+ vars?: z.objectOutputType<{}, z.ZodAny, "strip"> | undefined;
23
23
  editedAt?: Date | undefined;
24
24
  fileIds?: string[] | undefined;
25
25
  }, {
@@ -29,8 +29,8 @@ export declare const messageSchema: z.ZodObject<{
29
29
  channelId: string;
30
30
  messageId: string;
31
31
  assistantId?: string | undefined;
32
- vars?: z.objectInputType<{}, z.ZodAny, "strip"> | undefined;
33
32
  messageParentId?: string | undefined;
33
+ vars?: z.objectInputType<{}, z.ZodAny, "strip"> | undefined;
34
34
  editedAt?: Date | undefined;
35
35
  fileIds?: string[] | undefined;
36
36
  }>;
@@ -42,8 +42,8 @@ export declare function Messages(dataContext?: DataContext): import("..").Table<
42
42
  channelId: string;
43
43
  messageId: string;
44
44
  assistantId?: string | undefined;
45
- vars?: z.objectOutputType<{}, z.ZodAny, "strip"> | undefined;
46
45
  messageParentId?: string | undefined;
46
+ vars?: z.objectOutputType<{}, z.ZodAny, "strip"> | undefined;
47
47
  editedAt?: Date | undefined;
48
48
  fileIds?: string[] | undefined;
49
49
  }>;
@@ -66,17 +66,17 @@ declare const schema: z.ZodObject<{
66
66
  signature: string;
67
67
  by: string;
68
68
  }[] | undefined;
69
- versionTag?: string | undefined;
70
- routesBundleFileId?: string | undefined;
71
- routesBundleFileHash?: string | undefined;
72
- uiBundleFileId?: string | undefined;
73
- uiBundleFileHash?: string | undefined;
74
69
  appNavs?: {
75
70
  name: string;
76
71
  iconClassName: string;
77
72
  navigationPath: string;
78
73
  displayName?: string | undefined;
79
74
  }[] | undefined;
75
+ versionTag?: string | undefined;
76
+ routesBundleFileId?: string | undefined;
77
+ routesBundleFileHash?: string | undefined;
78
+ uiBundleFileId?: string | undefined;
79
+ uiBundleFileHash?: string | undefined;
80
80
  packageAuthorSignature?: string | undefined;
81
81
  }, {
82
82
  version: string;
@@ -94,17 +94,17 @@ declare const schema: z.ZodObject<{
94
94
  signature: string;
95
95
  by: string;
96
96
  }[] | undefined;
97
- versionTag?: string | undefined;
98
- routesBundleFileId?: string | undefined;
99
- routesBundleFileHash?: string | undefined;
100
- uiBundleFileId?: string | undefined;
101
- uiBundleFileHash?: string | undefined;
102
97
  appNavs?: {
103
98
  name: string;
104
99
  iconClassName: string;
105
100
  navigationPath: string;
106
101
  displayName?: string | undefined;
107
102
  }[] | undefined;
103
+ versionTag?: string | undefined;
104
+ routesBundleFileId?: string | undefined;
105
+ routesBundleFileHash?: string | undefined;
106
+ uiBundleFileId?: string | undefined;
107
+ uiBundleFileHash?: string | undefined;
108
108
  packageAuthorSignature?: string | undefined;
109
109
  }>;
110
110
  export type IPackageVersion = z.infer<typeof schema>;
@@ -65,12 +65,14 @@ export declare function hashToolArgs(args: Record<string, unknown> | undefined):
65
65
  */
66
66
  export declare function annotateToolAccessDescription(usageDescription: string, accessLevel: unknown): string;
67
67
  /**
68
- * Return the fail-closed access level for a record that may omit the field.
68
+ * Resolve admission from record metadata. Omitted preservation-request tools enter at None;
69
+ * ordinary tools and Assistants retain the fail-closed Self default.
69
70
  *
70
71
  * @param record - Tool or Assistant-like object.
71
72
  */
72
73
  export declare function recordAccessLevel(record: {
73
74
  accessLevel?: unknown;
75
+ authorityPropagation?: unknown;
74
76
  } | undefined): number;
75
77
  /**
76
78
  * Choose the delegated Assistant ceiling for a run.
@@ -105,13 +105,16 @@ function annotateToolAccessDescription(usageDescription, accessLevel) {
105
105
  return `${usageDescription}\n\n${annotation}`;
106
106
  }
107
107
  /**
108
- * Return the fail-closed access level for a record that may omit the field.
108
+ * Resolve admission from record metadata. Omitted preservation-request tools enter at None;
109
+ * ordinary tools and Assistants retain the fail-closed Self default.
109
110
  *
110
111
  * @param record - Tool or Assistant-like object.
111
112
  */
112
113
  function recordAccessLevel(record) {
113
114
  return record?.accessLevel == null
114
- ? access_level_1.DEFAULT_ACCESS_LEVEL
115
+ ? record?.authorityPropagation === "preserve"
116
+ ? access_level_1.AccessLevel.None
117
+ : access_level_1.DEFAULT_ACCESS_LEVEL
115
118
  : (0, access_level_1.resolveAccessLevel)(record.accessLevel);
116
119
  }
117
120
  /**
@@ -59,6 +59,13 @@ describe("annotateToolAccessDescription", () => {
59
59
  expect((0, tool_access_1.annotateToolAccessDescription)(once, 40)).toBe(once);
60
60
  });
61
61
  });
62
+ test("legacy host admission and descriptions use the preservation request, not a grant", () => {
63
+ const tool = { authorityPropagation: "preserve" };
64
+ expect((0, tool_access_1.recordAccessLevel)(tool)).toBe(0);
65
+ expect((0, tool_access_1.annotateToolAccessDescription)("route", (0, tool_access_1.recordAccessLevel)(tool))).toContain("None (0)");
66
+ expect((0, tool_access_1.recordAccessLevel)({})).toBe(100);
67
+ expect((0, tool_access_1.recordAccessLevel)({ ...tool, accessLevel: 40 })).toBe(40);
68
+ });
62
69
  describe("recordAccessLevel", () => {
63
70
  it("defaults missing records to 100", () => {
64
71
  expect((0, tool_access_1.recordAccessLevel)(undefined)).toBe(100);
@@ -219,7 +219,8 @@ export declare const toolSchema: z.ZodObject<{
219
219
  codeRepository: z.ZodOptional<z.ZodString>;
220
220
  isAssistantRunner: z.ZodOptional<z.ZodBoolean>;
221
221
  packageId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
222
- accessLevel: z.ZodDefault<z.ZodNumber>;
222
+ authorityPropagation: z.ZodOptional<z.ZodEnum<["cap", "preserve"]>>;
223
+ accessLevel: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
223
224
  remoteAccessLevel: z.ZodOptional<z.ZodNumber>;
224
225
  }, "strip", z.ZodTypeAny, {
225
226
  code: string;
@@ -250,7 +251,6 @@ export declare const toolSchema: z.ZodObject<{
250
251
  subType?: string | undefined;
251
252
  }[];
252
253
  };
253
- accessLevel: number;
254
254
  detailedDescription?: string | undefined;
255
255
  configSchema?: {
256
256
  type: IOSchemaType;
@@ -267,6 +267,8 @@ export declare const toolSchema: z.ZodObject<{
267
267
  codeRepository?: string | undefined;
268
268
  isAssistantRunner?: boolean | undefined;
269
269
  packageId?: string | undefined;
270
+ authorityPropagation?: "preserve" | "cap" | undefined;
271
+ accessLevel?: number | undefined;
270
272
  remoteAccessLevel?: number | undefined;
271
273
  }, {
272
274
  name: string;
@@ -313,6 +315,7 @@ export declare const toolSchema: z.ZodObject<{
313
315
  codeRepository?: string | undefined;
314
316
  isAssistantRunner?: boolean | undefined;
315
317
  packageId?: string | undefined;
318
+ authorityPropagation?: "preserve" | "cap" | undefined;
316
319
  accessLevel?: number | undefined;
317
320
  remoteAccessLevel?: number | undefined;
318
321
  }>;
@@ -359,7 +362,6 @@ export declare function Tools(dataContext?: DataContext): import("..").Table<{
359
362
  subType?: string | undefined;
360
363
  }[];
361
364
  };
362
- accessLevel: number;
363
365
  detailedDescription?: string | undefined;
364
366
  configSchema?: {
365
367
  type: IOSchemaType;
@@ -376,5 +378,7 @@ export declare function Tools(dataContext?: DataContext): import("..").Table<{
376
378
  codeRepository?: string | undefined;
377
379
  isAssistantRunner?: boolean | undefined;
378
380
  packageId?: string | undefined;
381
+ authorityPropagation?: "preserve" | "cap" | undefined;
382
+ accessLevel?: number | undefined;
379
383
  remoteAccessLevel?: number | undefined;
380
384
  }>;
@@ -48,7 +48,13 @@ exports.toolSchema = zod_1.z.object({
48
48
  .optional()
49
49
  .describe("Whether this tool is a model that can be used to run an assistant"),
50
50
  packageId: zod_types_1.zodPeerId.optional().describe("The package that installed this tool, if any"),
51
- accessLevel: access_level_1.accessLevelSchema.describe("Required access level (0-100) to run this tool. Unclassified tools default to 100 (Self)."),
51
+ authorityPropagation: zod_1.z
52
+ .enum(["cap", "preserve"])
53
+ .optional()
54
+ .describe("Declared outgoing authority behavior in strict dispatch. 'cap' (default) includes this tool's level in the outgoing ceiling; 'preserve' omits it and passes the caller's authority through."),
55
+ accessLevel: access_level_1.accessLevelSchema
56
+ .optional()
57
+ .describe("Admission level (0-100). Omitted 'preserve' tools enter at None (0); other omitted tools require Self (100)."),
52
58
  remoteAccessLevel: zod_1.z
53
59
  .number()
54
60
  .int()
@@ -1704,16 +1704,16 @@ export declare const inviteEnvelopeSchema: z.ZodObject<{
1704
1704
  fromPublicKey: string;
1705
1705
  }>;
1706
1706
  }, "strict", z.ZodTypeAny, {
1707
- v: 1;
1708
1707
  to: string;
1708
+ v: 1;
1709
1709
  box: {
1710
1710
  nonce: string;
1711
1711
  contents: string;
1712
1712
  fromPublicKey: string;
1713
1713
  };
1714
1714
  }, {
1715
- v: 1;
1716
1715
  to: string;
1716
+ v: 1;
1717
1717
  box: {
1718
1718
  nonce: string;
1719
1719
  contents: string;