SharedOS API v0.1.0-alpha.5


SharedOS API / @aicoo/sharedos-core

@aicoo/sharedos-core

The deny-by-default SharedOS authorization and dispatch kernel.

npm install @aicoo/sharedos-core@next

The kernel filters tool discovery, re-authorizes exact invocations, binds resource ownership, and emits structured audit events. Embedded hosts must construct access contexts from authenticated identity and trusted grant state.

Tool use requires registration, namespace enablement, and capability authority. Static handlers use ToolRegistry; user-specific MCP catalogs use ContextToolProvider. A host implements ToolNamespaceSettingsStore for atomic, durable namespace updates while keeping its database and product policy.

SharedOS is currently an 0.x prerelease.

Classes

CapabilityAuthorizer

Defined in: packages/core/src/authorization.ts:330

Constructors

Constructor

new CapabilityAuthorizer(options?): CapabilityAuthorizer

Defined in: packages/core/src/authorization.ts:338

Parameters
ParameterType
optionsCapabilityAuthorizerOptions
Returns

CapabilityAuthorizer

Accessors

hasHostCeiling
Get Signature

get hasHostCeiling(): boolean

Defined in: packages/core/src/authorization.ts:355

Whether a host ceiling is installed.

Read by the kernel so authority.resolved can say so. Without it, an audit stream containing no host_policy_denied is ambiguous between a deployment with no policy port and one whose port never fired, and that ambiguity is the difference between a count and a guess (ADR 0020).

Returns

boolean

Methods

authorize()

authorize(authority, request, options?): Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

Defined in: packages/core/src/authorization.ts:359

Parameters
ParameterType
authorityResolvedAuthority
requestAuthorizationRequest
optionsAuthorizeOptions
Returns

Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

canDiscover()

canDiscover(authority, ceiling, options?): Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

Defined in: packages/core/src/authorization.ts:382

Non-consuming catalog check. A narrow grant can discover a tool whose declared resource is a broader ceiling; invocation still checks the exact argument-selected resource.

Parameters
ParameterType
authorityResolvedAuthority
ceilingAuthorizationRequest
optionsAuthorizationInstantOptions
Returns

Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

reach()

reach(authority, options?): Promise<{ reach: object[]; status: "computed"; } | { reasonCode: "authority_unavailable" | "usage_store_unavailable"; status: "unavailable"; }>

Defined in: packages/core/src/authorization.ts:436

The reachable surface an authority describes, with the authority removed.

Answers "where may this actor look" without disclosing who allowed it, for how long, or how much budget is left. Only grants that would authorize something at this instant contribute: an expired, revoked, wrong-purpose, wrong-subject, unverified or chain-broken grant is not reach, and neither is a bounded grant whose budget is spent -- advertising a door that is already closed is worse than not advertising it.

Nothing is consumed. Asking is not opening, so reading reach never spends a bounded grant. A usage store that cannot be read makes the whole answer unavailable rather than the reach narrower: a surface that silently omits a live grant because a dependency is down looks exactly like one that is true, and the reader has no way to tell (ADR 0021).

This is descriptive, never permissive. Every operation is authorized independently afterwards, which is what makes an over-wide entry harmless and what makes reach safe to put in front of a model. The host ceiling is deliberately not consulted: a descendants entry is not one request, so a per-entry verdict would be neither sound nor complete, and a ceiling that refuses still refuses at the operation.

Entries are deduplicated and canonically ordered, so the same authority produces the same reach however the store happened to order its grants.

Only usage_store_unavailable is emitted here; SharedOSKernel.reach adds authority_unavailable when the authority itself could not be loaded.

See ADR 0021, which reads this for a subject by deriving a context from the reader's own, and SharedOSKernel.reach, which reads it for the turn's own scope.

Parameters
ParameterType
authorityResolvedAuthority
optionsAuthorizationInstantOptions
Returns

Promise<{ reach: object[]; status: "computed"; } | { reasonCode: "authority_unavailable" | "usage_store_unavailable"; status: "unavailable"; }>


CompositeAuditSink

Defined in: packages/core/src/audit.ts:114

Implements

Constructors

Constructor

new CompositeAuditSink(sinks): CompositeAuditSink

Defined in: packages/core/src/audit.ts:117

Parameters
ParameterType
sinksreadonly AuditSink[]
Returns

CompositeAuditSink

Methods

record()

record(event): Promise<void>>

Defined in: packages/core/src/audit.ts:121

Parameters
ParameterType
eventAuditEvent
Returns

Promise<void>

Implementation of

AuditSink.record


DuplicateRegistrationError

Defined in: packages/core/src/errors.ts:1

Extends

  • Error

Constructors

Constructor

new DuplicateRegistrationError(kind, identifier): DuplicateRegistrationError

Defined in: packages/core/src/errors.ts:4

Parameters
ParameterType
kind"tool" | "resource namespace" | "tool provider" | "tool namespace settings"
identifierstring
Returns

DuplicateRegistrationError

Overrides

Error.constructor

Properties

PropertyModifierTypeDefault valueDescriptionOverridesInherited fromDefined in
<a id="property-cause"></a> cause?publicunknownundefined--Error.causenode_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26
<a id="property-message"></a> messagepublicstringundefined--Error.messagenode_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077
<a id="property-name"></a> namereadonly"DuplicateRegistrationError""DuplicateRegistrationError"-Error.name-packages/core/src/errors.ts:2
<a id="property-stack"></a> stack?publicstringundefined--Error.stacknode_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078
<a id="property-stacktracelimit"></a> stackTraceLimitstaticnumberundefinedThe Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames.-Error.stackTraceLimitnode_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68

Methods

captureStackTrace()

static captureStackTrace(targetObject, constructorOpt?): void

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:52

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack; // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters
ParameterType
targetObjectobject
constructorOpt?Function
Returns

void

Inherited from

Error.captureStackTrace

prepareStackTrace()

static prepareStackTrace(err, stackTraces): any

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56

Parameters
ParameterType
errError
stackTracesCallSite[]
Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from

Error.prepareStackTrace


InMemoryGrantUsageStore

Defined in: packages/core/src/authorization.ts:306

An atomic, process-local usage store suitable for tests and single-process hosts. Distributed hosts should inject a durable compare-and-set store.

Implements

Constructors

Constructor

new InMemoryGrantUsageStore(): InMemoryGrantUsageStore

Returns

InMemoryGrantUsageStore

Methods

getUsage()

getUsage(namespaceId, grantId): Promise<number>>

Defined in: packages/core/src/authorization.ts:309

Parameters
ParameterType
namespaceIdstring
grantIdstring
Returns

Promise<number>

Implementation of

GrantUsageStore.getUsage

tryConsume()

tryConsume(namespaceId, grantId, maximumUses): Promise<boolean>>

Defined in: packages/core/src/authorization.ts:313

Parameters
ParameterType
namespaceIdstring
grantIdstring
maximumUsesnumber
Returns

Promise<boolean>

Implementation of

GrantUsageStore.tryConsume


MissingRegistrationError

Defined in: packages/core/src/errors.ts:12

Extends

  • Error

Constructors

Constructor

new MissingRegistrationError(kind, identifier): MissingRegistrationError

Defined in: packages/core/src/errors.ts:15

Parameters
ParameterType
kind"tool" | "resource namespace" | "tool provider" | "tool namespace settings"
identifierstring
Returns

MissingRegistrationError

Overrides

Error.constructor

Properties

PropertyModifierTypeDefault valueDescriptionOverridesInherited fromDefined in
<a id="property-cause-1"></a> cause?publicunknownundefined--Error.causenode_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26
<a id="property-message-1"></a> messagepublicstringundefined--Error.messagenode_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077
<a id="property-name-1"></a> namereadonly"MissingRegistrationError""MissingRegistrationError"-Error.name-packages/core/src/errors.ts:13
<a id="property-stack-1"></a> stack?publicstringundefined--Error.stacknode_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078
<a id="property-stacktracelimit-1"></a> stackTraceLimitstaticnumberundefinedThe Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)). The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames.-Error.stackTraceLimitnode_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68

Methods

captureStackTrace()

static captureStackTrace(targetObject, constructorOpt?): void

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:52

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack; // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters
ParameterType
targetObjectobject
constructorOpt?Function
Returns

void

Inherited from

Error.captureStackTrace

prepareStackTrace()

static prepareStackTrace(err, stackTraces): any

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56

Parameters
ParameterType
errError
stackTracesCallSite[]
Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from

Error.prepareStackTrace


NoopAuditSink

Defined in: packages/core/src/audit.ts:108

Implements

Constructors

Constructor

new NoopAuditSink(): NoopAuditSink

Returns

NoopAuditSink

Methods

record()

record(_event): Promise<void>>

Defined in: packages/core/src/audit.ts:109

Parameters
ParameterType
_eventAuditEvent
Returns

Promise<void>

Implementation of

AuditSink.record


RecipientScopedMessageCapabilityResolver

Defined in: packages/core/src/message-service.ts:52

Implements

Constructors

Constructor

new RecipientScopedMessageCapabilityResolver(namespace?): RecipientScopedMessageCapabilityResolver

Defined in: packages/core/src/message-service.ts:55

Parameters
ParameterTypeDefault value
namespacestringMESSAGING_NAMESPACE
Returns

RecipientScopedMessageCapabilityResolver

Methods

resolve()

resolve(context, envelope): AuthorizationRequest

Defined in: packages/core/src/message-service.ts:59

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
envelope{ createdAt: string; id: string; payload: JsonValue; provenance?: { metadata?: JsonObject; parentIds: string[]; source: string; }; purpose: string; receiver: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; replyTo?: string; sender: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; traceId: string; version: "1"; }
envelope.createdAtstring
envelope.idstring
envelope.payloadJsonValue
envelope.provenance?{ metadata?: JsonObject; parentIds: string[]; source: string; }
envelope.provenance.metadata?JsonObject
envelope.provenance.parentIdsstring[]
envelope.provenance.sourcestring
envelope.purposestring
envelope.receiver{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.replyTo?string
envelope.sender{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.traceIdstring
envelope.version"1"
Returns

AuthorizationRequest

Implementation of

MessageCapabilityResolver.resolve


ResourceProviderRegistry

Defined in: packages/core/src/resource-registry.ts:23

Constructors

Constructor

new ResourceProviderRegistry(): ResourceProviderRegistry

Returns

ResourceProviderRegistry

Methods

get()

get(namespace): ResourceProvider | undefined

Defined in: packages/core/src/resource-registry.ts:37

Parameters
ParameterType
namespacestring
Returns

ResourceProvider | undefined

has()

has(namespace): boolean

Defined in: packages/core/src/resource-registry.ts:41

Parameters
ParameterType
namespacestring
Returns

boolean

namespaces()

namespaces(): readonly string[]

Defined in: packages/core/src/resource-registry.ts:45

Returns

readonly string[]

register()

register(provider): void

Defined in: packages/core/src/resource-registry.ts:26

Parameters
ParameterType
providerResourceProvider
Returns

void


SharedOSKernel

Defined in: packages/core/src/kernel.ts:292

Host-neutral facade for every permission-controlled SharedOS operation. AccessContext is a trusted host-created boundary; never construct it from an unverified request body.

Constructors

Constructor

new SharedOSKernel(options): SharedOSKernel

Defined in: packages/core/src/kernel.ts:311

Parameters
ParameterType
optionsSharedOSKernelOptions
Returns

SharedOSKernel

Methods

admitTurn()

admitTurn(context, agent, options?): Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

Defined in: packages/core/src/kernel.ts:425

Consume permission to invoke exactly one target agent turn.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
agent{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
optionsKernelOperationOptions
Returns

Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

authorize()

authorize(context, request, options?): Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

Defined in: packages/core/src/kernel.ts:409

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
requestAuthorizationRequest
optionsKernelOperationOptions
Returns

Promise<{ allowed: boolean; matchedGrantId?: string; metadata?: JsonObject; reasonCode: string; requiredAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; }>

invokeResource()

invokeResource(context, request, options?): Promise<{ completedAt: string; metadata?: JsonObject; operationId: string; output: JsonValue; status: "succeeded"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "denied"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "failed"; }>

Defined in: packages/core/src/kernel.ts:1254

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
requestResourceInvocationRequest
optionsKernelOperationOptions
Returns

Promise<{ completedAt: string; metadata?: JsonObject; operationId: string; output: JsonValue; status: "succeeded"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "denied"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "failed"; }>

invokeTool()

invokeTool(context, call, options?): Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

Defined in: packages/core/src/kernel.ts:956

Re-authorize and dispatch one tool call.

The span around it is the kernel's whole share of one mediated call, and it contains the provider's own work, which is not enforcement. That part is named separately as SPAN.TOOL_HANDLER and carries the same call id, so a report subtracts it rather than attributing the host's storage to SharedOS. Both spans exist or neither does.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
call{ arguments: JsonObject; id: string; requestedAt: string; tool: string; traceId: string; }
call.argumentsJsonObject
call.idstring
call.requestedAtstring
call.toolstring
call.traceIdstring
optionsKernelOperationOptions
Returns

Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

listPublishedTools()

listPublishedTools(context, options): Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

Defined in: packages/core/src/kernel.ts:868

The effective catalogue as an external harness receives it.

listTools answers with SharedOS registrations, which carry the capability each tool would require. That is the right answer inside the host and the wrong thing to put on a wire, so everything crossing the MCP boundary goes through this instead: the same permission-filtered set, projected to what a model is allowed to see, in canonical order, with the hash that identifies it.

A context whose authority could not be loaded receives an empty catalogue and a hash over nothing, exactly as listTools returns no tools -- fail-closed, and still a well-formed catalogue rather than an error the harness would have to interpret.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
optionsKernelOperationOptions & object
Returns

Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

listToolNamespaces()

listToolNamespaces(context, options?): Promise<{ namespaces: object[]; summary: { disabled: number; enabled: number; total: number; }; }>

Defined in: packages/core/src/kernel.ts:876

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
optionsKernelOperationOptions
Returns

Promise<{ namespaces: object[]; summary: { disabled: number; enabled: number; total: number; }; }>

listTools()

listTools(context, options?): Promise<readonly object[]>

Defined in: packages/core/src/kernel.ts:761

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
optionsKernelOperationOptions
Returns

Promise<readonly object[]>

openTurnAuthority()

openTurnAuthority(context, options?): Promise<TurnAuthorityScope>>

Defined in: packages/core/src/kernel.ts:373

Resolve the authority one turn will be decided against, and hold it.

A turn must decide against a single authority state. This loads that state once, at the turn boundary, and every kernel operation presenting the same turn identity is then answered from it -- including operations a tool handler makes back into the kernel, which never receive a handle and would otherwise re-read the store.

An unavailable source is held too, so a turn that could not establish authority stays fail-closed for its whole length instead of retrying the store on every call and possibly changing its mind.

Callers must close the returned scope on every exit path. Hosts that call kernel operations outside any turn need not open one: an operation with no lease resolves its own authority, which is a turn of one operation.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
optionsKernelOperationOptions
Returns

Promise<TurnAuthorityScope>

reach()

reach(context, options?): Promise<{ reach: object[]; status: "computed"; } | { reasonCode: "authority_unavailable" | "usage_store_unavailable"; status: "unavailable"; }>

Defined in: packages/core/src/kernel.ts:751

Where this actor may operate, with the authority stripped out.

The turn's own reach: namespace, path, actions and scope from the grants that would authorize something at this instant, and nothing about who granted them, for how long, or how many uses remain. A runtime is handed it as RuntimeVisibleContext.reach, so a model can be told where to look without the host reading raw grants to write a prompt -- at exactly the boundary designed to keep grants away from the model. The card in readAgentCard is this same derivation pointed at somebody else.

Grant reach, over the whole world this context names. The host ceiling is not consulted, for the reason ADR 0021 gives, and enabledToolNamespaces is not applied here: the resource plane is not gated by tool namespaces, so an actor may reach through invokeResource what no enabled tool offers. A caller acting only through tools narrows to its catalogue with reachThroughTools, which is what the execution envelope does for a turn.

Non-consuming, and never a substitute for authorization: an over-wide entry is harmless because every operation is decided independently afterwards.

Fails whole rather than narrow. Authority that cannot be loaded and a bounded budget that cannot be read both answer unavailable, under the code the decide path fails closed with, because a reach that quietly omitted a live grant would be indistinguishable from one that is true. The authority load records itself; a turn that ends on an unavailable reach is recorded by the envelope as the turn's terminal.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
optionsKernelOperationOptions
Returns

Promise<{ reach: object[]; status: "computed"; } | { reasonCode: "authority_unavailable" | "usage_store_unavailable"; status: "unavailable"; }>

readAgentCard()

readAgentCard(context, subject, options?): Promise<AgentCardRead>>

Defined in: packages/core/src/kernel.ts:624

The kernel's description of one agent: identity, computed reach, nothing else.

SharedOS can address an agent and can authorize one; this is how it describes one, so an agent asking a colleague's agent for something can find out what that agent may be asked for instead of learning it out of band. Reach is derived here, from the grants in force at this instant, and is never stored: a stored reach would keep advertising a revoked grant, and it is the one description of authority in SharedOS that nothing would invalidate.

Reading a card is itself authorized, over sharedos / ["directory", <subject>] / read. Without that gate the directory is an enumeration oracle: it would answer "does this agent exist" and, through reach, "what resources exist and where", in one call rather than one refusal at a time -- exactly the disclosure ADR 0012 and ADR 0019 decline to make. The gate is also what pays for the second authority load: nothing loads a subject's grants until a reader has been authorized to ask about that subject, and the identity view never loads them at all.

A card is a view rather than a record. A less-authorized reader is served a narrower card, built from the fields that view declares, and never a wider one with a redaction pass over it. See agentCardPath for how the views are addressed and ADR 0021 for why the coarse answer is its own view rather than a filter inside reach.

Nothing is consumed. Reading that a door exists is not opening it, for the same reason discovery does not spend a bounded grant.

The host's richer card composes around this one. Display names, avatars, skills and protocol bindings stay in the host: the test is not whether a field is useful but whether it is authority.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
optionsAgentCardReadOptions
Returns

Promise<AgentCardRead>

recordEscalation()

recordEscalation(context, reason, options?): Promise<{ reason: string; requestedAt: string; requestedAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; reviewer: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; status: "pending"; }>

Defined in: packages/core/src/kernel.ts:461

Record that a turn stopped and asked a human to decide.

This mints nothing and unblocks nothing. It writes one audit event and returns the stub the turn terminates with, so an escalation is visible in the same stream as the decisions around it rather than surviving only as runtime prose. The reviewer is the owner the turn already runs on behalf of; SharedOS has no review roster and does not invent one.

Resolving an escalation is host-owned control-plane work: it ends in a new grant issued to the trusted store, which the next turn loads. There is deliberately no path from here back into the running turn.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
reasonstring
optionsEscalationOptions
Returns

Promise<{ reason: string; requestedAt: string; requestedAuthority?: { capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }; reviewer: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; status: "pending"; }>

recordRefusedCall()

recordRefusedCall(context, call, options?): Promise<void>>

Defined in: packages/core/src/kernel.ts:567

Record a tool call the envelope refused before the kernel was asked.

A name the turn's catalogue never offered, a spent step budget, a spent tool-call budget. These are attempted violations -- the guessed tool name is the clearest one the system produces -- and they reached no audit sink at all, because the boundary that refused them does not own one.

Recorded as tool.invoked, because that is what it is: a tool call that was attempted and denied. metadata.source says envelope, which is the fact that stops being inferable the moment this method exists (ADR 0023).

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
callRefusedCall
optionsKernelOperationOptions
Returns

Promise<void>

recordTurnEnd()

recordTurnEnd(context, turn, options?): Promise<void>>

Defined in: packages/core/src/kernel.ts:531

Record how a turn ended, from the boundary that ended it.

The envelope owns turn termination and, until this existed, owned no audit at all: a turn that started, completed, failed, or was cancelled left nothing in the trail, so a host reading audit could not bound a turn or join a set of tool calls to the one that made them beyond traceId. It is called through the kernel rather than from an AuditSink of the envelope's own, because one sink passed in two places is one sink a host can forget to pass twice -- and the failure mode of forgetting is a turn that enforces correctly and records nothing (ADR 0023).

One event, at the terminal. Not five: a lifecycle event per transition would triple the audit volume of every successful turn to say nothing more, and a turn.denied would double-count against the authorization.checked admitTurn already produced for the same refusal.

A cancelled turn is recorded failed with reason turn_cancelled rather than gaining an AuditOutcome of its own. The outcome vocabulary is a compatibility surface every host persists against, and reason already separates a deadline from a defect.

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
turnTurnEndRecord
optionsKernelOperationOptions
Returns

Promise<void>

registerResourceProvider()

registerResourceProvider(provider): void

Defined in: packages/core/src/kernel.ts:337

Parameters
ParameterType
providerResourceProvider
Returns

void

registerTool()

registerTool(handler): void

Defined in: packages/core/src/kernel.ts:341

Parameters
ParameterType
handlerToolHandler
Returns

void

registerToolProvider()

registerToolProvider(provider): void

Defined in: packages/core/src/kernel.ts:345

Parameters
ParameterType
providerContextToolProvider
Returns

void

sendMessage()

sendMessage(context, envelope, options?): Promise<{ messageId: string; metadata?: JsonObject; status: "accepted"; timestamp: string; } | { messageId: string; metadata?: JsonObject; status: "delivered"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "denied"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "failed"; timestamp: string; }>

Defined in: packages/core/src/kernel.ts:1523

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
envelope{ createdAt: string; id: string; payload: JsonValue; provenance?: { metadata?: JsonObject; parentIds: string[]; source: string; }; purpose: string; receiver: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; replyTo?: string; sender: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; traceId: string; version: "1"; }
envelope.createdAtstring
envelope.idstring
envelope.payloadJsonValue
envelope.provenance?{ metadata?: JsonObject; parentIds: string[]; source: string; }
envelope.provenance.metadata?JsonObject
envelope.provenance.parentIdsstring[]
envelope.provenance.sourcestring
envelope.purposestring
envelope.receiver{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.replyTo?string
envelope.sender{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.traceIdstring
envelope.version"1"
optionsKernelOperationOptions
Returns

Promise<{ messageId: string; metadata?: JsonObject; status: "accepted"; timestamp: string; } | { messageId: string; metadata?: JsonObject; status: "delivered"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "denied"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "failed"; timestamp: string; }>

updateToolNamespaces()

updateToolNamespaces(context, update, options?): Promise<{ namespaces: object[]; summary: { disabled: number; enabled: number; total: number; }; }>

Defined in: packages/core/src/kernel.ts:899

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
update{ disable?: string[]; enable?: string[]; }
update.disable?string[]
update.enable?string[]
optionsKernelOperationOptions
Returns

Promise<{ namespaces: object[]; summary: { disabled: number; enabled: number; total: number; }; }>


ToolRegistry

Defined in: packages/core/src/tool-registry.ts:43

Constructors

Constructor

new ToolRegistry(): ToolRegistry

Returns

ToolRegistry

Methods

copy()

copy(): ToolRegistry

Defined in: packages/core/src/tool-registry.ts:117

A registry holding the same registrations as this one.

The entries are shared, not re-registered. Every one of them has already been contract-validated, cloned and deep-frozen by register, which also freezes the entry itself, so re-deriving one spends a schema parse and a JSON round trip to arrive at a value equal to the one already held. That was being paid on the path of every mediated call, where the kernel builds the effective catalogue by re-registering its whole static registry.

Copying keeps both properties the rebuild was relied on for: the copy carries the names, so registering a colliding one still raises DuplicateRegistrationError, and later registrations land on the copy alone -- a host registry is never mutated by the call that adds context-supplied tools beside it.

Returns

ToolRegistry

definitions()

definitions(): readonly object[]

Defined in: packages/core/src/tool-registry.ts:133

Returns

readonly object[]

get()

get(name): ToolHandler | undefined

Defined in: packages/core/src/tool-registry.ts:125

Parameters
ParameterType
namestring
Returns

ToolHandler | undefined

handlers()

handlers(): readonly ToolHandler[]

Defined in: packages/core/src/tool-registry.ts:139

Returns

readonly ToolHandler[]

has()

has(name): boolean

Defined in: packages/core/src/tool-registry.ts:129

Parameters
ParameterType
namestring
Returns

boolean

namespaceCatalog()

namespaceCatalog(enabledToolNamespaces): object

Defined in: packages/core/src/tool-registry.ts:145

Parameters
ParameterType
enabledToolNamespacesreadonly string[]
Returns

object

namespaces

namespaces: object[]

summary

summary: object

summary.disabled

disabled: number

summary.enabled

enabled: number

summary.total

total: number

register()

register(handler): void

Defined in: packages/core/src/tool-registry.ts:46

Parameters
ParameterType
handlerToolHandler
Returns

void


TrustedAuthorityResolver

Defined in: packages/core/src/authority.ts:245

Loads and validates authority for one access context.

Every failure mode collapses to unavailable, so a decision is never made against a partially trusted authority set.

Constructors

Constructor

new TrustedAuthorityResolver(source): TrustedAuthorityResolver

Defined in: packages/core/src/authority.ts:250

Parameters
ParameterType
sourceGrantSource
Returns

TrustedAuthorityResolver

Methods

resolve()

resolve(context, signal): Promise<AuthorityResolution>>

Defined in: packages/core/src/authority.ts:257

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
signalAbortSignal
Returns

Promise<AuthorityResolution>

Interfaces

AgentCardReadOptions

Defined in: packages/core/src/kernel.ts:221

Extends

Properties

PropertyModifierTypeDescriptionInherited fromDefined in
<a id="property-signal"></a> signal?readonlyAbortSignal-KernelOperationOptions.signalpackages/core/src/kernel.ts:156
<a id="property-view"></a> view?readonly"reach" | "identity" | "namespaces"The view to serve, defaulting to reach. reach is the default because a directory without reach is not the feature: an agent asking about a colleague's agent is asking what it can be asked for. A reader that holds only a narrower view is refused and told which views it may still ask for, rather than being quietly served a different card than the one it asked for.-packages/core/src/kernel.ts:231

AgentCardRefusal

Defined in: packages/core/src/agent-card.ts:211

A card read that was refused, and what the reader may still ask for.

reasonCode is the authorizer's own vocabulary and nothing new: a reader holding no directory grant is told no_matching_grant, exactly as it would be for a path that does not exist. That is the point -- an absent agent and an agent this reader may not ask about are refused identically, so the directory is not an existence oracle one refusal at a time either.

servableViews names only views this same reader is already authorized for, so it discloses nothing the reader did not hold. It exists so a reader holding a narrow view learns what it may still ask for instead of concluding the subject is unreachable.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-reasoncode"></a> reasonCodereadonlystring-packages/core/src/agent-card.ts:213
<a id="property-requiredauthority"></a> requiredAuthority?readonlyobjectPresent when the authorizer described the authority that would have served this view.packages/core/src/agent-card.ts:216
requiredAuthority.capabilitiespublicobject[]-packages/contracts/dist/capability.d.ts:511
requiredAuthority.constraints?publicobject-packages/contracts/dist/capability.d.ts:534
requiredAuthority.constraints.delegationDepth?publicnumber-packages/contracts/dist/capability.d.ts:539
requiredAuthority.constraints.expiresAt?publicstring-packages/contracts/dist/capability.d.ts:537
requiredAuthority.constraints.maxUses?publicnumber-packages/contracts/dist/capability.d.ts:538
requiredAuthority.constraints.notBefore?publicstring-packages/contracts/dist/capability.d.ts:536
requiredAuthority.constraints.purposes?publicstring[]-packages/contracts/dist/capability.d.ts:535
requiredAuthority.idpublicstring-packages/contracts/dist/capability.d.ts:496
requiredAuthority.metadata?publicJsonObject-packages/contracts/dist/capability.d.ts:541
requiredAuthority.namespaceIdpublicstring-packages/contracts/dist/capability.d.ts:497
requiredAuthority.ownerpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/capability.d.ts:483
requiredAuthority.purposepublicstring-packages/contracts/dist/capability.d.ts:532
requiredAuthority.requestedAtpublicstring-packages/contracts/dist/capability.d.ts:533
requiredAuthority.requesterpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/capability.d.ts:498
<a id="property-servableviews"></a> servableViewsreadonlyreadonly ("reach" | "identity" | "namespaces")[]-packages/core/src/agent-card.ts:214
<a id="property-status"></a> statusreadonly"refused"-packages/core/src/agent-card.ts:212

AgentCardServed

Defined in: packages/core/src/agent-card.ts:192

A card the reader was authorized for, in the shape it was authorized for.

Properties

PropertyModifierTypeDefined in
<a id="property-card"></a> cardreadonly{ namespaceId: string; reach: object[]; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "reach"; } | { namespaceId: string; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "identity"; } | { namespaceId: string; namespaces: object[]; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "namespaces"; }packages/core/src/agent-card.ts:194
<a id="property-status-1"></a> statusreadonly"served"packages/core/src/agent-card.ts:193

AllowedDecision

Defined in: packages/core/src/authorization.ts:130

A decision that allowed, and the grant that produced it.

Named apart from AuthorizationDecision so a port can be given the allow arm alone. A denial is not assignable to it, which is how HostCeiling is prevented from ever seeing one.

Properties

PropertyModifierTypeDefined in
<a id="property-allowed"></a> allowedreadonlytruepackages/core/src/authorization.ts:131
<a id="property-matchedgrantid"></a> matchedGrantIdreadonlystringpackages/core/src/authorization.ts:133
<a id="property-metadata"></a> metadata?readonlyJsonObjectpackages/core/src/authorization.ts:134
<a id="property-reasoncode-1"></a> reasonCodereadonly"allowed"packages/core/src/authorization.ts:132

AuditEvent

Defined in: packages/core/src/audit.ts:53

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-action"></a> action?readonlystring-packages/core/src/audit.ts:78
<a id="property-actor"></a> actorreadonly{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/core/src/audit.ts:73
<a id="property-at"></a> atreadonlystring-packages/core/src/audit.ts:70
<a id="property-authority"></a> authorityreadonly{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/core/src/audit.ts:74
<a id="property-authorityhash"></a> authorityHash?readonlystringContent identifier of the exact authority set the decision was made against. A turn resolves authority once, so every decision in it carries the same value; the authority.resolved event that opened the turn carries the grant ids behind it.packages/core/src/audit.ts:86
<a id="property-grantid"></a> grantId?readonlystring-packages/core/src/audit.ts:79
<a id="property-id"></a> idreadonlystringThe identity of this record, unique among every record a kernel emits. Minted when the event is made and never derived from its content. Two records may agree on every other field: at is the turn's instant rather than the emission's, and a bare authorize carries no operationId, so the same question asked twice in one turn is two records that read the same. A durable sink that needs an idempotency key -- for a retried batch, a replayed outbox -- keys on this and on nothing else. Keying on a hash of the content drops every repeat as a duplicate, and a repeat is not a duplicate: an agent that asked twice is an agent that asked twice.packages/core/src/audit.ts:67
<a id="property-messageid"></a> messageId?readonlystring-packages/core/src/audit.ts:89
<a id="property-metadata-1"></a> metadata?readonlyJsonObject-packages/core/src/audit.ts:101
<a id="property-namespaceid"></a> namespaceIdreadonlystring-packages/core/src/audit.ts:72
<a id="property-operationid"></a> operationId?readonlystring-packages/core/src/audit.ts:87
<a id="property-outcome"></a> outcomereadonlyAuditOutcome-packages/core/src/audit.ts:69
<a id="property-owner"></a> ownerreadonly{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/core/src/audit.ts:75
<a id="property-purpose"></a> purposereadonlystring-packages/core/src/audit.ts:76
<a id="property-reason"></a> reason?readonlystring-packages/core/src/audit.ts:91
<a id="property-receiver"></a> receiver?readonly{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/core/src/audit.ts:90
<a id="property-requestedauthority"></a> requestedAuthority?readonlyobjectThe authority an escalation is asking for, when it names one. A first-class field rather than something folded into metadata, for the same reason resource is: it is a contract type with its own schema, and a reviewer's queue built from audit reads it directly rather than trusting that an untyped bag holds the right shape (ADR 0019).packages/core/src/audit.ts:100
requestedAuthority.capabilitiespublicobject[]-packages/contracts/dist/capability.d.ts:511
requestedAuthority.constraints?publicobject-packages/contracts/dist/capability.d.ts:534
requestedAuthority.constraints.delegationDepth?publicnumber-packages/contracts/dist/capability.d.ts:539
requestedAuthority.constraints.expiresAt?publicstring-packages/contracts/dist/capability.d.ts:537
requestedAuthority.constraints.maxUses?publicnumber-packages/contracts/dist/capability.d.ts:538
requestedAuthority.constraints.notBefore?publicstring-packages/contracts/dist/capability.d.ts:536
requestedAuthority.constraints.purposes?publicstring[]-packages/contracts/dist/capability.d.ts:535
requestedAuthority.idpublicstring-packages/contracts/dist/capability.d.ts:496
requestedAuthority.metadata?publicJsonObject-packages/contracts/dist/capability.d.ts:541
requestedAuthority.namespaceIdpublicstring-packages/contracts/dist/capability.d.ts:497
requestedAuthority.ownerpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/capability.d.ts:483
requestedAuthority.purposepublicstring-packages/contracts/dist/capability.d.ts:532
requestedAuthority.requestedAtpublicstring-packages/contracts/dist/capability.d.ts:533
requestedAuthority.requesterpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/capability.d.ts:498
<a id="property-resource"></a> resource?readonlyobject-packages/core/src/audit.ts:77
resource.namespacepublicstring-packages/contracts/dist/capability.d.ts:54
resource.owner?public{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/capability.d.ts:55
resource.pathpublicstring[]-packages/contracts/dist/capability.d.ts:53
<a id="property-tool"></a> tool?readonlystring-packages/core/src/audit.ts:88
<a id="property-traceid"></a> traceIdreadonlystring-packages/core/src/audit.ts:71
<a id="property-type"></a> typereadonlyAuditEventType-packages/core/src/audit.ts:68
<a id="property-version"></a> versionreadonly"1"-packages/core/src/audit.ts:54

AuditSink

Defined in: packages/core/src/audit.ts:104

Methods

record()

record(event): Promise<void>>

Defined in: packages/core/src/audit.ts:105

Parameters
ParameterType
eventAuditEvent
Returns

Promise<void>


AuthoritySnapshot

Defined in: packages/core/src/authority.ts:187

A content identifier for exactly the authority one decision was made against.

With MID_TURN_AUTHORITY_REFRESH off, a turn resolves authority once and every decision in it names the same snapshot -- including a decision that refused an expired grant, because expiry narrows what a snapshot authorizes without changing which snapshot it is. The per-decision field is kept rather than collapsed to a per-turn one because a host may still make kernel calls outside any turn, and because re-enabling the fuse must not change the shape of the evidence.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-grantcount"></a> grantCountreadonlynumber-packages/core/src/authority.ts:191
<a id="property-grantids"></a> grantIdsreadonlyreadonly string[]-packages/core/src/authority.ts:190
<a id="property-hash"></a> hashreadonlystringSHA-256 over the canonical, order-independent form of the grant set.packages/core/src/authority.ts:189
<a id="property-loadedat"></a> loadedAtreadonlystring-packages/core/src/authority.ts:192

AuthorityUnavailableDetail

Defined in: packages/core/src/authority.ts:226

Properties

PropertyModifierTypeDefined in
<a id="property-grantid-1"></a> grantIdreadonlystringpackages/core/src/authority.ts:227
<a id="property-reason-1"></a> reasonreadonlyGrantScopeMismatchpackages/core/src/authority.ts:228

AuthorizationExplanation

Defined in: packages/core/src/authorization.ts:107

Why a denial happened, addressed to the host rather than to the caller.

Three reason codes are deliberately indistinguishable at the call site -- no_matching_grant collapses nine causes, and authority_unavailable collapses four -- so that no caller can map the permission topology by reading refusals. That reticence is owed to the caller, not to the operator: the host wired the store, issued the grant, and built the context, and is entitled to know which of those was wrong. SharedOSKernel records this on the authorization.checked audit event, which never leaves the host.

missingDependency is the one field that reports a configuration fault rather than a policy outcome: a grant matched and could not be honoured because the authorizer was constructed without the store it needed.

Properties

PropertyModifierTypeDefined in
<a id="property-grantsresolved"></a> grantsResolvedreadonlynumberpackages/core/src/authorization.ts:109
<a id="property-missingdependency"></a> missingDependency?readonly"usageStore" | "delegationResolver"packages/core/src/authorization.ts:111
<a id="property-reasoncode-2"></a> reasonCodereadonlyAuthorizationReasonCodepackages/core/src/authorization.ts:108
<a id="property-rejections"></a> rejectionsreadonlyreadonly GrantRejection[]packages/core/src/authorization.ts:110

AuthorizationInstantOptions

Defined in: packages/core/src/authorization.ts:246

The instant one decision is made at, when it is not the turn's own.

ResolvedAuthority.context carries the instant the turn's authority was resolved, and that is what a turn is admitted against. A caller that knows the instant of the operation -- SharedOSKernel does, because the executor stamps a live context onto every call -- names it here, and a grant whose validity window has closed since admission is refused without re-reading the store. Omitting it decides at the turn's instant, which is what a kernel call outside any turn is. See grantIsActive in internal.ts for which removals move and which do not, and ADR 0016 for why.

Extended by

Properties

PropertyModifierTypeDefined in
<a id="property-now"></a> now?readonlystringpackages/core/src/authorization.ts:247

AuthorizationRequest

Defined in: packages/core/src/authorization.ts:32

Properties

PropertyModifierTypeDefined in
<a id="property-action-1"></a> actionreadonlystringpackages/core/src/authorization.ts:34
<a id="property-resource-1"></a> resourcereadonlyobjectpackages/core/src/authorization.ts:33
resource.namespacepublicstringpackages/contracts/dist/capability.d.ts:54
resource.owner?public{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }packages/contracts/dist/capability.d.ts:55
resource.pathpublicstring[]packages/contracts/dist/capability.d.ts:53

AuthorizeOptions

Defined in: packages/core/src/authorization.ts:250

The instant one decision is made at, when it is not the turn's own.

ResolvedAuthority.context carries the instant the turn's authority was resolved, and that is what a turn is admitted against. A caller that knows the instant of the operation -- SharedOSKernel does, because the executor stamps a live context onto every call -- names it here, and a grant whose validity window has closed since admission is refused without re-reading the store. Omitting it decides at the turn's instant, which is what a kernel call outside any turn is. See grantIsActive in internal.ts for which removals move and which do not, and ADR 0016 for why.

Extends

Properties

PropertyModifierTypeDescriptionInherited fromDefined in
<a id="property-consume"></a> consume?readonlybooleanConsumption is reserved for execution. Discovery calls must leave this false so merely viewing a catalog cannot spend a bounded grant.-packages/core/src/authorization.ts:255
<a id="property-now-1"></a> now?readonlystring-AuthorizationInstantOptions.nowpackages/core/src/authorization.ts:247
<a id="property-onexplain"></a> onExplain?readonly(explanation) => voidCalled once with the host-facing account of a denial, before it is returned. Never called for an allow, and never for a discovery check -- catalog filtering denies constantly and by design, and explaining each one would bury the denials that surprised somebody. The callback runs synchronously on a frozen value and must not throw: a diagnostic that can change a decision is a decision.-packages/core/src/authorization.ts:265

CapabilityAuthorizerOptions

Defined in: packages/core/src/authorization.ts:268

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-delegationresolver"></a> delegationResolver?readonlyDelegationChainResolverTrusted ancestor lookup for delegated grants. Without it, a grant that claims a parent can never authorize anything.packages/core/src/authorization.ts:275
<a id="property-grantverifier"></a> grantVerifier?readonlyCapabilityGrantVerifier-packages/core/src/authorization.ts:270
<a id="property-hostceiling"></a> hostCeiling?readonlyHostCeiling<unknown>Product or organization policy the kernel consults. See HostCeiling. Installed by whoever constructs the authorizer, which is the party that already chooses the GrantSource. That is not a new privilege: anyone who decides what authority exists can already decide it is none. The per-turn policy it decides against, when it has one, comes from SharedOSKernelOptions.policySource -- on the kernel rather than here, because the load is a turn-boundary event and the kernel owns the turn boundary. The authorizer only carries what was loaded to the ceiling.packages/core/src/authorization.ts:289
<a id="property-maxdelegationchainlength"></a> maxDelegationChainLength?readonlynumber-packages/core/src/authorization.ts:276
<a id="property-onprovidererror"></a> onProviderError?readonlyProviderErrorReporterWhere a throw from HostCeiling.narrow is reported. The same shape SharedOSKernelOptions.onProviderError takes, and a host wanting both passes one function to both: the ceiling is installed here rather than on the kernel, so the kernel's hook cannot reach it. Without this, a ceiling that fails denies every operation in the deployment as host_policy_unavailable and says nothing about why.packages/core/src/authorization.ts:299
<a id="property-usagestore"></a> usageStore?readonlyGrantUsageStore-packages/core/src/authorization.ts:269

CapabilityGrantVerifier

Defined in: packages/core/src/authorization.ts:119

Methods

verify()

verify(grant, context): Promise<boolean>>

Defined in: packages/core/src/authorization.ts:120

Parameters
ParameterType
grant{ capabilities: object[]; constraints: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; issuedAt: string; issuer: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; metadata?: JsonObject; namespaceId: string; parentGrantId?: string; revokedAt?: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }
grant.capabilitiesobject[]
grant.constraints{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }
grant.constraints.delegationDepth?number
grant.constraints.expiresAt?string
grant.constraints.maxUses?number
grant.constraints.notBefore?string
grant.constraints.purposes?string[]
grant.idstring
grant.issuedAtstring
grant.issuer{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
grant.metadata?JsonObject
grant.namespaceIdstring
grant.parentGrantId?string
grant.revokedAt?string
grant.subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
Returns

Promise<boolean>


ContextToolProvider

Defined in: packages/core/src/tool-registry.ts:38

Supplies tools for exactly one trusted access context.

Hosts use this port for user-specific MCP servers and other dynamic catalogs instead of mutating one global registry shared by concurrent users.

Called once per turn, not once per operation. The kernel holds what it returns for the turn's length, so a provider that varies part-way through a turn does not change what that turn is answered from (ADR 0026). The context it is given is the one carried by the turn's first operation to need a catalogue, which for enabledToolNamespaces may be older than the operation being served: what the turn holds is the unfiltered registry, and the namespace check still runs per operation over it.

Properties

PropertyModifierTypeDefined in
<a id="property-id-1"></a> idreadonlystringpackages/core/src/tool-registry.ts:39

Methods

listTools()

listTools(context, signal): Promise<readonly ToolHandler[]>

Defined in: packages/core/src/tool-registry.ts:40

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
signalAbortSignal
Returns

Promise<readonly ToolHandler[]>


DelegationChainResolver

Defined in: packages/core/src/delegation.ts:30

The trusted lookup for ancestors of a derived grant.

A delegated grant travels with a parent identifier, never with its parent's contents, so the ancestor must be loaded from an authoritative source. An implementation must resolve only within the requested namespace and must throw rather than return a partial or stale ancestor.

Methods

resolve()

resolve(namespaceId, grantId): Promise<{ capabilities: object[]; constraints: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; issuedAt: string; issuer: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; metadata?: JsonObject; namespaceId: string; parentGrantId?: string; revokedAt?: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; } | undefined>>

Defined in: packages/core/src/delegation.ts:31

Parameters
ParameterType
namespaceIdstring
grantIdstring
Returns

Promise<{ capabilities: object[]; constraints: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; issuedAt: string; issuer: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; metadata?: JsonObject; namespaceId: string; parentGrantId?: string; revokedAt?: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; } | undefined>


DelegationValidationOptions

Defined in: packages/core/src/delegation.ts:66

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-admittedat"></a> admittedAt?readonlynumberThe instant the turn's authority was resolved, when it is not now. An ancestor is subject to the same split as the grant that names it: its expiry is observed at now, everything else at the instant the turn was admitted. Defaults to now, which decides the whole chain at one instant.packages/core/src/delegation.ts:76
<a id="property-maxchainlength"></a> maxChainLength?readonlynumber-packages/core/src/delegation.ts:68
<a id="property-resolver"></a> resolver?readonlyDelegationChainResolver-packages/core/src/delegation.ts:67

DeriveGrantRequest

Defined in: packages/core/src/delegation.ts:292

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-capabilities"></a> capabilitiesreadonlyreadonly object[]The subset being passed on. Must be within the parent, capability by capability.packages/core/src/delegation.ts:298
<a id="property-constraints"></a> constraints?readonlyOmit<{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }, "delegationDepth"> & object-packages/core/src/delegation.ts:299
<a id="property-id-2"></a> idreadonlystringIdentifier for the derived grant. Must be unique within the namespace.packages/core/src/delegation.ts:294
<a id="property-issuedat"></a> issuedAtreadonlystring-packages/core/src/delegation.ts:302
<a id="property-metadata-2"></a> metadata?readonlyJsonObject-packages/core/src/delegation.ts:303
<a id="property-subject"></a> subjectreadonly{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }Who receives the derived authority.packages/core/src/delegation.ts:296

EscalationOptions

Defined in: packages/core/src/kernel.ts:196

Extends

Properties

PropertyModifierTypeDescriptionInherited fromDefined in
<a id="property-requestedauthority-1"></a> requestedAuthority?readonlyCapabilityRequestPayloadThe authority this escalation is asking for. A host escalating a denial passes the requiredAuthority that denial described; a model-chosen escalation usually has none, because a sentence is all it produced. Either way nothing here advances the escalation -- resolution stays host-owned work that ends in a grant the next turn loads. The two names are one concept in two roles, and both end in the noun this package uses for what grants confer: a denial says what was required, and an escalation requests it. { requestedAuthority: denial.requiredAuthority } is the whole hop. What is recorded is minted, not copied. The ask -- capabilities, purpose, constraints, metadata -- is the caller's; id, namespaceId, requester, owner, and requestedAt come from the trusted context, whatever the caller wrote, because a request the caller authored would be a caller-chosen correlation for a decision the kernel made. The hop above still round-trips: the denial's description was minted from the same ask, so it comes back under the same identifier (ADR 0019).-packages/core/src/kernel.ts:218
<a id="property-signal-1"></a> signal?readonlyAbortSignal-KernelOperationOptions.signalpackages/core/src/kernel.ts:156

GrantRejection

Defined in: packages/core/src/authorization.ts:87

Properties

PropertyModifierTypeDefined in
<a id="property-grantid-2"></a> grantIdreadonlystringpackages/core/src/authorization.ts:88
<a id="property-reason-2"></a> reasonreadonlyGrantRejectionReasonpackages/core/src/authorization.ts:89

GrantSource

Defined in: packages/core/src/authority.ts:95

The trusted boundary that loads authoritative grants.

This is the only way authority enters SharedOS. An implementation must answer from the issuing store rather than from anything the caller supplied, and it must return exactly the active grants issued to context.actor by context.authority inside context.namespaceId. Returning material outside that scope, or material that does not satisfy the grant contract, is treated as an unavailable source rather than as partial authority.

Throwing is the correct response to an outage. SharedOS converts it into a fail-closed denial; it never falls back to a cached or caller-supplied set.

Methods

load()

load(context, signal): Promise<readonly object[]>

Defined in: packages/core/src/authority.ts:96

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
signalAbortSignal
Returns

Promise<readonly object[]>


GrantUsageStore

Defined in: packages/core/src/authorization.ts:114

Methods

getUsage()

getUsage(namespaceId, grantId): Promise<number>>

Defined in: packages/core/src/authorization.ts:115

Parameters
ParameterType
namespaceIdstring
grantIdstring
Returns

Promise<number>

tryConsume()

tryConsume(namespaceId, grantId, maximumUses): Promise<boolean>>

Defined in: packages/core/src/authorization.ts:116

Parameters
ParameterType
namespaceIdstring
grantIdstring
maximumUsesnumber
Returns

Promise<boolean>


HostCeiling

Defined in: packages/core/src/authorization.ts:225

Product or organization policy, consulted on a grant that would otherwise allow.

A host narrows what its agents may do for reasons no grant expresses -- a relationship model, a content-sensitivity check, an org-wide freeze. Doing that outside the kernel makes it a second enforcement point SharedOS cannot see: the refusal reaches no audit sink and no conformance cell, and the denial counts a deployment produces say "nobody authorized this" about calls a grant did authorize. This is where that judgment goes instead (ADR 0020).

Synchronous, and that is the contract. A synchronous return structurally forbids the network call, the database read, and the model call. A ceiling needing a remote policy service is not this port: a per-call round trip here is a latency and availability change to every operation SharedOS mediates. Load the policy into memory and refresh it on your own schedule, which is what correctness would require anyway.

It may only narrow, and the types say so. narrow takes an AllowedDecision and returns a HostCeilingVerdict: the decision it was given, or a HostPolicyDenial whose code is fixed. A denial cannot be passed in, so none can be turned into an allow, and a code cannot be authored. A host outside TypeScript is held to the same at runtime, and nothing else is read from what it returns: an allowed result carrying a different matchedGrantId is treated as a malfunction and fails closed, and any other reasonCode on a refusal is replaced with host_policy_denied so one refusal vocabulary survives (ADR 0012). Say more in metadata, which is preserved -- except that audit drops the consumed and failClosed keys the kernel states itself, and anything that is not a JSON object is dropped whole.

It is consulted before a bounded use is consumed, so a call policy stopped does not spend a maxUses grant: that counter records what an actor did.

It is consulted per matching grant, not once per request. A refusal ends that grant's candidacy and the walk continues, because two grants can match one request and differ in ways policy distinguishes. Decide from request and context; decision.matchedGrantId is there so a refusal can record which grant it overrode, and a ceiling that branches on it is describing grant issuance rather than a ceiling.

Discovery consults it too, so a catalogue is not offered on authority that invocation would refuse -- the agreement ADR 0016 established for expiry. Note what it is asked there: a tool's declared ceiling, which ADR 0012 allows to be broader than the argument-selected resource of any particular call.

Its policy arrives as the fourth argument. When the kernel was given a PolicySource, policy is what that source loaded for this turn, handed back exactly as loaded -- not cloned, because SharedOS does not know its shape -- and the same value for every decision in the turn. When it was not, policy is undefined and the ceiling decides over state it closes over. The pairing is the host's: SharedOS cannot check that the type a ceiling expects is the type its source produces, which is why the parameter admits undefined rather than promising a value. A turn whose policy could not be loaded never reaches narrow: every decision the ceiling would have been consulted on is refused host_policy_unavailable instead.

A throw fails closed as host_policy_unavailable, an infrastructure denial like every other unavailable trusted component.

Type Parameters

Type ParameterDefault type
PolicyHostPolicy

Methods

narrow()

narrow(decision, request, context, policy): HostCeilingVerdict

Defined in: packages/core/src/authorization.ts:226

Parameters
ParameterType
decisionAllowedDecision
requestAuthorizationRequest
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
policyPolicy | undefined
Returns

HostCeilingVerdict


HostPolicyDenial

Defined in: packages/core/src/authorization.ts:145

A refusal by host policy, the one input to a decision no grant expresses.

The only denial a ceiling may author. Its code is fixed here rather than taken from the ceiling, so the vocabulary stays SharedOS's: a host cannot invent a reason code by returning one, and cannot borrow no_matching_grant to make its own refusal look like an absent grant. Say more in metadata.

Properties

PropertyModifierTypeDefined in
<a id="property-allowed-1"></a> allowedreadonlyfalsepackages/core/src/authorization.ts:146
<a id="property-metadata-3"></a> metadata?readonlyJsonObjectpackages/core/src/authorization.ts:148
<a id="property-reasoncode-3"></a> reasonCodereadonly"host_policy_denied"packages/core/src/authorization.ts:147

KernelOperationOptions

Defined in: packages/core/src/kernel.ts:155

Extended by

Properties

PropertyModifierTypeDefined in
<a id="property-signal-2"></a> signal?readonlyAbortSignalpackages/core/src/kernel.ts:156

LoadedPolicy

Defined in: packages/core/src/authority.ts:151

What a PolicySource loaded: the policy, and the source's name for it.

version is the one thing about a policy SharedOS reads. It is not derived from the policy -- an opaque value has no canonical form to hash, and a compiled matcher has no bytes to digest -- so the source states it: a revision, an etag, the content hash of the table it read. Two loads that would decide the same way should carry the same version and two that would not, different ones; nothing else about it is checked. It is recorded on every tool.catalog.listed event in the turn as hostPolicyVersion, which is what lets a reader pin the catalogue a turn was shown to the policy state it was decided against, the way authorityHash pins it to the grant set.

Type Parameters

Type ParameterDefault type
PolicyHostPolicy

Properties

PropertyModifierTypeDefined in
<a id="property-policy"></a> policyreadonlyPolicypackages/core/src/authority.ts:152
<a id="property-version-1"></a> versionreadonlystringpackages/core/src/authority.ts:153

MessageCapabilityResolver

Defined in: packages/core/src/message-service.ts:48

Methods

resolve()

resolve(context, envelope): AuthorizationRequest

Defined in: packages/core/src/message-service.ts:49

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
envelope{ createdAt: string; id: string; payload: JsonValue; provenance?: { metadata?: JsonObject; parentIds: string[]; source: string; }; purpose: string; receiver: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; replyTo?: string; sender: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; traceId: string; version: "1"; }
envelope.createdAtstring
envelope.idstring
envelope.payloadJsonValue
envelope.provenance?{ metadata?: JsonObject; parentIds: string[]; source: string; }
envelope.provenance.metadata?JsonObject
envelope.provenance.parentIdsstring[]
envelope.provenance.sourcestring
envelope.purposestring
envelope.receiver{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.replyTo?string
envelope.sender{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.traceIdstring
envelope.version"1"
Returns

AuthorizationRequest


MessageRequestRouter

Defined in: packages/core/src/message-service.ts:39

Host-owned lookup for the durable reply to one accepted message request. SharedOS validates the returned envelope before exposing its payload.

Methods

resolveReply()

resolveReply(context, request, delivery, signal): Promise<{ createdAt: string; id: string; payload: JsonValue; provenance?: { metadata?: JsonObject; parentIds: string[]; source: string; }; purpose: string; receiver: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; replyTo?: string; sender: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; traceId: string; version: "1"; }>

Defined in: packages/core/src/message-service.ts:40

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
request{ createdAt: string; id: string; payload: JsonValue; provenance?: { metadata?: JsonObject; parentIds: string[]; source: string; }; purpose: string; receiver: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; replyTo?: string; sender: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; traceId: string; version: "1"; }
request.createdAtstring
request.idstring
request.payloadJsonValue
request.provenance?{ metadata?: JsonObject; parentIds: string[]; source: string; }
request.provenance.metadata?JsonObject
request.provenance.parentIdsstring[]
request.provenance.sourcestring
request.purposestring
request.receiver{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
request.replyTo?string
request.sender{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
request.traceIdstring
request.version"1"
delivery{ messageId: string; metadata?: JsonObject; status: "accepted"; timestamp: string; } | { messageId: string; metadata?: JsonObject; status: "delivered"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "denied"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "failed"; timestamp: string; }
signalAbortSignal
Returns

Promise<{ createdAt: string; id: string; payload: JsonValue; provenance?: { metadata?: JsonObject; parentIds: string[]; source: string; }; purpose: string; receiver: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; replyTo?: string; sender: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; traceId: string; version: "1"; }>


MessageTransport

Defined in: packages/core/src/message-service.ts:27

Methods

deliver()

deliver(context, envelope, signal): Promise<{ messageId: string; metadata?: JsonObject; status: "accepted"; timestamp: string; } | { messageId: string; metadata?: JsonObject; status: "delivered"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "denied"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "failed"; timestamp: string; }>

Defined in: packages/core/src/message-service.ts:28

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
envelope{ createdAt: string; id: string; payload: JsonValue; provenance?: { metadata?: JsonObject; parentIds: string[]; source: string; }; purpose: string; receiver: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; replyTo?: string; sender: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; traceId: string; version: "1"; }
envelope.createdAtstring
envelope.idstring
envelope.payloadJsonValue
envelope.provenance?{ metadata?: JsonObject; parentIds: string[]; source: string; }
envelope.provenance.metadata?JsonObject
envelope.provenance.parentIdsstring[]
envelope.provenance.sourcestring
envelope.purposestring
envelope.receiver{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.replyTo?string
envelope.sender{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
envelope.traceIdstring
envelope.version"1"
signalAbortSignal
Returns

Promise<{ messageId: string; metadata?: JsonObject; status: "accepted"; timestamp: string; } | { messageId: string; metadata?: JsonObject; status: "delivered"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "denied"; timestamp: string; } | { error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; messageId: string; metadata?: JsonObject; status: "failed"; timestamp: string; }>


PolicySource

Defined in: packages/core/src/authority.ts:134

The trusted boundary that loads host policy, once per turn, beside the grant set.

A HostCeiling is synchronous by contract, so it can only decide against state it already holds. This is where that state comes from when it lives in a store: one asynchronous load at the turn boundary, in the same place and at the same moment authority is resolved, and every decision inside the turn made against the result without reading the store again. A ceiling whose policy is fixed before a run starts needs no source at all and closes over its own state; the port exists so a policy that lives in a database is not forced back outside the kernel by the signature (ADR 0020).

Throwing is the correct response to an outage. SharedOS fails the turn's policy closed: every decision a ceiling would have been consulted on is refused host_policy_unavailable, the error goes to SharedOSKernelOptions.onProviderError, and nothing falls back to a cached or caller-supplied policy. A result that is not a LoadedPolicy -- no version, or an empty one -- is a defect of the same weight and is treated the same way.

Type Parameters

Type ParameterDefault type
PolicyHostPolicy

Methods

load()

load(context, signal): Promise<LoadedPolicy<Policy>>>>

Defined in: packages/core/src/authority.ts:135

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
signalAbortSignal
Returns

Promise<LoadedPolicy<Policy>>


ProviderErrorContext

Defined in: packages/core/src/diagnostics.ts:83

What one contained throw was, in the kernel's own terms.

kind is what lets a single hook stay honest across a growing set of ports. A host that wants to route a transport failure differently from a tool's branches on it, and gets that without SharedOS having guessed in advance which splits a host would want; a fifth port added later is covered by the hook every host already installed, where a fifth option would be one nobody passes.

reasonCode closes the loop, and is most of the value here. It is the code the kernel returned in place of the throw, and the same code the matching audit event carries under reason, so a host can join its own log line to audit without correlating on timing. Usually it is also what the agent was told; the exception is a transport failure under the message-request tool, where audit records message_delivery_failed and the tool result says message_request_not_accepted. Both records carry the same operationId.

policy is the one kind that is not an operation. It is a HostCeiling that threw while narrowing a decision, or a PolicySource that threw while loading the turn's policy; both are answered with host_policy_unavailable. The ceiling is installed on CapabilityAuthorizer and the source on the kernel, so each reports through the hook where it lives -- CapabilityAuthorizerOptions.onProviderError for the ceiling, SharedOSKernelOptions.onProviderError for the source -- and a host that wants both passes the same function to both, which is why they share one shape rather than the ceiling growing a hook of its own. A source's report names no resource or action: it fires at the turn boundary, before any operation, and once per turn rather than once per decision it fails.

kind follows the entry point, not the port, where the two differ. A MessageCapabilityResolver that throws is message when the turn called sendMessage and tool when it went through the message-request tool, since that is a tool call resolving its requirement. A host watching one port should match on reasonCode, which is stable, rather than on kind alone.

The rest is what the kernel knew at the point it caught: traceId and namespaceId always, and whichever of the operation's identifiers exist on that path. A message resolved outside a tool call names neither a call nor a tool; a resource names no tool.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-action-2"></a> action?readonlystring-packages/core/src/diagnostics.ts:93
<a id="property-kind"></a> kindreadonlyProviderErrorKind-packages/core/src/diagnostics.ts:84
<a id="property-namespaceid-1"></a> namespaceIdreadonlystring-packages/core/src/diagnostics.ts:88
<a id="property-operationid-1"></a> operationId?readonlystringThe call id, where the path has one.packages/core/src/diagnostics.ts:90
<a id="property-reasoncode-4"></a> reasonCodereadonlystringThe code the kernel returned instead.packages/core/src/diagnostics.ts:86
<a id="property-resource-2"></a> resource?readonlyobject-packages/core/src/diagnostics.ts:92
resource.namespacepublicstring-packages/contracts/dist/capability.d.ts:54
resource.owner?public{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/capability.d.ts:55
resource.pathpublicstring[]-packages/contracts/dist/capability.d.ts:53
<a id="property-tool-1"></a> tool?readonlystring-packages/core/src/diagnostics.ts:91
<a id="property-traceid-1"></a> traceIdreadonlystring-packages/core/src/diagnostics.ts:87

RefusedCall

Defined in: packages/core/src/kernel.ts:174

One call an enforcement boundary refused without invoking anything.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-callid"></a> callIdreadonlystring-packages/core/src/kernel.ts:175
<a id="property-cause-2"></a> cause?readonlystringWhich situation a coarse code was, where it covers several.packages/core/src/kernel.ts:179
<a id="property-reasoncode-5"></a> reasonCodereadonlystring-packages/core/src/kernel.ts:177
<a id="property-tool-2"></a> toolreadonlystring-packages/core/src/kernel.ts:176

ResolvedAuthority

Defined in: packages/core/src/authority.ts:203

An access context together with the authority a trusted source produced for it.

Authority is deliberately held beside the context rather than merged into it, so a resolved authority can never be passed to a provider, tool handler, message transport, or runtime that expects an AccessContext.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-context"></a> contextreadonlyobject-packages/core/src/authority.ts:204
context.actorpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/access.d.ts:144
context.authoritypublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/access.d.ts:157
context.enabledToolNamespacespublicstring[]-packages/contracts/dist/access.d.ts:170
context.namespaceIdpublicstring-packages/contracts/dist/access.d.ts:141
context.nowpublicstring-packages/contracts/dist/access.d.ts:171
context.ownerpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/access.d.ts:128
context.purposepublicstring-packages/contracts/dist/access.d.ts:142
context.traceIdpublicstring-packages/contracts/dist/access.d.ts:143
<a id="property-grants"></a> grantsreadonlyreadonly object[]-packages/core/src/authority.ts:205
<a id="property-hostpolicy"></a> hostPolicy?readonlyPolicyResolution<unknown>The host policy loaded for this turn, when a PolicySource is installed. Absent when none is, and the ceiling -- if one is installed -- decides over state it closes over. Not part of AuthoritySnapshot: policy is not authority, and an opaque value has no canonical form to hash.packages/core/src/authority.ts:213
<a id="property-snapshot"></a> snapshotreadonlyAuthoritySnapshot-packages/core/src/authority.ts:206

ResourceInvocationRequest

Defined in: packages/core/src/resource-registry.ts:10

Properties

PropertyModifierTypeDefined in
<a id="property-action-3"></a> actionreadonlystringpackages/core/src/resource-registry.ts:13
<a id="property-input"></a> input?readonlyJsonValuepackages/core/src/resource-registry.ts:14
<a id="property-metadata-4"></a> metadata?readonlyJsonObjectpackages/core/src/resource-registry.ts:15
<a id="property-operationid-2"></a> operationIdreadonlystringpackages/core/src/resource-registry.ts:11
<a id="property-resource-3"></a> resourcereadonlyobjectpackages/core/src/resource-registry.ts:12
resource.namespacepublicstringpackages/contracts/dist/capability.d.ts:54
resource.owner?public{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }packages/contracts/dist/capability.d.ts:55
resource.pathpublicstring[]packages/contracts/dist/capability.d.ts:53

ResourceProvider

Defined in: packages/core/src/resource-registry.ts:18

Properties

PropertyModifierTypeDefined in
<a id="property-namespace"></a> namespacereadonlystringpackages/core/src/resource-registry.ts:19

Methods

invoke()

invoke(operation, signal): Promise<{ completedAt: string; metadata?: JsonObject; operationId: string; output: JsonValue; status: "succeeded"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "denied"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "failed"; }>

Defined in: packages/core/src/resource-registry.ts:20

Parameters
ParameterType
operation{ action: string; context: { actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }; input?: JsonValue; metadata?: JsonObject; operationId: string; resource: { namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }; }
operation.actionstring
operation.context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
operation.context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
operation.context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
operation.context.enabledToolNamespacesstring[]
operation.context.namespaceIdstring
operation.context.nowstring
operation.context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
operation.context.purposestring
operation.context.traceIdstring
operation.input?JsonValue
operation.metadata?JsonObject
operation.operationIdstring
operation.resource{ namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }
operation.resource.namespacestring
operation.resource.owner?{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
operation.resource.pathstring[]
signalAbortSignal
Returns

Promise<{ completedAt: string; metadata?: JsonObject; operationId: string; output: JsonValue; status: "succeeded"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "denied"; } | { completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; operationId: string; status: "failed"; }>


SharedOSKernelOptions

Defined in: packages/core/src/kernel.ts:93

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-audit"></a> audit?readonlyAuditSink-packages/core/src/kernel.ts:129
<a id="property-authorizer"></a> authorizer?readonlyCapabilityAuthorizer-packages/core/src/kernel.ts:111
<a id="property-createauditid"></a> createAuditId?readonly() => stringHow each audit record gets its identity. A random UUID by default. Override for a deterministic host -- a replayed fixture, a conformance run -- and nowhere else, and never with a factory that can repeat: two records with one id are one record to every sink that deduplicates, which is exactly the loss AuditEvent.id exists to prevent.packages/core/src/kernel.ts:128
<a id="property-createmessageid"></a> createMessageId?readonly(context, call) => string-packages/core/src/kernel.ts:119
<a id="property-grantsource"></a> grantSourcereadonlyGrantSourceThe trusted boundary that loads authority. It is required: a kernel with no authoritative grant source can only fail closed.packages/core/src/kernel.ts:98
<a id="property-messagecapabilityresolver"></a> messageCapabilityResolver?readonlyMessageCapabilityResolver-packages/core/src/kernel.ts:118
<a id="property-messagerequestrouter"></a> messageRequestRouter?readonlyMessageRequestRouter-packages/core/src/kernel.ts:117
<a id="property-messagetransport"></a> messageTransport?readonlyMessageTransport-packages/core/src/kernel.ts:116
<a id="property-onauditerror"></a> onAuditError?readonly(error, event) => void | Promise<void>Notification for audit failures that occur after a side effect.packages/core/src/kernel.ts:131
<a id="property-onprovidererror-1"></a> onProviderError?readonlyProviderErrorReporterNotification for a throw the kernel contained rather than propagated. A provider, tool handler, transport, or router that throws is answered with a fixed reason code, and until a host installs this the error itself is gone: tool_execution_failed says an operation stopped and does not say why. One hook covers every such port, and ProviderErrorContext.kind is what a host branches on if it wants to treat them differently. Synchronous, unlike SharedOSKernelOptions.onAuditError, and see reportContainedError for why the two differ.packages/core/src/kernel.ts:144
<a id="property-policysource"></a> policySource?readonlyPolicySource<unknown>The trusted boundary that loads host policy, once per turn, beside the grant set. See PolicySource. Optional. Without one the ceiling installed on the authorizer, if any, is handed undefined and decides over state it closes over. It is installed here rather than beside the ceiling because the load is a turn-boundary event and the kernel owns the turn boundary; a throw is reported to SharedOSKernelOptions.onProviderError as kind: "policy", and the turn's policy fails closed.packages/core/src/kernel.ts:110
<a id="property-resources"></a> resources?readonlyResourceProviderRegistry-packages/core/src/kernel.ts:112
<a id="property-spans"></a> spans?readonlySpanSinkWhere the cost of enforcement is reported, when a host is measuring it. Absent by default and absent in every production path that does not ask for it, which is what keeps a measured run and an unmeasured one the same run. See SpanSink.packages/core/src/kernel.ts:152
<a id="property-toolnamespacesettings"></a> toolNamespaceSettings?readonlyToolNamespaceSettingsStore-packages/core/src/kernel.ts:115
<a id="property-toolproviders"></a> toolProviders?readonlyreadonly ContextToolProvider[]-packages/core/src/kernel.ts:114
<a id="property-tools"></a> tools?readonlyToolRegistry-packages/core/src/kernel.ts:113

Span

Defined in: packages/core/src/spans.ts:37

One completed span of SharedOS-owned work.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-attributes"></a> attributesreadonlySpanAttributes-packages/core/src/spans.ts:41
<a id="property-durationms"></a> durationMsreadonlynumberMonotonic duration in fractional milliseconds.packages/core/src/spans.ts:40
<a id="property-name-2"></a> namereadonlystring-packages/core/src/spans.ts:38

SpanScope

Defined in: packages/core/src/spans.ts:64

The handle an operation uses to say what it turned out to be.

Attributes are set from inside the measured operation rather than derived from its return value, because the facts worth recording are not all in the return: the call id an MCP server minted, the refusal code a path took, the boundary that answered. Setting one on a span nobody is recording is a no-op.

Methods

set()

set(key, value): void

Defined in: packages/core/src/spans.ts:65

Parameters
ParameterType
keystring
valuestring | number | boolean
Returns

void


SpanSink

Defined in: packages/core/src/spans.ts:52

Where completed spans are reported.

Synchronous and returning nothing, so a sink cannot delay the operation it is measuring or change what the operation returns. A sink that throws is ignored: measurement is an observation, and an observation that could fail an authorization decision would be a new way for a turn to be denied.

Methods

record()

record(span): void

Defined in: packages/core/src/spans.ts:53

Parameters
ParameterType
spanSpan
Returns

void


ToolCatalogOptions

Defined in: packages/core/src/published-tool.ts:133

Properties

PropertyModifierTypeDefined in
<a id="property-executionid"></a> executionIdreadonlystringpackages/core/src/published-tool.ts:134

ToolHandler

Defined in: packages/core/src/tool-registry.ts:15

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-definition"></a> definitionreadonlyobject-packages/core/src/tool-registry.ts:16
definition.annotations?publicobject-packages/contracts/dist/tool.d.ts:309
definition.annotations.destructive?publicboolean-packages/contracts/dist/tool.d.ts:311
definition.annotations.idempotent?publicboolean-packages/contracts/dist/tool.d.ts:312
definition.annotations.readOnly?publicboolean-packages/contracts/dist/tool.d.ts:310
definition.descriptionpublicstring-packages/contracts/dist/tool.d.ts:283
definition.inputSchemapublicJsonObject-packages/contracts/dist/tool.d.ts:286
definition.metadata?publicJsonObject-packages/contracts/dist/tool.d.ts:307
definition.namepublicstring-packages/contracts/dist/tool.d.ts:282
definition.namespacepublicstring-packages/contracts/dist/tool.d.ts:281
definition.outputSchema?publicJsonObject-packages/contracts/dist/tool.d.ts:308
definition.readWritepublic"read" | "write"-packages/contracts/dist/tool.d.ts:285
definition.requiredCapabilitypublicobject-packages/contracts/dist/tool.d.ts:287
definition.requiredCapability.actionpublicstring-packages/contracts/dist/tool.d.ts:305
definition.requiredCapability.resourcepublicobject-packages/contracts/dist/tool.d.ts:288
definition.requiredCapability.resource.namespacepublicstring-packages/contracts/dist/tool.d.ts:290
definition.requiredCapability.resource.owner?public{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-packages/contracts/dist/tool.d.ts:291
definition.requiredCapability.resource.pathpublicstring[]-packages/contracts/dist/tool.d.ts:289
definition.sourcepublicstring-packages/contracts/dist/tool.d.ts:284
<a id="property-parsearguments"></a> parseArgumentsreadonly(arguments_) => unknownParse and normalize untrusted arguments before authorization or execution.packages/core/src/tool-registry.ts:18
<a id="property-resolverequirement"></a> resolveRequirement?readonly(context, call) => AuthorizationRequestResolve argument-selected resources immediately before execution.packages/core/src/tool-registry.ts:20

Methods

invoke()

invoke(context, call, signal): Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

Defined in: packages/core/src/tool-registry.ts:21

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
call{ arguments: JsonObject; id: string; requestedAt: string; tool: string; traceId: string; }
call.argumentsJsonObject
call.idstring
call.requestedAtstring
call.toolstring
call.traceIdstring
signalAbortSignal
Returns

Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>


ToolNamespaceSettingsStore

Defined in: packages/core/src/tool-namespace-control.ts:11

Host-owned persistence and product-policy boundary for namespace settings.

Implementations must apply a patch atomically against fresh state and return the authoritative effective selection. They may narrow the result according to organization policy, but must never widen it beyond trusted host policy.

Methods

applyUpdate()

applyUpdate(context, update, signal): Promise<readonly string[]>

Defined in: packages/core/src/tool-namespace-control.ts:12

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
update{ disable?: string[]; enable?: string[]; }
update.disable?string[]
update.enable?string[]
signalAbortSignal
Returns

Promise<readonly string[]>


TurnEndRecord

Defined in: packages/core/src/kernel.ts:160

How a turn finished, as the boundary that finished it saw it.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-endedby"></a> endedBy?readonly"envelope" | "runtime"Who produced a failure: the envelope refusing, or the runtime reporting its own. The same distinction ExecutionEvent carries, kept because a record reader crediting enforcement must not credit a plugin's self-reported error.packages/core/src/kernel.ts:170
<a id="property-executionid-1"></a> executionIdreadonlystring-packages/core/src/kernel.ts:161
<a id="property-reasoncode-6"></a> reasonCode?readonlystringThe terminal code, where the ending had one.packages/core/src/kernel.ts:164
<a id="property-status-2"></a> statusreadonly"denied" | "succeeded" | "failed" | "escalated" | "cancelled"-packages/core/src/kernel.ts:162

Type Aliases

AgentCardRead

AgentCardRead = AgentCardServed | AgentCardRefusal

Defined in: packages/core/src/agent-card.ts:219


AuditEventInput

AuditEventInput = Omit<AuditEvent, "version" | "id" | "at" | "traceId" | "namespaceId" | "actor" | "authority" | "owner" | "purpose">>

Defined in: packages/core/src/audit.ts:129

What an emitter states about one event; the kernel supplies the rest.


AuditEventType

AuditEventType = "authority.resolved" | "authorization.checked" | "escalation.requested" | "escalation.auto_decided" | "resource.invoked" | "tool.catalog.listed" | "tool.namespace.catalog.listed" | "tool.namespace.selection.updated" | "tool.invoked" | "message.sent" | "turn.ended"

Defined in: packages/core/src/audit.ts:10


AuditOutcome

AuditOutcome = "allowed" | "denied" | "succeeded" | "failed" | "escalated"

Defined in: packages/core/src/audit.ts:39

escalated is its own outcome, not a denial.

A denial is a decision SharedOS made. An escalation is a decision it declined to make and handed to a human, and counting the two together would inflate every denial rate by the cases where the system correctly asked for help.


AuditSource

AuditSource = "kernel" | "envelope"

Defined in: packages/core/src/audit.ts:51

Which enforcement boundary produced an operation or terminal event.

Recorded in metadata on every one of them. It was free to infer until the execution envelope began recording as well -- anything in audit was the kernel's, because the envelope wrote nothing -- and the moment that stopped being true it became a fact with nowhere to live. ADR 0012 keeps one refusal vocabulary across both boundaries on purpose: a code says what was refused, and this says who refused it (ADR 0023).


AuthorityResolution

AuthorityResolution = { authority: ResolvedAuthority; status: "resolved"; } | { code: AuthorityUnavailableCode; detail?: AuthorityUnavailableDetail; status: "unavailable"; }

Defined in: packages/core/src/authority.ts:231


AuthorityUnavailableCode

AuthorityUnavailableCode = "grant_source_failed" | "invalid_grant_material" | "grant_scope_mismatch" | "grant_limit_exceeded"

Defined in: packages/core/src/authority.ts:170

Why authority could not be established for one decision.


AuthorizationReasonCode

AuthorizationReasonCode = "allowed" | "invalid_context" | "invalid_request" | "no_matching_grant" | "grant_exhausted" | "delegation_chain_invalid" | "authority_unavailable" | "delegation_chain_unverified" | "usage_store_unavailable" | "host_policy_denied" | "host_policy_unavailable"

Defined in: packages/core/src/authorization.ts:37


CapabilityRequestPayload

CapabilityRequestPayload = Pick<CapabilityRequest, "capabilities" | "purpose" | "constraints" | "metadata">>

Defined in: packages/core/src/capability-request.ts:18

What a caller may say about the authority it asks for.

Everything else on a CapabilityRequest is the kernel's to state. A whole request is accepted here too -- the requiredAuthority a denial described is the usual one -- and the id, namespaceId, requester, owner, and requestedAt it carries are discarded and minted again from the trusted context. That is why { requestedAuthority: denial.requiredAuthority } comes back with the identifier it went in with: both were minted from the same ask.


ConstraintEnvelopeField

ConstraintEnvelopeField = "purposes" | "notBefore" | "expiresAt"

Defined in: packages/core/src/constraints.ts:13

The fields that bound when and for what a capability may be used.

These three are ordered: one window sits inside another, one purpose set is a subset of another. maxUses and delegationDepth are budgets, spent where they are counted -- the usage store and the delegation chain -- and a containment check has nothing to say about them.


DelegationRefusal

DelegationRefusal = "empty_capabilities" | "id_collides_with_parent" | "bounded_parent_not_delegable" | "parent_not_delegable" | "depth_exhausted" | "capability_not_within_parent" | "purpose_not_within_parent" | "window_not_within_parent" | "issued_before_parent"

Defined in: packages/core/src/delegation.ts:277

Why a delegation was refused at the point it was issued.


DelegationUnverifiedCode

DelegationUnverifiedCode = "resolver_unavailable" | "parent_not_found" | "resolver_failed"

Defined in: packages/core/src/delegation.ts:48

The chain could not be established, which is never treated as valid.


DelegationValidation

DelegationValidation = { chain: readonly string[]; status: "valid"; } | { chain: readonly string[]; code: DelegationViolationCode; grantId: string; status: "invalid"; } | { chain: readonly string[]; code: DelegationUnverifiedCode; grantId: string; status: "unverified"; }

Defined in: packages/core/src/delegation.ts:51


DelegationViolationCode

DelegationViolationCode = "delegation_not_permitted" | "delegation_depth_exceeded" | "bounded_parent_not_delegable" | "issuer_not_parent_subject" | "namespace_mismatch" | "parent_inactive" | "capability_widened" | "constraints_widened" | "chain_cycle" | "chain_too_long"

Defined in: packages/core/src/delegation.ts:35

A structural rule the presented chain broke.


DeriveGrantResult

DeriveGrantResult = { grant: CapabilityGrant; ok: true; } | { ok: false; reason: DelegationRefusal; }

Defined in: packages/core/src/delegation.ts:288


GrantRejectionReason

GrantRejectionReason = "issuer" | "subject" | "namespace" | "window" | "purpose" | "verifier" | "capability" | "delegation" | "exhausted"

Defined in: packages/core/src/authorization.ts:76

The first condition a resolved grant failed, in the order they are checked.

These are the causes the no_matching_grant checklist enumerates, and a denial names them only to the host. A caller learns that it may not proceed; which of its grants nearly matched, and how, is the host's to see.


GrantScopeMismatch

GrantScopeMismatch = "namespace" | "subject" | "issuer"

Defined in: packages/core/src/authority.ts:224

Which of the three scope conditions a loaded grant failed.

issuer is the one people hit: context.authority is whose grants are being exercised, which on a delegated chain is the delegator and not the owner of the data. The caller is told only authority_unavailable; this reaches the host through the authority.resolved audit event.


HostCeilingVerdict

HostCeilingVerdict = AllowedDecision | HostPolicyDenial

Defined in: packages/core/src/authorization.ts:163

The only two things a ceiling may say: the decision it was handed, or no.

Widening is inexpressible rather than forbidden. A ceiling is handed an AllowedDecision and can therefore never receive a denial to turn into an allow; the allow arm it may return is pinned to reasonCode: "allowed" and requires a matchedGrantId, which CapabilityAuthorizer checks is the one it handed over. Anything else is a malfunction and fails closed as host_policy_unavailable. A host outside TypeScript is held to the same at runtime, where a foreign reasonCode on a refusal is replaced rather than carried.


HostPolicy

HostPolicy = unknown

Defined in: packages/core/src/authority.ts:111

What a turn's host policy is, to SharedOS: nothing it reads.

Whatever a PolicySource loaded, carried beside the resolved authority and handed back to the host's own HostCeiling as the fourth argument of narrow. It is never cloned, validated, hashed, or audited: a policy may be a compiled matcher or a table with methods on it, and SharedOS decides nothing from it -- the ceiling does. A host pairs the two ports itself, and the pairing is the host's to get right (ADR 0020). The one thing read is the version the source states beside it (LoadedPolicy), and that is what audit records -- never the policy.


PolicyResolution

PolicyResolution<Policy> > = { policy: Policy; status: "loaded"; version: string; } | { status: "unavailable"; }

Defined in: packages/core/src/authority.ts:165

The policy one turn decides against, or the fact that it could not be loaded.

Held beside the grant set for the length of the turn, so a source that failed at the boundary stays failed for every decision in the turn rather than being retried on each and possibly changing its mind -- the same rule an unavailable GrantSource is held to.

Type Parameters

Type ParameterDefault type
PolicyHostPolicy

ProviderErrorKind

ProviderErrorKind = "tool" | "tool_catalog" | "resource" | "message" | "policy"

Defined in: packages/core/src/diagnostics.ts:40

Which of the kernel's mediated operations a contained throw happened under.


ProviderErrorReporter

ProviderErrorReporter = (error, operation) => void

Defined in: packages/core/src/diagnostics.ts:127

A host's sink for a throw the kernel contained rather than propagated.

A provider, tool handler, transport, or router that throws is answered with a fixed reason code and a fixed message: the operation fails closed and the agent is told a bounded fact about it. That is the right thing to put on the wire and the wrong place to put a stack, so the error itself comes here for a host's own logs, as thrown.

One case is wrapped rather than as-thrown, and it is worth knowing which. When a ContextToolProvider's listTools throws, the kernel replaces it with one catalogue-failure sentence -- every caller of the catalogue reads that one -- and the provider's error becomes its cause. A tool_catalog report from any other origin, such as a returned handler the registry refuses, carries that error unwrapped and has no cause. Log error and let a formatter walk it; do not read cause on its own.

It reaches nothing else. Audit records the outcome and the reason code and has never carried call data; a thrown message may contain arguments, rows, or credentials the thrower had in scope, and routing it into an audit sink or a protocol error would be a disclosure the rest of the design spends its effort preventing.

Observational. One that throws is ignored, and a kernel with none installed takes the same decisions. A cancelled operation is not reported: every site that awaits a host port re-throws the abort ahead of the containment, and the three that do not -- an argument parser, a requirement resolver, a message capability resolver -- wrap synchronous code that is never handed the signal, so an abort cannot be what made them throw. A caller that stopped the work is not a defect to diagnose.

Parameters

ParameterType
errorunknown
operationProviderErrorContext

Returns

void


SpanAttributes

SpanAttributes = Readonly<Record<string, string | number | boolean>>>>

Defined in: packages/core/src/spans.ts:34

What a span may say about itself.

Identifiers, tool names, and outcomes. Never arguments, never results, never payloads -- the same redaction rule the audit trail follows, for the same reason: a measurement sink is not an authorized reader of anything a call carried, and a span that leaked one would be a disclosure channel opened by turning measurement on.


SpanName

SpanName = typeof SPAN[keyof typeof SPAN]

Defined in: packages/core/src/spans.ts:188


TurnAuthorityScope

TurnAuthorityScope = object

Defined in: packages/core/src/authority.ts:73

A handle on one turn's frozen authority.

The handle reports whether authority could be established at the turn boundary so a caller can refuse admission, and carries the snapshot the whole turn will be decided against. It deliberately exposes no grants: like ResolvedAuthority, it is not assignable to an AccessContext, so it cannot reach a provider, tool handler, transport, or runtime.

close is idempotent and must run on every path out of the turn, including cancellation. An unclosed lease keeps a stale authority state answering for any later operation that presents the same turn identity.

Properties

code?

readonly optional code?: AuthorityUnavailableCode

Defined in: packages/core/src/authority.ts:78

Present when it was not.

snapshot?

readonly optional snapshot?: AuthoritySnapshot

Defined in: packages/core/src/authority.ts:76

Present when authority was established.

status

readonly status: "resolved" | "unavailable"

Defined in: packages/core/src/authority.ts:74

Methods

close()

close(): void

Defined in: packages/core/src/authority.ts:79

Returns

void

Variables

AGENT_INVOKE_ACTION

const AGENT_INVOKE_ACTION: "invoke" = "invoke"

Defined in: packages/core/src/kernel.ts:235


CATALOG_HASH_FIELDS

const CATALOG_HASH_FIELDS: readonly string[]

Defined in: packages/core/src/published-tool.ts:27

The fields of a published tool that catalogHash is computed over.

This list is the contract, not an implementation detail. Two hosts can both claim to compute catalogHash and disagree on every value unless participation is fixed somewhere, so it is fixed here and asserted by publishToolDefinition, which cannot emit a key outside it.

What is deliberately absent is everything that varies with how a catalogue was delivered rather than what it contains: executionId, the harness-side alias, the runtime name, the transport. Two harnesses handed the same tools must hash identically, or the hash cannot be used to prove they were compared on equal terms -- which is the only reason it exists.


DEFAULT_MAX_DELEGATION_CHAIN_LENGTH

const DEFAULT_MAX_DELEGATION_CHAIN_LENGTH: 16 = 16

Defined in: packages/core/src/delegation.ts:20

The longest ancestor chain SharedOS will walk before failing closed.


DIRECTORY_NAMESPACE

const DIRECTORY_NAMESPACE: "sharedos" = "sharedos"

Defined in: packages/core/src/agent-card.ts:17

Kernel affordances live in one namespace; the directory is the second one.


DIRECTORY_READ_ACTION

const DIRECTORY_READ_ACTION: "read" = "read"

Defined in: packages/core/src/agent-card.ts:20


DIRECTORY_RESOURCE_ROOT

const DIRECTORY_RESOURCE_ROOT: readonly string[]

Defined in: packages/core/src/agent-card.ts:19

The resource every card hangs beneath, and the one a host grants over.


EXECUTION_NAMESPACE

const EXECUTION_NAMESPACE: "sharedos.execution" = "sharedos.execution"

Defined in: packages/core/src/kernel.ts:234


INFRASTRUCTURE_DENIAL_REASONS

const INFRASTRUCTURE_DENIAL_REASONS: readonly AuthorizationReasonCode[]

Defined in: packages/core/src/authorization.ts:58

Denials caused by SharedOS being unable to establish a fact, not by policy.

Fail-closed behaviour makes these look like denials at the call site. An experiment must separate them from expected permission denials before computing any rate, so they are named once here and marked failClosed in the audit record.


MAX_RESOLVED_GRANTS

const MAX_RESOLVED_GRANTS: 256 = 256

Defined in: packages/core/src/authority.ts:8

The largest authority set SharedOS will evaluate for one decision.


MESSAGE_REQUEST_TOOL_DEFINITION

const MESSAGE_REQUEST_TOOL_DEFINITION: ToolDefinition

Defined in: packages/core/src/message-tool.ts:25


MESSAGE_REQUEST_TOOL_NAME

const MESSAGE_REQUEST_TOOL_NAME: "messages.request" = "messages.request"

Defined in: packages/core/src/message-tool.ts:23


MESSAGE_SEND_ACTION

const MESSAGE_SEND_ACTION: "send" = "send"

Defined in: packages/core/src/message-service.ts:13


MESSAGE_TOOL_NAMESPACE

const MESSAGE_TOOL_NAMESPACE: "messages" = "messages"

Defined in: packages/core/src/message-tool.ts:22


MESSAGING_NAMESPACE

const MESSAGING_NAMESPACE: "sharedos.messaging" = "sharedos.messaging"

Defined in: packages/core/src/message-service.ts:12


MID_TURN_AUTHORITY_REFRESH

const MID_TURN_AUTHORITY_REFRESH: false = false

Defined in: packages/core/src/authority.ts:38

The fuse over per-operation authority resolution. Off.

SharedOS originally re-loaded authority from the trusted source for every kernel operation, so a grant removed from the store part-way through a turn was refused at the next decision inside that same turn. That path is retained in SharedOSKernel and is re-enabled by setting this to true.

It is off because a turn must decide against one grant set. Authority is resolved once, at the turn boundary, and a store-side edit -- a revocation, a withdrawn purpose -- is observed by the next turn. A request therefore carries the authority it was admitted with, rather than having authority resolved underneath it while it runs.

The fuse no longer covers expiry. ADR 0016 settled the question this constant used to carry as a TBD: expiry is a property the grant already held when the turn began, so honouring it part-way through costs no store read and leaks no store state, and grantIsActive in internal.ts now evaluates it against the instant of the operation while every other removal stays at the instant the turn's authority was resolved. Nothing about that needs this fuse, which is why it stays off.

What remains behind it is exactly one behaviour: seeing a store edit without waiting for the next turn. A host cannot set it: it is an exported constant, a build-time switch for this package's maintainers, and turning it on means patching the package. Whether it becomes a kernel option, with the store read per operation that implies, is an open item (docs/open-items.md).


SPAN

const SPAN: Readonly<{ AUTHORITY_LOAD: "kernel.authority.load"; AUTHORIZE: "kernel.authorize"; MCP_HANDLE: "mcp.handle"; TOOL_CATALOGUE: "kernel.tool.catalogue"; TOOL_DISCOVER: "kernel.tool.discover"; TOOL_HANDLER: "kernel.tool.handler"; TOOL_INVOKE: "kernel.tool.invoke"; TOOL_MEDIATE: "envelope.tool.mediate"; TURN: "envelope.turn"; }>

Defined in: packages/core/src/spans.ts:167

The spans SharedOS emits, named once so a sink and a report agree.

TOOL_HANDLER is the odd one and the important one: it is the only span here that measures work SharedOS does not own. A resource provider's read is the host's storage, not enforcement, and an end-to-end figure that included it would report the host's disk as a SharedOS cost. It is emitted so it can be taken back out, correlated by the callId every span on one call carries.

Functions

addressesEqual()

addressesEqual(left, right): boolean

Defined in: packages/core/src/internal.ts:144

Parameters

ParameterType
left{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
right{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

Returns

boolean


addressPath()

addressPath(address): ["human" | "agent" | "group" | "service", string]

Defined in: packages/core/src/message-service.ts:71

Stable, segment-safe grant path for recipient-scoped messaging.

Parameters

ParameterType
address{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

Returns

["human" | "agent" | "group" | "service", string]


agentCardCapability()

agentCardCapability(subject, owner, view?): object

Defined in: packages/core/src/agent-card.ts:50

The capability a reader needs to be served one view of one subject's card.

Issued per subject. A host that wants a reader to see a whole directory issues directoryCapability instead.

Parameters

ParameterTypeDefault value
subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }undefined
owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }undefined
view"reach" | "identity" | "namespaces""reach"

Returns

object

actions

actions: string[]

resource

resource: object

resource.namespace

namespace: string

resource.owner?

optional owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

resource.path

path: string[]

scope

scope: "exact" | "descendants"


agentCardPath()

agentCardPath(subject, view?): string[]

Defined in: packages/core/src/agent-card.ts:39

The resource one view of one subject's card is served from.

The widest card -- identity together with reach -- is the subject's own path, so a grant written per subject with exact scope serves it. Each narrower view is a distinct resource beneath it, which is how a less-authorized reader gets less without any redaction pass: a grant over ["directory", "agent", "bob", "identity"] serves a name and cannot be substituted for the card, and a descendants grant over the subject or over ["directory"] covers every view of what it covers.

Expressing the views as resources rather than as fields is a deliberate departure from ADR 0021, which writes them as PR #35's field-level governed views. #35 is unmerged, and the two land in the same place: a view is named, matching is exact and never substitutive, and the coarse answer is its own name rather than a filter inside reach.

Parameters

ParameterTypeDefault value
subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }undefined
view"reach" | "identity" | "namespaces""reach"

Returns

string[]


agentCardRequest()

agentCardRequest(subject, owner, view): AuthorizationRequest

Defined in: packages/core/src/agent-card.ts:79

The authorization one card read is decided on.

Parameters

ParameterType
subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
view"reach" | "identity" | "namespaces"

Returns

AuthorizationRequest


agentExecutionCapability()

agentExecutionCapability(agent, owner): object

Defined in: packages/core/src/kernel.ts:237

Parameters

ParameterType
agent{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

Returns

object

actions

actions: string[]

resource

resource: object

resource.namespace

namespace: string

resource.owner?

optional owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

resource.path

path: string[]

scope

scope: "exact" | "descendants"


applyToolNamespaceUpdate()

applyToolNamespaceUpdate(current, update): string[]

Defined in: packages/core/src/tool-namespace-control.ts:20

Apply the standard idempotent patch semantics used by host stores.

Parameters

ParameterType
currentreadonly string[]
update{ disable?: string[]; enable?: string[]; }
update.disable?string[]
update.enable?string[]

Returns

string[]


auditEvent()

auditEvent(context, event, createId?): AuditEvent

Defined in: packages/core/src/audit.ts:143

One audit record, stamped from the trusted context.

createId mints the record's identity. The default is a random UUID from Web Crypto, so the kernel stays host-neutral; a host that needs a deterministic trail -- a replayed fixture, a conformance run -- supplies its own, and supplies one that never repeats, because two records with one id are one record to every sink that deduplicates.

Parameters

ParameterTypeDefault value
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }undefined
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }undefined
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }undefined
context.enabledToolNamespacesstring[]undefined
context.namespaceIdstringundefined
context.nowstringundefined
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }undefined
context.purposestringundefined
context.traceIdstringundefined
eventAuditEventInputundefined
createId() => stringrandomAuditEventId

Returns

AuditEvent


buildToolCatalog()

buildToolCatalog(definitions, options): Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

Defined in: packages/core/src/published-tool.ts:138

Build the per-turn catalogue a harness is served, hash included.

Parameters

ParameterType
definitionsreadonly object[]
optionsToolCatalogOptions

Returns

Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>


canonicalJson()

canonicalJson(value): string

Defined in: packages/core/src/internal.ts:4

Structural JSON equality for protocol values with unordered object keys.

Parameters

ParameterType
valueunknown

Returns

string


capabilityIntersectsCeiling()

capabilityIntersectsCeiling(capability, ceiling, context): boolean

Defined in: packages/core/src/authorization.ts:927

Parameters

ParameterType
capability{ actions: string[]; resource: { namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }; scope: "exact" | "descendants"; }
capability.actionsstring[]
capability.resource{ namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }
capability.resource.namespacestring
capability.resource.owner?{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
capability.resource.pathstring[]
capability.scope"exact" | "descendants"
ceilingAuthorizationRequest
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring

Returns

boolean


capabilityIsWithin()

capabilityIsWithin(capability, ancestor, context): boolean

Defined in: packages/core/src/delegation.ts:212

True when every access capability permits is also permitted by ancestor.

The one containment predicate, exported so that nothing has to write a second one. Namespace, resolved owner, action set, and path by segment -- with an exact ancestor covering only its own path and a descendants ancestor covering everything beneath it. ADR 0008 has already paid for what happens when two definitions of "narrower" drift, and a containment rule that is right in one place and approximate in another is worse than one that is missing.

Only the owner is read off the context, so a caller that has resolved an owner without holding a whole access context -- precedent admission, ADR 0022 R2 -- passes { owner }. An unowned resource on either side resolves against it, which is what makes "the same owner" a comparison rather than a guess.

This is the deciding-side question: is capability within ancestor in this context. The issuing side asks whether it holds in every context, which is a stricter question with its own predicate inside deriveGrant.

Parameters

ParameterType
capability{ actions: string[]; resource: { namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }; scope: "exact" | "descendants"; }
capability.actionsstring[]
capability.resource{ namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }
capability.resource.namespacestring
capability.resource.owner?{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
capability.resource.pathstring[]
capability.scope"exact" | "descendants"
ancestor{ actions: string[]; resource: { namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }; scope: "exact" | "descendants"; }
ancestor.actionsstring[]
ancestor.resource{ namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }
ancestor.resource.namespacestring
ancestor.resource.owner?{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
ancestor.resource.pathstring[]
ancestor.scope"exact" | "descendants"
contextPick<AccessContext, "owner">

Returns

boolean


capabilityMatches()

capabilityMatches(capability, request, context): boolean

Defined in: packages/core/src/authorization.ts:899

Parameters

ParameterType
capability{ actions: string[]; resource: { namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }; scope: "exact" | "descendants"; }
capability.actionsstring[]
capability.resource{ namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }
capability.resource.namespacestring
capability.resource.owner?{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
capability.resource.pathstring[]
capability.scope"exact" | "descendants"
requestAuthorizationRequest
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring

Returns

boolean


catalogHash()

catalogHash(tools): Promise<string>>

Defined in: packages/core/src/published-tool.ts:121

A stable identifier for one effective, model-facing tool catalogue.

catalogHash = SHA-256(canonical JSON(tools sorted by canonical name))

Canonicalisation is canonicalJson: object keys sorted, no incidental whitespace, so a host that serialises its schemas in a different key order still produces the same hash. Field participation is CATALOG_HASH_FIELDS.

The hash answers one question -- were these harnesses given the same semantic tool set? -- and answers it against schema drift, a missing tool, a renamed tool, and a stale discovery cache alike.

Parameters

ParameterType
toolsreadonly object[]

Returns

Promise<string>


composeAgentCard()

composeAgentCard(view, subject, context, reach): { namespaceId: string; reach: object[]; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "reach"; } | { namespaceId: string; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "identity"; } | { namespaceId: string; namespaces: object[]; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "namespaces"; }

Defined in: packages/core/src/agent-card.ts:166

Compose the served view, and hold it to the card contract.

The projection happens here and nowhere else: a view is built from the fields it declares rather than assembled whole and redacted, so there is no shape in which a wider card exists on its way to a narrower reader. identity never receives a reach at all, because the kernel does not load the subject's grants for it.

A card that does not parse is a defect in this function rather than anything a caller did, and it throws rather than serving a half-built one.

Parameters

ParameterType
view"reach" | "identity" | "namespaces"
subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
reachreadonly object[]

Returns

{ namespaceId: string; reach: object[]; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "reach"; } | { namespaceId: string; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "identity"; } | { namespaceId: string; namespaces: object[]; readAt: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; view: "namespaces"; }


constraintEnvelopeViolation()

constraintEnvelopeViolation(inner, outer): ConstraintEnvelopeField | undefined

Defined in: packages/core/src/constraints.ts:29

The first field on which inner reaches outside outer, or undefined when inner is within outer.

One ordering, written once. An absent bound on outer admits anything; a present one requires the same bound on inner, readable and at least as tight: an expiry no later, a start no earlier, purposes that are a subset. A present timestamp that does not parse, on either side, violates its field rather than counting as absent, because a bound that cannot be read must not read as unbounded.

Fields are checked in the order they are declared, so a caller that reports one violation reports the same one every time.

Parameters

ParameterType
inner{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }
inner.delegationDepth?number
inner.expiresAt?string
inner.maxUses?number
inner.notBefore?string
inner.purposes?string[]
outer{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }
outer.delegationDepth?number
outer.expiresAt?string
outer.maxUses?number
outer.notBefore?string
outer.purposes?string[]

Returns

ConstraintEnvelopeField | undefined


constraintsAreWithin()

constraintsAreWithin(inner, outer): boolean

Defined in: packages/core/src/constraints.ts:57

True when every use inner admits, outer admits too.

The boolean of constraintEnvelopeViolation, for callers with nothing to report about which field failed.

Parameters

ParameterType
inner{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }
inner.delegationDepth?number
inner.expiresAt?string
inner.maxUses?number
inner.notBefore?string
inner.purposes?string[]
outer{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }
outer.delegationDepth?number
outer.expiresAt?string
outer.maxUses?number
outer.notBefore?string
outer.purposes?string[]

Returns

boolean


deriveGrant()

deriveGrant(parent, request): DeriveGrantResult

Defined in: packages/core/src/delegation.ts:371

Derive a narrower grant from one the delegator already holds.

This is the supported way to produce a grant whose issuer is not the resource owner. It is a pure function: it never consults a store, never mints authority the parent does not carry, and refuses rather than clamping when a request would exceed the parent — a silently clamped delegation reads as accepted, and the delegator then believes it passed on more than it did.

What it produces is a claim, not a decision. The derived grant names only its immediate parent, and validateDelegationChain re-resolves the ancestors from the issuing store at every use, because narrowing settles here but revocation happens afterwards. Deriving a grant is therefore never sufficient on its own: a host that issues one must also install a DelegationChainResolver.

Parameters

ParameterType
parent{ capabilities: object[]; constraints: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; issuedAt: string; issuer: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; metadata?: JsonObject; namespaceId: string; parentGrantId?: string; revokedAt?: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }
parent.capabilitiesobject[]
parent.constraints{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }
parent.constraints.delegationDepth?number
parent.constraints.expiresAt?string
parent.constraints.maxUses?number
parent.constraints.notBefore?string
parent.constraints.purposes?string[]
parent.idstring
parent.issuedAtstring
parent.issuer{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
parent.metadata?JsonObject
parent.namespaceIdstring
parent.parentGrantId?string
parent.revokedAt?string
parent.subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
requestDeriveGrantRequest

Returns

DeriveGrantResult


describeRequiredAuthority()

describeRequiredAuthority(context, request): Promise<{ capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; } | undefined>>

Defined in: packages/core/src/capability-request.ts:98

The authority that would have satisfied a request nothing matched.

Every field is already in hand at the point of denial -- the caller named the resource and the action, and its own context names the requester, the owner, the namespace, and the purpose -- so nothing is resolved and no port is called. That is what keeps this affordable on a denial path and what keeps it from revealing anything: it restates the request rather than answering a question about the world (ADR 0019).

Exactly one capability, always. The schema's bound of 64 is there for a host-built consent request that legitimately asks for several; this describes the one resource and one action the caller named, and a second entry could only be a guess at what else it might have wanted.

Parameters

ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
requestAuthorizationRequest

Returns

Promise<{ capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; } | undefined>


directoryCapability()

directoryCapability(owner): object

Defined in: packages/core/src/agent-card.ts:70

The capability a reader needs to be served every card in a world.

This is the enumeration grant, and it is meant to look like one. Holding it is what makes the directory answer "does this agent exist" in bulk, which is the reason reading a card is gated at all: without a gate every actor that can reach the kernel holds this implicitly.

Parameters

ParameterType
owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

Returns

object

actions

actions: string[]

resource

resource: object

resource.namespace

namespace: string

resource.owner?

optional owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

resource.path

path: string[]

scope

scope: "exact" | "descendants"


formatCatalogHash()

formatCatalogHash(hash): string

Defined in: packages/core/src/published-tool.ts:129

The hash as an experiment record renders it: algorithm-qualified.

Parameters

ParameterType
hashstring

Returns

string


hashJson()

hashJson(value): Promise<string>>

Defined in: packages/core/src/hashing.ts:12

A stable content identifier for any JSON-safe value.

Object key order never changes the result, so two hosts that serialize the same state differently still produce the same identifier. Web Crypto is used rather than node:crypto so the kernel stays host-neutral.

Parameters

ParameterType
valueunknown

Returns

Promise<string>


isInfrastructureDenial()

isInfrastructureDenial(reasonCode): boolean

Defined in: packages/core/src/authorization.ts:65

Parameters

ParameterType
reasonCodestring

Returns

boolean


measure()

measure<T>>(sink, name, operation, describe?): Promise<T>>

Defined in: packages/core/src/spans.ts:92

Run an operation, and report how long the part SharedOS owns took.

With no sink this is one comparison and a direct call: operation is invoked and its own promise handed back untouched, so an uninstrumented host pays nothing for the call sites existing.

That property is the reason operation must be an ordinary arrow that returns a promise rather than an async one that awaits inside. An async callback allocates a second promise and two microtask hops on every call, measured or not, and eight of those on the path of one tool call is a real cost charged to hosts that never asked to be measured. Attributes only knowable from the result go to describe, which runs solely when there is a sink to report to.

Nested spans are reported whole and are not subtracted from one another here. A span that contains foreign work -- a resource provider, a host's storage -- is separated from it by naming that work in its own span and correlating the two afterwards on a shared identifier. Doing the subtraction inside would need an ambient stack, and an ambient stack is wrong the first time two turns are in flight at once.

Type Parameters

Type Parameter
T

Parameters

ParameterType
sinkSpanSink | undefined
namestring
operation(scope) => Promise<T>
describe?(value, scope) => void

Returns

Promise<T>


measureSync()

measureSync<T>>(sink, name, operation): T

Defined in: packages/core/src/spans.ts:102

measure for an operation that does not await.

Type Parameters

Type Parameter
T

Parameters

ParameterType
sinkSpanSink | undefined
namestring
operation(scope) => T

Returns

T


messageSendCapability()

messageSendCapability(receiver, owner): object

Defined in: packages/core/src/message-service.ts:15

Parameters

ParameterType
receiver{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

Returns

object

actions

actions: string[]

resource

resource: object

resource.namespace

namespace: string

resource.owner?

optional owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

resource.path

path: string[]

scope

scope: "exact" | "descendants"


mintCapabilityRequest()

mintCapabilityRequest(context, payload): Promise<{ capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; } | undefined>>

Defined in: packages/core/src/capability-request.ts:53

Mint a request for authority from the trusted context and what was asked.

namespaceId, requester, owner, and requestedAt come from the context and nothing else: a request the caller authored would be a caller-chosen correlation for a decision the kernel made (ADR 0019).

id is derived rather than generated -- SHA-256 over the namespace, requester, owner, purpose, constraints, and capabilities -- so the same ask describes itself the same way twice. requestedAt is deliberately not part of it: it is the instant of the authority a decision was made against, stable within a turn but moving between turns that describe the same missing authority, and moving on every conformance run. Hashing only the ask is what gives one missing authority one identifier across turns, and what keeps a conformance cell able to state the value it observed rather than that a field was present. metadata is not part of it either: it annotates an ask, and does not make it a different one.

undefined when what was asked is not a valid ask -- no capabilities, a purpose the schema refuses -- so the caller decides whether that is a thrown contract violation or a field to omit.

Parameters

ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
payloadCapabilityRequestPayload

Returns

Promise<{ capabilities: object[]; constraints?: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; metadata?: JsonObject; namespaceId: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; requestedAt: string; requester: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; } | undefined>


portableToolName()

portableToolName(name): string

Defined in: packages/core/src/published-tool.ts:161

The canonical name rewritten for a transport that cannot carry a dot.

Provided because harnesses do this anyway and an unowned rewrite is worse than an owned one. It is transport presentation only: it is not the tool's identity, it is not what catalogHash covers, and nothing may authorize against it. SharedOS maps a harness alias back to the canonical name before the call reaches the kernel; the alias may be recorded diagnostically, and that is the whole of its role.

Parameters

ParameterType
namestring

Returns

string


publishToolCatalog()

publishToolCatalog(definitions): readonly object[]

Defined in: packages/core/src/published-tool.ts:91

Project a permission-filtered catalogue, in canonical order.

Sorting is part of the projection rather than of the hash, so the tools a harness receives and the tools that were hashed are in the same order and can be compared by eye. Duplicate names are rejected here: a catalogue that publishes one name twice has already lost the property the whole boundary rests on, that a name identifies exactly one operation.

Parameters

ParameterType
definitionsreadonly object[]

Returns

readonly object[]


publishToolDefinition()

publishToolDefinition(definition): object

Defined in: packages/core/src/published-tool.ts:51

Project one registered tool into what a harness is allowed to see.

Everything authorization-bearing is dropped rather than redacted: requiredCapability, resolveRequirement, and the handler itself never leave SharedOS. A harness therefore cannot infer what authority a call would need, and could not use the answer if it could -- the requirement is re-resolved from the arguments at invocation time, so two calls to one published tool routinely need different authority.

readWrite is a required classification on every registration, so readOnlyHint is always determined. destructiveHint and idempotentHint appear only when the registration stated them: emitting a guess would put an unfixed value into catalogHash.

Parameters

ParameterType
definition{ annotations?: { destructive?: boolean; idempotent?: boolean; readOnly?: boolean; }; description: string; inputSchema: JsonObject; metadata?: JsonObject; name: string; namespace: string; outputSchema?: JsonObject; readWrite: "read" | "write"; requiredCapability: { action: string; resource: { namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }; }; source: string; }
definition.annotations?{ destructive?: boolean; idempotent?: boolean; readOnly?: boolean; }
definition.annotations.destructive?boolean
definition.annotations.idempotent?boolean
definition.annotations.readOnly?boolean
definition.descriptionstring
definition.inputSchemaJsonObject
definition.metadata?JsonObject
definition.namestring
definition.namespacestring
definition.outputSchema?JsonObject
definition.readWrite"read" | "write"
definition.requiredCapability{ action: string; resource: { namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }; }
definition.requiredCapability.actionstring
definition.requiredCapability.resource{ namespace: string; owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; path: string[]; }
definition.requiredCapability.resource.namespacestring
definition.requiredCapability.resource.owner?{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
definition.requiredCapability.resource.pathstring[]
definition.sourcestring

Returns

object

annotations?

optional annotations?: object

annotations.destructiveHint?

optional destructiveHint?: boolean

annotations.idempotentHint?

optional idempotentHint?: boolean

annotations.openWorldHint?

optional openWorldHint?: boolean

annotations.readOnlyHint?

optional readOnlyHint?: boolean

description

description: string

inputSchema

inputSchema: JsonObject

metadata?

optional metadata?: object

metadata.namespace?

optional namespace?: string

metadata.source?

optional source?: string

name

name: string

outputSchema?

optional outputSchema?: JsonObject


reachThroughTools()

reachThroughTools(reach, tools): readonly object[]

Defined in: packages/core/src/reach.ts:23

The part of a reach a catalogue of tools can act on.

Grant reach says where an actor is authorized. A runtime acts only through the tools it was handed, so for a turn the two are not the same: a place no offered tool operates on is not somewhere the turn can work, and naming it would send a model at a wall. This keeps the entries whose namespace some offered tool requires a capability over, and drops the rest.

Keyed on the resource namespace a tool operates on, not on the tool's own namespace. They are different vocabularies -- the message tool lives in messages and operates on sharedos.messaging -- so a filter on AccessContext.enabledToolNamespaces would drop reach the turn has and keep reach it does not. Nothing is narrowed within an entry: a tool's requiredCapability.action is a discovery ceiling, not the action a call is authorized against, so actions are left as the grants state them.

Descriptive, never permissive: every call is authorized independently, so an entry this keeps is not a permission and an entry it drops was not a refusal.

Parameters

ParameterType
reachreadonly object[]
toolsreadonly object[]

Returns

readonly object[]


reportContainedError()

reportContainedError<Context>>(report, error, context): void

Defined in: packages/core/src/diagnostics.ts:24

Call one diagnostic sink without letting it change what happened.

Exported deliberately, and it is the guard rather than a convenience: a host or package offering a hook of this shape should not reimplement the swallow rule, because two implementations of one promise is how it stops being true in one of them. @aicoo/sharedos-runtime uses it for exactly that reason.

The guard behind the synchronous "here is the error we contained" hooks -- SharedOSKernelOptions.onProviderError and the runtime's onTurnError -- generic over the context each one carries so there is one implementation of the rule rather than one per hook. A sink that throws is swallowed: a diagnostic that can turn one failure into two is a liability, and a host would be right to weigh installing it against the risk. There is no risk.

Synchronous is the reason onAuditError is not among them and keeps a guard of its own. That one is awaited because it fires after the side effect, where there is nothing left to hold up; every sink called through here fires mid-flight, with a result still to construct and return, so awaiting a host's logger would put its latency on the path of every failed call.

Type Parameters

Type Parameter
Context

Parameters

ParameterType
report((error, context) => void) | undefined
errorunknown
contextContext

Returns

void


sha256Hex()

sha256Hex(value): Promise<string>>

Defined in: packages/core/src/hashing.ts:16

Parameters

ParameterType
valuestring

Returns

Promise<string>


subjectCardContext()

subjectCardContext(reader, subject): object

Defined in: packages/core/src/agent-card.ts:123

The context a subject's own grants are loaded under, derived from the reader's.

Computing a subject's reach needs grants that are not the caller's, and a GrantSource answers for context.actor. So the kernel derives a second context from the reader's own -- same namespaceId, same now, same authority, same purpose and trace -- with actor set to the subject. That is not a workaround for the contract; it is the contract doing the bounding:

  • One authority. AccessContext.authority already scopes what a GrantSource may answer with, so a card shows what the subject holds under the authority the reader is itself operating under, not the subject's whole life. It costs no new field.
  • One world. The derived context carries the reader's namespaceId, so a card read in one namespace never describes reach in another.

The obligation this puts on a host is the one thing about cards that needs saying loudly: a GrantSource that reads an ambient session user instead of context.actor now answers with the wrong principal's grants. SharedOS catches the loud form of that mistake -- TrustedAuthorityResolver refuses a grant whose subject is not context.actor, so a source that hands back the reader's grants fails closed as grant_scope_mismatch rather than serving a card of the wrong agent. It cannot catch the quiet form: a source that filters by session and finds nothing answers with an empty grant set, and an empty card is a card that understates.

The ResolvedAuthority this produces is used for exactly one thing, shaping reach, and authorizes nothing. ADR 0009's wrapper is what makes that checkable rather than promised: it is not assignable to AccessContext, so a subject's grants cannot reach a provider, a handler, or a runtime by accident.

Parameters

ParameterType
reader{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
reader.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
reader.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
reader.enabledToolNamespacesstring[]
reader.namespaceIdstring
reader.nowstring
reader.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
reader.purposestring
reader.traceIdstring
subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

Returns

object

actor

actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

authority

authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

enabledToolNamespaces

enabledToolNamespaces: string[]

namespaceId

namespaceId: string

now

now: string

owner

owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

purpose

purpose: string

traceId

traceId: string


summarizeReach()

summarizeReach(reach): object[]

Defined in: packages/core/src/agent-card.ts:134

Which namespaces a reach touches and how much of each, with no paths.

The coarse view's whole content. entries counts reach entries rather than resources: collapsing a descendants entry into a resource count would mean asking a provider what exists, which is the lookup a card must never become.

Parameters

ParameterType
reachreadonly object[]

Returns

object[]


tightestConstraints()

tightestConstraints(sets): { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; } | undefined

Defined in: packages/core/src/constraints.ts:79

The tightest envelope every set admits, or undefined when they admit nothing in common.

The meet of the ordering constraintEnvelopeViolation checks: the earliest expiry, the latest start, the intersection of purposes, the fewest uses, the shallowest delegation. An absent bound on one set is not a bound of zero -- an approval with no expiry does not stop a co-cited approval's expiry from being the tightest one -- so absent bounds are skipped, and the meet of no sets is unbounded.

Disjoint bounds have no envelope. Purposes that intersect to nothing, a window whose start is past its end, or a timestamp that cannot be read all yield undefined rather than a clamped or guessed bound.

Parameters

ParameterType
setsreadonly object[]

Returns

{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; } | undefined


toResourceOperation()

toResourceOperation(context, request): object

Defined in: packages/core/src/resource-registry.ts:50

Parameters

ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
requestResourceInvocationRequest

Returns

object

action

action: string

context

context: object

context.actor

actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

context.authority

authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

context.enabledToolNamespaces

enabledToolNamespaces: string[]

context.namespaceId

namespaceId: string

context.now

now: string

context.owner

owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

context.purpose

purpose: string

context.traceId

traceId: string

input?

optional input?: JsonValue

metadata?

optional metadata?: JsonObject

operationId

operationId: string

resource

resource: object

resource.namespace

namespace: string

resource.owner?

optional owner?: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

resource.path

path: string[]


turnAuthorityKey()

turnAuthorityKey(context): string

Defined in: packages/core/src/authority.ts:49

The identity a turn's frozen authority is held against.

now is excluded because the turn instant is precisely what a lease freezes, and enabledToolNamespaces is excluded because namespace enablement is host state that stays live per operation and is never read by an authorization decision. Every other field an authorization decision reads is in the key, so a lease can never answer for a context it was not resolved for.

Parameters

ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring

Returns

string


validateDelegationChain()

validateDelegationChain(grant, context, now, options?): Promise<DelegationValidation>>

Defined in: packages/core/src/delegation.ts:103

Validate the complete ancestor chain of one grant.

A grant without parentGrantId is a root grant and is valid here; its own expiry, revocation, and purpose remain the caller's separate check. For a derived grant every link must satisfy all of:

  • the child's issuer is exactly the parent's subject;
  • both grants live in the same namespace;
  • the parent is itself active for the requested purpose, so revoking or expiring an ancestor invalidates every descendant. A revoked ancestor is observed at options.admittedAt and an expired one at now, exactly as for the grant presenting the chain;
  • every child capability is covered by one parent capability;
  • time window and purposes never widen;
  • the parent holds delegation budget and the child's budget is strictly smaller;
  • the parent is not itself bounded by maxUses. Usage counters are per grant, so n children of a k-use parent would carry n*k uses between them. Sharing one budget across a chain needs accounting that spans grants, and until that exists the parent is refused rather than multiplied.

Anything the resolver cannot establish returns unverified, never valid.

Parameters

ParameterType
grant{ capabilities: object[]; constraints: { delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }; id: string; issuedAt: string; issuer: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; metadata?: JsonObject; namespaceId: string; parentGrantId?: string; revokedAt?: string; subject: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; }
grant.capabilitiesobject[]
grant.constraints{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }
grant.constraints.delegationDepth?number
grant.constraints.expiresAt?string
grant.constraints.maxUses?number
grant.constraints.notBefore?string
grant.constraints.purposes?string[]
grant.idstring
grant.issuedAtstring
grant.issuer{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
grant.metadata?JsonObject
grant.namespaceIdstring
grant.parentGrantId?string
grant.revokedAt?string
grant.subject{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
nownumber
optionsDelegationValidationOptions

Returns

Promise<DelegationValidation>