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
| Parameter | Type |
|---|---|
options | CapabilityAuthorizerOptions |
Returns
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
| Parameter | Type |
|---|---|
authority | ResolvedAuthority |
request | AuthorizationRequest |
options | AuthorizeOptions |
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
| Parameter | Type |
|---|---|
authority | ResolvedAuthority |
ceiling | AuthorizationRequest |
options | AuthorizationInstantOptions |
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
| Parameter | Type |
|---|---|
authority | ResolvedAuthority |
options | AuthorizationInstantOptions |
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
| Parameter | Type |
|---|---|
sinks | readonly AuditSink[] |
Returns
Methods
record()
record(
event):Promise<void>>
Defined in: packages/core/src/audit.ts:121
Parameters
| Parameter | Type |
|---|---|
event | AuditEvent |
Returns
Promise<void>
Implementation of
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
| Parameter | Type |
|---|---|
kind | "tool" | "resource namespace" | "tool provider" | "tool namespace settings" |
identifier | string |
Returns
Overrides
Error.constructor
Properties
| Property | Modifier | Type | Default value | Description | Overrides | Inherited from | Defined in |
|---|---|---|---|---|---|---|---|
<a id="property-cause"></a> cause? | public | unknown | undefined | - | - | Error.cause | node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26 |
<a id="property-message"></a> message | public | string | undefined | - | - | Error.message | node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077 |
<a id="property-name"></a> name | readonly | "DuplicateRegistrationError" | "DuplicateRegistrationError" | - | Error.name | - | packages/core/src/errors.ts:2 |
<a id="property-stack"></a> stack? | public | string | undefined | - | - | Error.stack | node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078 |
<a id="property-stacktracelimit"></a> stackTraceLimit | static | number | undefined | The 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.stackTraceLimit | node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68 |
Methods
captureStackTrace()
staticcaptureStackTrace(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
| Parameter | Type |
|---|---|
targetObject | object |
constructorOpt? | Function |
Returns
void
Inherited from
Error.captureStackTrace
prepareStackTrace()
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56
Parameters
| Parameter | Type |
|---|---|
err | Error |
stackTraces | CallSite[] |
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
Methods
getUsage()
getUsage(
namespaceId,grantId):Promise<number>>
Defined in: packages/core/src/authorization.ts:309
Parameters
| Parameter | Type |
|---|---|
namespaceId | string |
grantId | string |
Returns
Promise<number>
Implementation of
tryConsume()
tryConsume(
namespaceId,grantId,maximumUses):Promise<boolean>>
Defined in: packages/core/src/authorization.ts:313
Parameters
| Parameter | Type |
|---|---|
namespaceId | string |
grantId | string |
maximumUses | number |
Returns
Promise<boolean>
Implementation of
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
| Parameter | Type |
|---|---|
kind | "tool" | "resource namespace" | "tool provider" | "tool namespace settings" |
identifier | string |
Returns
Overrides
Error.constructor
Properties
| Property | Modifier | Type | Default value | Description | Overrides | Inherited from | Defined in |
|---|---|---|---|---|---|---|---|
<a id="property-cause-1"></a> cause? | public | unknown | undefined | - | - | Error.cause | node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26 |
<a id="property-message-1"></a> message | public | string | undefined | - | - | Error.message | node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077 |
<a id="property-name-1"></a> name | readonly | "MissingRegistrationError" | "MissingRegistrationError" | - | Error.name | - | packages/core/src/errors.ts:13 |
<a id="property-stack-1"></a> stack? | public | string | undefined | - | - | Error.stack | node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078 |
<a id="property-stacktracelimit-1"></a> stackTraceLimit | static | number | undefined | The 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.stackTraceLimit | node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68 |
Methods
captureStackTrace()
staticcaptureStackTrace(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
| Parameter | Type |
|---|---|
targetObject | object |
constructorOpt? | Function |
Returns
void
Inherited from
Error.captureStackTrace
prepareStackTrace()
staticprepareStackTrace(err,stackTraces):any
Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56
Parameters
| Parameter | Type |
|---|---|
err | Error |
stackTraces | CallSite[] |
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
Methods
record()
record(
_event):Promise<void>>
Defined in: packages/core/src/audit.ts:109
Parameters
| Parameter | Type |
|---|---|
_event | AuditEvent |
Returns
Promise<void>
Implementation of
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
| Parameter | Type | Default value |
|---|---|---|
namespace | string | MESSAGING_NAMESPACE |
Returns
RecipientScopedMessageCapabilityResolver
Methods
resolve()
resolve(
context,envelope):AuthorizationRequest
Defined in: packages/core/src/message-service.ts:59
Parameters
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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.createdAt | string |
envelope.id | string |
envelope.payload | JsonValue |
envelope.provenance? | { metadata?: JsonObject; parentIds: string[]; source: string; } |
envelope.provenance.metadata? | JsonObject |
envelope.provenance.parentIds | string[] |
envelope.provenance.source | string |
envelope.purpose | string |
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.traceId | string |
envelope.version | "1" |
Returns
Implementation of
MessageCapabilityResolver.resolve
ResourceProviderRegistry
Defined in: packages/core/src/resource-registry.ts:23
Constructors
Constructor
new ResourceProviderRegistry():
ResourceProviderRegistry
Returns
Methods
get()
get(
namespace):ResourceProvider|undefined
Defined in: packages/core/src/resource-registry.ts:37
Parameters
| Parameter | Type |
|---|---|
namespace | string |
Returns
ResourceProvider | undefined
has()
has(
namespace):boolean
Defined in: packages/core/src/resource-registry.ts:41
Parameters
| Parameter | Type |
|---|---|
namespace | string |
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
| Parameter | Type |
|---|---|
provider | ResourceProvider |
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
| Parameter | Type |
|---|---|
options | SharedOSKernelOptions |
Returns
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
agent | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
request | AuthorizationRequest |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
request | ResourceInvocationRequest |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
call | { arguments: JsonObject; id: string; requestedAt: string; tool: string; traceId: string; } |
call.arguments | JsonObject |
call.id | string |
call.requestedAt | string |
call.tool | string |
call.traceId | string |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
options | KernelOperationOptions & 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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
options | KernelOperationOptions |
Returns
Promise<{ namespaces: object[]; summary: { disabled: number; enabled: number; total: number; }; }>
listTools()
listTools(
context,options?):Promise<readonlyobject[]>
Defined in: packages/core/src/kernel.ts:761
Parameters
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
subject | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
options | AgentCardReadOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
reason | string |
options | EscalationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
call | RefusedCall |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
turn | TurnEndRecord |
options | KernelOperationOptions |
Returns
Promise<void>
registerResourceProvider()
registerResourceProvider(
provider):void
Defined in: packages/core/src/kernel.ts:337
Parameters
| Parameter | Type |
|---|---|
provider | ResourceProvider |
Returns
void
registerTool()
registerTool(
handler):void
Defined in: packages/core/src/kernel.ts:341
Parameters
| Parameter | Type |
|---|---|
handler | ToolHandler |
Returns
void
registerToolProvider()
registerToolProvider(
provider):void
Defined in: packages/core/src/kernel.ts:345
Parameters
| Parameter | Type |
|---|---|
provider | ContextToolProvider |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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.createdAt | string |
envelope.id | string |
envelope.payload | JsonValue |
envelope.provenance? | { metadata?: JsonObject; parentIds: string[]; source: string; } |
envelope.provenance.metadata? | JsonObject |
envelope.provenance.parentIds | string[] |
envelope.provenance.source | string |
envelope.purpose | string |
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.traceId | string |
envelope.version | "1" |
options | KernelOperationOptions |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
update | { disable?: string[]; enable?: string[]; } |
update.disable? | string[] |
update.enable? | string[] |
options | KernelOperationOptions |
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
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
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
| Parameter | Type |
|---|---|
name | string |
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
| Parameter | Type |
|---|---|
name | string |
Returns
boolean
namespaceCatalog()
namespaceCatalog(
enabledToolNamespaces):object
Defined in: packages/core/src/tool-registry.ts:145
Parameters
| Parameter | Type |
|---|---|
enabledToolNamespaces | readonly 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
| Parameter | Type |
|---|---|
handler | ToolHandler |
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
| Parameter | Type |
|---|---|
source | GrantSource |
Returns
Methods
resolve()
resolve(
context,signal):Promise<AuthorityResolution>>
Defined in: packages/core/src/authority.ts:257
Parameters
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
signal | AbortSignal |
Returns
Promise<AuthorityResolution>
Interfaces
AgentCardReadOptions
Defined in: packages/core/src/kernel.ts:221
Extends
Properties
| Property | Modifier | Type | Description | Inherited from | Defined in |
|---|---|---|---|---|---|
<a id="property-signal"></a> signal? | readonly | AbortSignal | - | KernelOperationOptions.signal | packages/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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-reasoncode"></a> reasonCode | readonly | string | - | packages/core/src/agent-card.ts:213 |
<a id="property-requiredauthority"></a> requiredAuthority? | readonly | object | Present when the authorizer described the authority that would have served this view. | packages/core/src/agent-card.ts:216 |
requiredAuthority.capabilities | public | object[] | - | packages/contracts/dist/capability.d.ts:511 |
requiredAuthority.constraints? | public | object | - | packages/contracts/dist/capability.d.ts:534 |
requiredAuthority.constraints.delegationDepth? | public | number | - | packages/contracts/dist/capability.d.ts:539 |
requiredAuthority.constraints.expiresAt? | public | string | - | packages/contracts/dist/capability.d.ts:537 |
requiredAuthority.constraints.maxUses? | public | number | - | packages/contracts/dist/capability.d.ts:538 |
requiredAuthority.constraints.notBefore? | public | string | - | packages/contracts/dist/capability.d.ts:536 |
requiredAuthority.constraints.purposes? | public | string[] | - | packages/contracts/dist/capability.d.ts:535 |
requiredAuthority.id | public | string | - | packages/contracts/dist/capability.d.ts:496 |
requiredAuthority.metadata? | public | JsonObject | - | packages/contracts/dist/capability.d.ts:541 |
requiredAuthority.namespaceId | public | string | - | packages/contracts/dist/capability.d.ts:497 |
requiredAuthority.owner | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | packages/contracts/dist/capability.d.ts:483 |
requiredAuthority.purpose | public | string | - | packages/contracts/dist/capability.d.ts:532 |
requiredAuthority.requestedAt | public | string | - | packages/contracts/dist/capability.d.ts:533 |
requiredAuthority.requester | public | { 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> servableViews | readonly | readonly ("reach" | "identity" | "namespaces")[] | - | packages/core/src/agent-card.ts:214 |
<a id="property-status"></a> status | readonly | "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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-card"></a> card | readonly | { 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> status | readonly | "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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-allowed"></a> allowed | readonly | true | packages/core/src/authorization.ts:131 |
<a id="property-matchedgrantid"></a> matchedGrantId | readonly | string | packages/core/src/authorization.ts:133 |
<a id="property-metadata"></a> metadata? | readonly | JsonObject | packages/core/src/authorization.ts:134 |
<a id="property-reasoncode-1"></a> reasonCode | readonly | "allowed" | packages/core/src/authorization.ts:132 |
AuditEvent
Defined in: packages/core/src/audit.ts:53
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-action"></a> action? | readonly | string | - | packages/core/src/audit.ts:78 |
<a id="property-actor"></a> actor | readonly | { 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> at | readonly | string | - | packages/core/src/audit.ts:70 |
<a id="property-authority"></a> authority | readonly | { 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? | readonly | string | Content 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? | readonly | string | - | packages/core/src/audit.ts:79 |
<a id="property-id"></a> id | readonly | string | The 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? | readonly | string | - | packages/core/src/audit.ts:89 |
<a id="property-metadata-1"></a> metadata? | readonly | JsonObject | - | packages/core/src/audit.ts:101 |
<a id="property-namespaceid"></a> namespaceId | readonly | string | - | packages/core/src/audit.ts:72 |
<a id="property-operationid"></a> operationId? | readonly | string | - | packages/core/src/audit.ts:87 |
<a id="property-outcome"></a> outcome | readonly | AuditOutcome | - | packages/core/src/audit.ts:69 |
<a id="property-owner"></a> owner | readonly | { 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> purpose | readonly | string | - | packages/core/src/audit.ts:76 |
<a id="property-reason"></a> reason? | readonly | string | - | 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? | readonly | object | The 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.capabilities | public | object[] | - | packages/contracts/dist/capability.d.ts:511 |
requestedAuthority.constraints? | public | object | - | packages/contracts/dist/capability.d.ts:534 |
requestedAuthority.constraints.delegationDepth? | public | number | - | packages/contracts/dist/capability.d.ts:539 |
requestedAuthority.constraints.expiresAt? | public | string | - | packages/contracts/dist/capability.d.ts:537 |
requestedAuthority.constraints.maxUses? | public | number | - | packages/contracts/dist/capability.d.ts:538 |
requestedAuthority.constraints.notBefore? | public | string | - | packages/contracts/dist/capability.d.ts:536 |
requestedAuthority.constraints.purposes? | public | string[] | - | packages/contracts/dist/capability.d.ts:535 |
requestedAuthority.id | public | string | - | packages/contracts/dist/capability.d.ts:496 |
requestedAuthority.metadata? | public | JsonObject | - | packages/contracts/dist/capability.d.ts:541 |
requestedAuthority.namespaceId | public | string | - | packages/contracts/dist/capability.d.ts:497 |
requestedAuthority.owner | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | packages/contracts/dist/capability.d.ts:483 |
requestedAuthority.purpose | public | string | - | packages/contracts/dist/capability.d.ts:532 |
requestedAuthority.requestedAt | public | string | - | packages/contracts/dist/capability.d.ts:533 |
requestedAuthority.requester | public | { 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? | readonly | object | - | packages/core/src/audit.ts:77 |
resource.namespace | public | string | - | 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.path | public | string[] | - | packages/contracts/dist/capability.d.ts:53 |
<a id="property-tool"></a> tool? | readonly | string | - | packages/core/src/audit.ts:88 |
<a id="property-traceid"></a> traceId | readonly | string | - | packages/core/src/audit.ts:71 |
<a id="property-type"></a> type | readonly | AuditEventType | - | packages/core/src/audit.ts:68 |
<a id="property-version"></a> version | readonly | "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
| Parameter | Type |
|---|---|
event | AuditEvent |
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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-grantcount"></a> grantCount | readonly | number | - | packages/core/src/authority.ts:191 |
<a id="property-grantids"></a> grantIds | readonly | readonly string[] | - | packages/core/src/authority.ts:190 |
<a id="property-hash"></a> hash | readonly | string | SHA-256 over the canonical, order-independent form of the grant set. | packages/core/src/authority.ts:189 |
<a id="property-loadedat"></a> loadedAt | readonly | string | - | packages/core/src/authority.ts:192 |
AuthorityUnavailableDetail
Defined in: packages/core/src/authority.ts:226
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-grantid-1"></a> grantId | readonly | string | packages/core/src/authority.ts:227 |
<a id="property-reason-1"></a> reason | readonly | GrantScopeMismatch | packages/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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-grantsresolved"></a> grantsResolved | readonly | number | packages/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> reasonCode | readonly | AuthorizationReasonCode | packages/core/src/authorization.ts:108 |
<a id="property-rejections"></a> rejections | readonly | readonly 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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-now"></a> now? | readonly | string | packages/core/src/authorization.ts:247 |
AuthorizationRequest
Defined in: packages/core/src/authorization.ts:32
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-action-1"></a> action | readonly | string | packages/core/src/authorization.ts:34 |
<a id="property-resource-1"></a> resource | readonly | object | packages/core/src/authorization.ts:33 |
resource.namespace | public | string | 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.path | public | string[] | 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
| Property | Modifier | Type | Description | Inherited from | Defined in |
|---|---|---|---|---|---|
<a id="property-consume"></a> consume? | readonly | boolean | Consumption 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? | readonly | string | - | AuthorizationInstantOptions.now | packages/core/src/authorization.ts:247 |
<a id="property-onexplain"></a> onExplain? | readonly | (explanation) => void | Called 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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-delegationresolver"></a> delegationResolver? | readonly | DelegationChainResolver | Trusted 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? | readonly | CapabilityGrantVerifier | - | packages/core/src/authorization.ts:270 |
<a id="property-hostceiling"></a> hostCeiling? | readonly | HostCeiling<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? | readonly | number | - | packages/core/src/authorization.ts:276 |
<a id="property-onprovidererror"></a> onProviderError? | readonly | ProviderErrorReporter | Where 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? | readonly | GrantUsageStore | - | 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
| Parameter | Type |
|---|---|
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.capabilities | object[] |
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.id | string |
grant.issuedAt | string |
grant.issuer | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
grant.metadata? | JsonObject |
grant.namespaceId | string |
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-id-1"></a> id | readonly | string | packages/core/src/tool-registry.ts:39 |
Methods
listTools()
listTools(
context,signal):Promise<readonlyToolHandler[]>
Defined in: packages/core/src/tool-registry.ts:40
Parameters
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
signal | AbortSignal |
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
| Parameter | Type |
|---|---|
namespaceId | string |
grantId | string |
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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-admittedat"></a> admittedAt? | readonly | number | The 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? | readonly | number | - | packages/core/src/delegation.ts:68 |
<a id="property-resolver"></a> resolver? | readonly | DelegationChainResolver | - | packages/core/src/delegation.ts:67 |
DeriveGrantRequest
Defined in: packages/core/src/delegation.ts:292
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-capabilities"></a> capabilities | readonly | readonly 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? | readonly | Omit<{ delegationDepth?: number; expiresAt?: string; maxUses?: number; notBefore?: string; purposes?: string[]; }, "delegationDepth"> & object | - | packages/core/src/delegation.ts:299 |
<a id="property-id-2"></a> id | readonly | string | Identifier for the derived grant. Must be unique within the namespace. | packages/core/src/delegation.ts:294 |
<a id="property-issuedat"></a> issuedAt | readonly | string | - | packages/core/src/delegation.ts:302 |
<a id="property-metadata-2"></a> metadata? | readonly | JsonObject | - | packages/core/src/delegation.ts:303 |
<a id="property-subject"></a> subject | readonly | { 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
| Property | Modifier | Type | Description | Inherited from | Defined in |
|---|---|---|---|---|---|
<a id="property-requestedauthority-1"></a> requestedAuthority? | readonly | CapabilityRequestPayload | The 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? | readonly | AbortSignal | - | KernelOperationOptions.signal | packages/core/src/kernel.ts:156 |
GrantRejection
Defined in: packages/core/src/authorization.ts:87
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-grantid-2"></a> grantId | readonly | string | packages/core/src/authorization.ts:88 |
<a id="property-reason-2"></a> reason | readonly | GrantRejectionReason | packages/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<readonlyobject[]>
Defined in: packages/core/src/authority.ts:96
Parameters
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
signal | AbortSignal |
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
| Parameter | Type |
|---|---|
namespaceId | string |
grantId | string |
Returns
Promise<number>
tryConsume()
tryConsume(
namespaceId,grantId,maximumUses):Promise<boolean>>
Defined in: packages/core/src/authorization.ts:116
Parameters
| Parameter | Type |
|---|---|
namespaceId | string |
grantId | string |
maximumUses | number |
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 Parameter | Default type |
|---|---|
Policy | HostPolicy |
Methods
narrow()
narrow(
decision,request,context,policy):HostCeilingVerdict
Defined in: packages/core/src/authorization.ts:226
Parameters
| Parameter | Type |
|---|---|
decision | AllowedDecision |
request | AuthorizationRequest |
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
policy | Policy | undefined |
Returns
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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-allowed-1"></a> allowed | readonly | false | packages/core/src/authorization.ts:146 |
<a id="property-metadata-3"></a> metadata? | readonly | JsonObject | packages/core/src/authorization.ts:148 |
<a id="property-reasoncode-3"></a> reasonCode | readonly | "host_policy_denied" | packages/core/src/authorization.ts:147 |
KernelOperationOptions
Defined in: packages/core/src/kernel.ts:155
Extended by
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-signal-2"></a> signal? | readonly | AbortSignal | packages/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 Parameter | Default type |
|---|---|
Policy | HostPolicy |
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-policy"></a> policy | readonly | Policy | packages/core/src/authority.ts:152 |
<a id="property-version-1"></a> version | readonly | string | packages/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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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.createdAt | string |
envelope.id | string |
envelope.payload | JsonValue |
envelope.provenance? | { metadata?: JsonObject; parentIds: string[]; source: string; } |
envelope.provenance.metadata? | JsonObject |
envelope.provenance.parentIds | string[] |
envelope.provenance.source | string |
envelope.purpose | string |
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.traceId | string |
envelope.version | "1" |
Returns
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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.createdAt | string |
request.id | string |
request.payload | JsonValue |
request.provenance? | { metadata?: JsonObject; parentIds: string[]; source: string; } |
request.provenance.metadata? | JsonObject |
request.provenance.parentIds | string[] |
request.provenance.source | string |
request.purpose | string |
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.traceId | string |
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; } |
signal | AbortSignal |
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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.createdAt | string |
envelope.id | string |
envelope.payload | JsonValue |
envelope.provenance? | { metadata?: JsonObject; parentIds: string[]; source: string; } |
envelope.provenance.metadata? | JsonObject |
envelope.provenance.parentIds | string[] |
envelope.provenance.source | string |
envelope.purpose | string |
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.traceId | string |
envelope.version | "1" |
signal | AbortSignal |
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 Parameter | Default type |
|---|---|
Policy | HostPolicy |
Methods
load()
load(
context,signal):Promise<LoadedPolicy<Policy>>>>
Defined in: packages/core/src/authority.ts:135
Parameters
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
signal | AbortSignal |
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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-action-2"></a> action? | readonly | string | - | packages/core/src/diagnostics.ts:93 |
<a id="property-kind"></a> kind | readonly | ProviderErrorKind | - | packages/core/src/diagnostics.ts:84 |
<a id="property-namespaceid-1"></a> namespaceId | readonly | string | - | packages/core/src/diagnostics.ts:88 |
<a id="property-operationid-1"></a> operationId? | readonly | string | The call id, where the path has one. | packages/core/src/diagnostics.ts:90 |
<a id="property-reasoncode-4"></a> reasonCode | readonly | string | The code the kernel returned instead. | packages/core/src/diagnostics.ts:86 |
<a id="property-resource-2"></a> resource? | readonly | object | - | packages/core/src/diagnostics.ts:92 |
resource.namespace | public | string | - | 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.path | public | string[] | - | packages/contracts/dist/capability.d.ts:53 |
<a id="property-tool-1"></a> tool? | readonly | string | - | packages/core/src/diagnostics.ts:91 |
<a id="property-traceid-1"></a> traceId | readonly | string | - | 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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-callid"></a> callId | readonly | string | - | packages/core/src/kernel.ts:175 |
<a id="property-cause-2"></a> cause? | readonly | string | Which situation a coarse code was, where it covers several. | packages/core/src/kernel.ts:179 |
<a id="property-reasoncode-5"></a> reasonCode | readonly | string | - | packages/core/src/kernel.ts:177 |
<a id="property-tool-2"></a> tool | readonly | string | - | 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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-context"></a> context | readonly | object | - | packages/core/src/authority.ts:204 |
context.actor | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | packages/contracts/dist/access.d.ts:144 |
context.authority | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | packages/contracts/dist/access.d.ts:157 |
context.enabledToolNamespaces | public | string[] | - | packages/contracts/dist/access.d.ts:170 |
context.namespaceId | public | string | - | packages/contracts/dist/access.d.ts:141 |
context.now | public | string | - | packages/contracts/dist/access.d.ts:171 |
context.owner | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | packages/contracts/dist/access.d.ts:128 |
context.purpose | public | string | - | packages/contracts/dist/access.d.ts:142 |
context.traceId | public | string | - | packages/contracts/dist/access.d.ts:143 |
<a id="property-grants"></a> grants | readonly | readonly object[] | - | packages/core/src/authority.ts:205 |
<a id="property-hostpolicy"></a> hostPolicy? | readonly | PolicyResolution<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> snapshot | readonly | AuthoritySnapshot | - | packages/core/src/authority.ts:206 |
ResourceInvocationRequest
Defined in: packages/core/src/resource-registry.ts:10
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-action-3"></a> action | readonly | string | packages/core/src/resource-registry.ts:13 |
<a id="property-input"></a> input? | readonly | JsonValue | packages/core/src/resource-registry.ts:14 |
<a id="property-metadata-4"></a> metadata? | readonly | JsonObject | packages/core/src/resource-registry.ts:15 |
<a id="property-operationid-2"></a> operationId | readonly | string | packages/core/src/resource-registry.ts:11 |
<a id="property-resource-3"></a> resource | readonly | object | packages/core/src/resource-registry.ts:12 |
resource.namespace | public | string | 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.path | public | string[] | packages/contracts/dist/capability.d.ts:53 |
ResourceProvider
Defined in: packages/core/src/resource-registry.ts:18
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-namespace"></a> namespace | readonly | string | packages/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
| Parameter | Type |
|---|---|
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.action | string |
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.enabledToolNamespaces | string[] |
operation.context.namespaceId | string |
operation.context.now | string |
operation.context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
operation.context.purpose | string |
operation.context.traceId | string |
operation.input? | JsonValue |
operation.metadata? | JsonObject |
operation.operationId | string |
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.namespace | string |
operation.resource.owner? | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
operation.resource.path | string[] |
signal | AbortSignal |
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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-audit"></a> audit? | readonly | AuditSink | - | packages/core/src/kernel.ts:129 |
<a id="property-authorizer"></a> authorizer? | readonly | CapabilityAuthorizer | - | packages/core/src/kernel.ts:111 |
<a id="property-createauditid"></a> createAuditId? | readonly | () => string | How 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> grantSource | readonly | GrantSource | The 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? | readonly | MessageCapabilityResolver | - | packages/core/src/kernel.ts:118 |
<a id="property-messagerequestrouter"></a> messageRequestRouter? | readonly | MessageRequestRouter | - | packages/core/src/kernel.ts:117 |
<a id="property-messagetransport"></a> messageTransport? | readonly | MessageTransport | - | 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? | readonly | ProviderErrorReporter | Notification 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? | readonly | PolicySource<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? | readonly | ResourceProviderRegistry | - | packages/core/src/kernel.ts:112 |
<a id="property-spans"></a> spans? | readonly | SpanSink | Where 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? | readonly | ToolNamespaceSettingsStore | - | packages/core/src/kernel.ts:115 |
<a id="property-toolproviders"></a> toolProviders? | readonly | readonly ContextToolProvider[] | - | packages/core/src/kernel.ts:114 |
<a id="property-tools"></a> tools? | readonly | ToolRegistry | - | packages/core/src/kernel.ts:113 |
Span
Defined in: packages/core/src/spans.ts:37
One completed span of SharedOS-owned work.
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-attributes"></a> attributes | readonly | SpanAttributes | - | packages/core/src/spans.ts:41 |
<a id="property-durationms"></a> durationMs | readonly | number | Monotonic duration in fractional milliseconds. | packages/core/src/spans.ts:40 |
<a id="property-name-2"></a> name | readonly | string | - | 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
| Parameter | Type |
|---|---|
key | string |
value | string | 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
| Parameter | Type |
|---|---|
span | Span |
Returns
void
ToolCatalogOptions
Defined in: packages/core/src/published-tool.ts:133
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-executionid"></a> executionId | readonly | string | packages/core/src/published-tool.ts:134 |
ToolHandler
Defined in: packages/core/src/tool-registry.ts:15
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-definition"></a> definition | readonly | object | - | packages/core/src/tool-registry.ts:16 |
definition.annotations? | public | object | - | packages/contracts/dist/tool.d.ts:309 |
definition.annotations.destructive? | public | boolean | - | packages/contracts/dist/tool.d.ts:311 |
definition.annotations.idempotent? | public | boolean | - | packages/contracts/dist/tool.d.ts:312 |
definition.annotations.readOnly? | public | boolean | - | packages/contracts/dist/tool.d.ts:310 |
definition.description | public | string | - | packages/contracts/dist/tool.d.ts:283 |
definition.inputSchema | public | JsonObject | - | packages/contracts/dist/tool.d.ts:286 |
definition.metadata? | public | JsonObject | - | packages/contracts/dist/tool.d.ts:307 |
definition.name | public | string | - | packages/contracts/dist/tool.d.ts:282 |
definition.namespace | public | string | - | packages/contracts/dist/tool.d.ts:281 |
definition.outputSchema? | public | JsonObject | - | packages/contracts/dist/tool.d.ts:308 |
definition.readWrite | public | "read" | "write" | - | packages/contracts/dist/tool.d.ts:285 |
definition.requiredCapability | public | object | - | packages/contracts/dist/tool.d.ts:287 |
definition.requiredCapability.action | public | string | - | packages/contracts/dist/tool.d.ts:305 |
definition.requiredCapability.resource | public | object | - | packages/contracts/dist/tool.d.ts:288 |
definition.requiredCapability.resource.namespace | public | string | - | 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.path | public | string[] | - | packages/contracts/dist/tool.d.ts:289 |
definition.source | public | string | - | packages/contracts/dist/tool.d.ts:284 |
<a id="property-parsearguments"></a> parseArguments | readonly | (arguments_) => unknown | Parse and normalize untrusted arguments before authorization or execution. | packages/core/src/tool-registry.ts:18 |
<a id="property-resolverequirement"></a> resolveRequirement? | readonly | (context, call) => AuthorizationRequest | Resolve 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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
call | { arguments: JsonObject; id: string; requestedAt: string; tool: string; traceId: string; } |
call.arguments | JsonObject |
call.id | string |
call.requestedAt | string |
call.tool | string |
call.traceId | string |
signal | AbortSignal |
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<readonlystring[]>
Defined in: packages/core/src/tool-namespace-control.ts:12
Parameters
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
update | { disable?: string[]; enable?: string[]; } |
update.disable? | string[] |
update.enable? | string[] |
signal | AbortSignal |
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
| Property | Modifier | Type | Description | Defined 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> executionId | readonly | string | - | packages/core/src/kernel.ts:161 |
<a id="property-reasoncode-6"></a> reasonCode? | readonly | string | The terminal code, where the ending had one. | packages/core/src/kernel.ts:164 |
<a id="property-status-2"></a> status | readonly | "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: readonlystring[];status:"valid"; } | {chain: readonlystring[];code:DelegationViolationCode;grantId:string;status:"invalid"; } | {chain: readonlystring[];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 Parameter | Default type |
|---|---|
Policy | HostPolicy |
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
| Parameter | Type |
|---|---|
error | unknown |
operation | ProviderErrorContext |
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
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?
readonlyoptionalcode?:AuthorityUnavailableCode
Defined in: packages/core/src/authority.ts:78
Present when it was not.
snapshot?
readonlyoptionalsnapshot?:AuthoritySnapshot
Defined in: packages/core/src/authority.ts:76
Present when authority was established.
status
readonlystatus:"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
constAGENT_INVOKE_ACTION:"invoke"="invoke"
Defined in: packages/core/src/kernel.ts:235
CATALOG_HASH_FIELDS
constCATALOG_HASH_FIELDS: readonlystring[]
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
constDEFAULT_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
constDIRECTORY_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
constDIRECTORY_READ_ACTION:"read"="read"
Defined in: packages/core/src/agent-card.ts:20
DIRECTORY_RESOURCE_ROOT
constDIRECTORY_RESOURCE_ROOT: readonlystring[]
Defined in: packages/core/src/agent-card.ts:19
The resource every card hangs beneath, and the one a host grants over.
EXECUTION_NAMESPACE
constEXECUTION_NAMESPACE:"sharedos.execution"="sharedos.execution"
Defined in: packages/core/src/kernel.ts:234
INFRASTRUCTURE_DENIAL_REASONS
constINFRASTRUCTURE_DENIAL_REASONS: readonlyAuthorizationReasonCode[]
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
constMAX_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
constMESSAGE_REQUEST_TOOL_DEFINITION:ToolDefinition
Defined in: packages/core/src/message-tool.ts:25
MESSAGE_REQUEST_TOOL_NAME
constMESSAGE_REQUEST_TOOL_NAME:"messages.request"="messages.request"
Defined in: packages/core/src/message-tool.ts:23
MESSAGE_SEND_ACTION
constMESSAGE_SEND_ACTION:"send"="send"
Defined in: packages/core/src/message-service.ts:13
MESSAGE_TOOL_NAMESPACE
constMESSAGE_TOOL_NAMESPACE:"messages"="messages"
Defined in: packages/core/src/message-tool.ts:22
MESSAGING_NAMESPACE
constMESSAGING_NAMESPACE:"sharedos.messaging"="sharedos.messaging"
Defined in: packages/core/src/message-service.ts:12
MID_TURN_AUTHORITY_REFRESH
constMID_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
constSPAN: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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
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
| Parameter | Type | Default 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?
optionalowner?: {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
| Parameter | Type | Default 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
| Parameter | Type |
|---|---|
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
agentExecutionCapability()
agentExecutionCapability(
agent,owner):object
Defined in: packages/core/src/kernel.ts:237
Parameters
| Parameter | Type |
|---|---|
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?
optionalowner?: {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
| Parameter | Type |
|---|---|
current | readonly 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
| Parameter | Type | Default 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.enabledToolNamespaces | string[] | undefined |
context.namespaceId | string | undefined |
context.now | string | undefined |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | undefined |
context.purpose | string | undefined |
context.traceId | string | undefined |
event | AuditEventInput | undefined |
createId | () => string | randomAuditEventId |
Returns
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
| Parameter | Type |
|---|---|
definitions | readonly object[] |
options | ToolCatalogOptions |
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
| Parameter | Type |
|---|---|
value | unknown |
Returns
string
capabilityIntersectsCeiling()
capabilityIntersectsCeiling(
capability,ceiling,context):boolean
Defined in: packages/core/src/authorization.ts:927
Parameters
| Parameter | Type |
|---|---|
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.actions | string[] |
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.namespace | string |
capability.resource.owner? | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
capability.resource.path | string[] |
capability.scope | "exact" | "descendants" |
ceiling | AuthorizationRequest |
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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
| Parameter | Type |
|---|---|
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.actions | string[] |
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.namespace | string |
capability.resource.owner? | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
capability.resource.path | string[] |
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.actions | string[] |
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.namespace | string |
ancestor.resource.owner? | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
ancestor.resource.path | string[] |
ancestor.scope | "exact" | "descendants" |
context | Pick<AccessContext, "owner"> |
Returns
boolean
capabilityMatches()
capabilityMatches(
capability,request,context):boolean
Defined in: packages/core/src/authorization.ts:899
Parameters
| Parameter | Type |
|---|---|
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.actions | string[] |
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.namespace | string |
capability.resource.owner? | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
capability.resource.path | string[] |
capability.scope | "exact" | "descendants" |
request | AuthorizationRequest |
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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
| Parameter | Type |
|---|---|
tools | readonly 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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
reach | readonly 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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
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.capabilities | object[] |
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.id | string |
parent.issuedAt | string |
parent.issuer | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
parent.metadata? | JsonObject |
parent.namespaceId | string |
parent.parentGrantId? | string |
parent.revokedAt? | string |
parent.subject | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
request | DeriveGrantRequest |
Returns
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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
request | AuthorizationRequest |
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
| Parameter | Type |
|---|---|
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?
optionalowner?: {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
| Parameter | Type |
|---|---|
hash | string |
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
| Parameter | Type |
|---|---|
value | unknown |
Returns
Promise<string>
isInfrastructureDenial()
isInfrastructureDenial(
reasonCode):boolean
Defined in: packages/core/src/authorization.ts:65
Parameters
| Parameter | Type |
|---|---|
reasonCode | string |
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
| Parameter | Type |
|---|---|
sink | SpanSink | undefined |
name | string |
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
| Parameter | Type |
|---|---|
sink | SpanSink | undefined |
name | string |
operation | (scope) => T |
Returns
T
messageSendCapability()
messageSendCapability(
receiver,owner):object
Defined in: packages/core/src/message-service.ts:15
Parameters
| Parameter | Type |
|---|---|
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?
optionalowner?: {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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
payload | CapabilityRequestPayload |
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
| Parameter | Type |
|---|---|
name | string |
Returns
string
publishToolCatalog()
publishToolCatalog(
definitions): readonlyobject[]
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
| Parameter | Type |
|---|---|
definitions | readonly 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
| Parameter | Type |
|---|---|
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.description | string |
definition.inputSchema | JsonObject |
definition.metadata? | JsonObject |
definition.name | string |
definition.namespace | string |
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.action | string |
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.namespace | string |
definition.requiredCapability.resource.owner? | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
definition.requiredCapability.resource.path | string[] |
definition.source | string |
Returns
object
annotations?
optionalannotations?:object
annotations.destructiveHint?
optionaldestructiveHint?:boolean
annotations.idempotentHint?
optionalidempotentHint?:boolean
annotations.openWorldHint?
optionalopenWorldHint?:boolean
annotations.readOnlyHint?
optionalreadOnlyHint?:boolean
description
description:
string
inputSchema
inputSchema:
JsonObject
metadata?
optionalmetadata?:object
metadata.namespace?
optionalnamespace?:string
metadata.source?
optionalsource?:string
name
name:
string
outputSchema?
optionaloutputSchema?:JsonObject
reachThroughTools()
reachThroughTools(
reach,tools): readonlyobject[]
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
| Parameter | Type |
|---|---|
reach | readonly object[] |
tools | readonly 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
| Parameter | Type |
|---|---|
report | ((error, context) => void) | undefined |
error | unknown |
context | Context |
Returns
void
sha256Hex()
sha256Hex(
value):Promise<string>>
Defined in: packages/core/src/hashing.ts:16
Parameters
| Parameter | Type |
|---|---|
value | string |
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.authorityalready scopes what aGrantSourcemay 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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
reader.namespaceId | string |
reader.now | string |
reader.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
reader.purpose | string |
reader.traceId | string |
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
| Parameter | Type |
|---|---|
reach | readonly 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
| Parameter | Type |
|---|---|
sets | readonly 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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
request | ResourceInvocationRequest |
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?
optionalinput?:JsonValue
metadata?
optionalmetadata?:JsonObject
operationId
operationId:
string
resource
resource:
object
resource.namespace
namespace:
string
resource.owner?
optionalowner?: {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
| Parameter | Type |
|---|---|
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
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.admittedAtand an expired one atnow, 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
| Parameter | Type |
|---|---|
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.capabilities | object[] |
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.id | string |
grant.issuedAt | string |
grant.issuer | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
grant.metadata? | JsonObject |
grant.namespaceId | string |
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.enabledToolNamespaces | string[] |
context.namespaceId | string |
context.now | string |
context.owner | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } |
context.purpose | string |
context.traceId | string |
now | number |
options | DelegationValidationOptions |
Returns
Promise<DelegationValidation>