@arnilo/prism 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/agent-run-lifecycle.d.ts +5 -1
  3. package/dist/agent-run-lifecycle.js +17 -1
  4. package/dist/agents.d.ts +3 -1
  5. package/dist/agents.js +98 -20
  6. package/dist/contracts.d.ts +29 -1
  7. package/dist/extensions.d.ts +11 -0
  8. package/dist/extensions.js +15 -0
  9. package/dist/identity.d.ts +92 -0
  10. package/dist/identity.js +257 -0
  11. package/dist/index.d.ts +8 -4
  12. package/dist/index.js +4 -2
  13. package/dist/persistence-lifecycle.d.ts +103 -0
  14. package/dist/persistence-lifecycle.js +204 -0
  15. package/dist/providers/openai-compatible.d.ts +5 -1
  16. package/dist/providers/openai-compatible.js +15 -6
  17. package/dist/secure-agent.js +7 -1
  18. package/dist/testing/persistence-schema.d.ts +2 -2
  19. package/dist/testing/persistence-schema.js +35 -2
  20. package/dist/tools.d.ts +2 -0
  21. package/dist/tools.js +6 -0
  22. package/docs/a2a.md +3 -0
  23. package/docs/ag-ui.md +123 -0
  24. package/docs/agent-events.md +2 -1
  25. package/docs/agent-identity.md +111 -0
  26. package/docs/agent-session-runtime.md +5 -1
  27. package/docs/coding-agent-tools.md +2 -0
  28. package/docs/compaction-and-retry.md +2 -1
  29. package/docs/compaction-llm.md +20 -1
  30. package/docs/credential-storage.md +5 -1
  31. package/docs/credentials-and-redaction.md +8 -0
  32. package/docs/database-persistence.md +18 -7
  33. package/docs/extensions.md +1 -0
  34. package/docs/guardrails.md +3 -0
  35. package/docs/host-security.md +7 -1
  36. package/docs/index.md +25 -14
  37. package/docs/mcp-tools.md +2 -0
  38. package/docs/migration.md +43 -0
  39. package/docs/model-routing.md +102 -0
  40. package/docs/observability.md +2 -0
  41. package/docs/performance.md +38 -0
  42. package/docs/policy-and-audit.md +127 -0
  43. package/docs/postgres-persistence.md +1 -1
  44. package/docs/provider-packages.md +17 -0
  45. package/docs/provider-request-policies.md +2 -0
  46. package/docs/providers/anthropic.md +3 -2
  47. package/docs/providers/azure.md +74 -0
  48. package/docs/providers/bedrock.md +72 -0
  49. package/docs/providers/google.md +4 -2
  50. package/docs/providers/openai-compatible.md +3 -1
  51. package/docs/providers/openai.md +2 -2
  52. package/docs/providers/openrouter.md +2 -0
  53. package/docs/providers/vertex.md +71 -0
  54. package/docs/public-contracts.md +5 -1
  55. package/docs/release-and-install.md +167 -17
  56. package/docs/review-coverage-2026-07-22-phase-7.md +173 -0
  57. package/docs/review-coverage-2026-07-23-phase-8.md +245 -0
  58. package/docs/runs-and-usage.md +3 -0
  59. package/docs/server.md +34 -4
  60. package/docs/sqlite-persistence.md +1 -1
  61. package/docs/supervisors.md +2 -0
  62. package/docs/work-connectors.md +28 -0
  63. package/docs/work-tools.md +114 -0
  64. package/package.json +5 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.13] - 2026-07-24
4
+
5
+ ### Added
6
+
7
+ - Enterprise identity (`Principal` / `AgentIdentity`), optional `@arnilo/prism-policy`, `@arnilo/prism-model-router`, enterprise cloud providers (Azure/Bedrock/Vertex), server deployment seams, persistence schema v5 lifecycle hooks, and `@arnilo/prism-work-tools` (M365 + GWS).
8
+
9
+ ### Changed
10
+
11
+ - Versioned all **41** first-party manifests and exact internal ranges to `0.0.13`; Phase 8 optional packages enroll in `@arnilo/prism-all` only.
12
+ - Network-free enterprise evidence: `scripts/benchmark-0.0.13.mjs`.
13
+
3
14
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
15
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
16
 
@@ -7,6 +18,19 @@ All notable changes to this project will be documented in this file.
7
18
 
8
19
  ## [Unreleased]
9
20
 
21
+ ## [0.0.12] - 2026-07-22
22
+
23
+ ### Added
24
+
25
+ - Optional `@arnilo/prism-ag-ui` package with bounded AG-UI mapper/authorized handler/replay and stable `./acp` sibling, built over shared durable resume streams.
26
+ - `createCodingCompactionStrategy()` preset for bounded coding-session handoff.
27
+
28
+ ### Changed
29
+
30
+ - Versioned all 35 first-party manifests and exact internal ranges to `0.0.12`; `@arnilo/prism-all` includes AG-UI while `@arnilo/prism-code` and `@arnilo/prism-sdk` remain free of UI protocol dependencies.
31
+ - Added network-free interoperability/compaction evidence: `scripts/benchmark-0.0.12.mjs`.
32
+
33
+
10
34
  ## [0.0.11] - 2026-07-22
11
35
 
12
36
  ### Added
@@ -1,4 +1,4 @@
1
- import type { Agent, AgentRunRef, AgentRunResult, AgentRunResume, AgentRunStatusResult, OwnershipScope } from "./contracts.js";
1
+ import type { Agent, AgentEvent, AgentRunRef, AgentRunResult, AgentRunResume, AgentRunStatusResult, OwnershipScope, SubscribeOptions } from "./contracts.js";
2
2
  import type { CheckpointStore } from "./contracts.js";
3
3
  export interface AgentRunLifecycleAgent {
4
4
  readonly agent: Agent;
@@ -20,9 +20,13 @@ export interface AgentRunLifecycleRequest {
20
20
  /** Adapter-selected capability; stored runs for another agent are non-enumerable. */
21
21
  readonly agentId?: string;
22
22
  }
23
+ /** Bounded live-event options for a durable lifecycle resume. */
24
+ export interface AgentRunLifecycleStreamRequest extends AgentRunLifecycleRequest, SubscribeOptions {
25
+ }
23
26
  export interface AgentRunLifecycle {
24
27
  status(ref: AgentRunRef, options?: AgentRunLifecycleRequest): Promise<AgentRunStatusResult>;
25
28
  resume(ref: AgentRunRef, resume: AgentRunResume, options?: AgentRunLifecycleRequest): Promise<AgentRunResult>;
29
+ resumeStream(ref: AgentRunRef, resume: AgentRunResume, options?: AgentRunLifecycleStreamRequest): AsyncIterable<AgentEvent>;
26
30
  }
27
31
  /** Host capability for durable agent status/resume. Adapters supply authorized ownership only. */
28
32
  export declare function createAgentRunLifecycle(options: AgentRunLifecycleOptions): AgentRunLifecycle;
@@ -1,6 +1,6 @@
1
1
  import { AgentRunStateError } from "./contracts.js";
2
2
  import { loadAgentRunState, publicState } from "./agent-run-state.js";
3
- import { resumeAgentRun } from "./agents.js";
3
+ import { resumeAgentRun, resumeAgentRunStream } from "./agents.js";
4
4
  function assertAgentId(actual, expected) {
5
5
  if (expected !== undefined && actual !== expected)
6
6
  throw new AgentRunStateError("Agent run capability mismatch");
@@ -28,6 +28,22 @@ export function createAgentRunLifecycle(options) {
28
28
  definitionRevision: resolved.definitionRevision,
29
29
  });
30
30
  },
31
+ async *resumeStream(ref, resume, request = {}) {
32
+ request.signal?.throwIfAborted();
33
+ const { state } = await loadAgentRunState(options.checkpoints, ref, request.ownership);
34
+ assertAgentId(state.agentId, request.agentId);
35
+ const resolved = await options.resolveAgent({ agentId: state.agentId, ownership: request.ownership, signal: request.signal });
36
+ request.signal?.throwIfAborted();
37
+ yield* resumeAgentRunStream(resolved.agent, ref, resume, {
38
+ checkpoints: options.checkpoints,
39
+ ownership: request.ownership,
40
+ fencingToken: options.fencingToken,
41
+ definitionRevision: resolved.definitionRevision,
42
+ signal: request.signal,
43
+ maxQueuedEvents: request.maxQueuedEvents,
44
+ overflow: request.overflow,
45
+ });
46
+ },
31
47
  };
32
48
  }
33
49
  //# sourceMappingURL=agent-run-lifecycle.js.map
package/dist/agents.d.ts CHANGED
@@ -1,7 +1,9 @@
1
- import type { Agent, AgentConfig, AgentRunResult, AgentRunResume, AgentRunResumeOptions, AgentRunRef, AgentSession, AgentSessionConfig } from "./contracts.js";
1
+ import type { Agent, AgentConfig, AgentEvent, AgentRunResult, AgentRunResume, AgentRunResumeOptions, AgentRunResumeStreamOptions, AgentRunRef, AgentSession, AgentSessionConfig } from "./contracts.js";
2
2
  export declare function createAgent(config: AgentConfig): Agent;
3
3
  export declare function createAgentSession(config: AgentSessionConfig & {
4
4
  readonly agent: Agent;
5
5
  }): AgentSession;
6
6
  /** Resume a persisted built-in run. A claimed/dispatched tool is never replayed automatically. */
7
7
  export declare function resumeAgentRun(agent: Agent, ref: AgentRunRef, resume: AgentRunResume, options: AgentRunResumeOptions): Promise<AgentRunResult>;
8
+ /** Subscribe before resuming one durable run. Early consumer return aborts that resumed execution. */
9
+ export declare function resumeAgentRunStream(agent: Agent, ref: AgentRunRef, resume: AgentRunResume, options: AgentRunResumeStreamOptions): AsyncGenerator<AgentEvent>;
package/dist/agents.js CHANGED
@@ -17,6 +17,7 @@ import { createToolRegistry, dispatchToolCall } from "./tools.js";
17
17
  import { RunLimitError, RunLimitTracker, resolveRunLimits } from "./run-limits.js";
18
18
  import { agentFingerprint, initialAgentRunState, loadAgentRunState, publicState, saveAgentRunState, validateRunStateOptions } from "./agent-run-state.js";
19
19
  import { resolveActiveSkills } from "./skills.js";
20
+ import { identityTelemetryAttributes, ownershipFromIdentity, resolveRunIdentity, } from "./identity.js";
20
21
  export function createAgent(config) {
21
22
  return {
22
23
  config,
@@ -30,6 +31,32 @@ export function createAgentSession(config) {
30
31
  }
31
32
  /** Resume a persisted built-in run. A claimed/dispatched tool is never replayed automatically. */
32
33
  export async function resumeAgentRun(agent, ref, resume, options) {
34
+ return executePreparedAgentRunResume(await prepareAgentRunResume(agent, ref, resume, options));
35
+ }
36
+ /** Subscribe before resuming one durable run. Early consumer return aborts that resumed execution. */
37
+ export async function* resumeAgentRunStream(agent, ref, resume, options) {
38
+ throwIfAbortedSignal(options.signal);
39
+ const prepared = await prepareAgentRunResume(agent, ref, resume, options, options.signal);
40
+ const subscription = prepared.session.subscribe(options);
41
+ let settled = false;
42
+ const runPromise = executePreparedAgentRunResume(prepared, options.signal).finally(() => { settled = true; });
43
+ try {
44
+ for await (const event of subscription) {
45
+ if ("runId" in event && event.runId !== ref.runId)
46
+ continue;
47
+ yield event;
48
+ }
49
+ await runPromise;
50
+ }
51
+ finally {
52
+ if (!settled) {
53
+ prepared.session.abort(new Error("resume stream consumer closed"));
54
+ await runPromise.catch(() => undefined);
55
+ }
56
+ }
57
+ }
58
+ async function prepareAgentRunResume(agent, ref, resume, options, signal) {
59
+ throwIfAbortedSignal(signal);
33
60
  const { record, state } = await loadAgentRunState(options.checkpoints, ref, options.ownership);
34
61
  if (state.definitionRevision !== options.definitionRevision || state.agentId !== (agent.config.id ?? agent.config.name) || state.fingerprint !== agentFingerprint(agent, options.definitionRevision)) {
35
62
  throw new AgentRunStateError("Agent definition revision or fingerprint mismatch on resume");
@@ -37,7 +64,9 @@ export async function resumeAgentRun(agent, ref, resume, options) {
37
64
  if (record.version !== resume.expectedVersion || state.status !== "suspended") {
38
65
  throw new AgentRunStateError("Stale or non-suspended agent run resume");
39
66
  }
67
+ const session = new RuntimeAgentSession({ agent, id: state.sessionId, leafId: state.leafId });
40
68
  if (resume.decision === "deny") {
69
+ throwIfAbortedSignal(signal);
41
70
  const denied = await saveAgentRunState({
42
71
  checkpoints: options.checkpoints,
43
72
  state: { ...state, status: "denied" },
@@ -45,10 +74,23 @@ export async function resumeAgentRun(agent, ref, resume, options) {
45
74
  ownership: options.ownership,
46
75
  fencingToken: options.fencingToken,
47
76
  });
48
- const session = new RuntimeAgentSession({ agent, id: state.sessionId, leafId: state.leafId });
49
- await session.recordDurableDenial(state.runId, state.interruption, denied.record.version, options.ownership);
50
- const runState = publicState(denied.state);
51
- return { sessionId: state.sessionId, runId: state.runId, status: "denied", leafId: state.leafId, text: "", content: [], runState, interruption: state.interruption };
77
+ return {
78
+ kind: "deny",
79
+ session,
80
+ interruption: state.interruption,
81
+ version: denied.record.version,
82
+ ownership: options.ownership,
83
+ result: {
84
+ sessionId: state.sessionId,
85
+ runId: state.runId,
86
+ status: "denied",
87
+ leafId: state.leafId,
88
+ text: "",
89
+ content: [],
90
+ runState: publicState(denied.state),
91
+ interruption: state.interruption,
92
+ },
93
+ };
52
94
  }
53
95
  if (state.pending?.status === "dispatched")
54
96
  throw new AgentRunStateError("Ambiguous dispatched tool requires operator resolution");
@@ -56,6 +98,7 @@ export async function resumeAgentRun(agent, ref, resume, options) {
56
98
  if (configured && (configured.checkpoints !== options.checkpoints || configured.definitionRevision !== options.definitionRevision)) {
57
99
  throw new AgentRunStateError("Agent durable run-state configuration mismatch on resume");
58
100
  }
101
+ throwIfAbortedSignal(signal);
59
102
  const claimed = await saveAgentRunState({
60
103
  checkpoints: options.checkpoints,
61
104
  state: { ...state, status: "running", interruption: undefined },
@@ -63,13 +106,25 @@ export async function resumeAgentRun(agent, ref, resume, options) {
63
106
  ownership: options.ownership,
64
107
  fencingToken: options.fencingToken,
65
108
  });
66
- const session = new RuntimeAgentSession({ agent, id: state.sessionId, leafId: state.leafId });
67
- return session.resumeDurable(claimed.state, configured ?? {
68
- checkpoints: options.checkpoints,
69
- definitionRevision: options.definitionRevision,
70
- interruptBeforeTool: state.interruptBeforeTool,
71
- fencingToken: options.fencingToken,
72
- }, options.ownership);
109
+ return {
110
+ kind: "approve",
111
+ session,
112
+ state: claimed.state,
113
+ ownership: options.ownership,
114
+ runState: configured ?? {
115
+ checkpoints: options.checkpoints,
116
+ definitionRevision: options.definitionRevision,
117
+ interruptBeforeTool: state.interruptBeforeTool,
118
+ fencingToken: options.fencingToken,
119
+ },
120
+ };
121
+ }
122
+ async function executePreparedAgentRunResume(prepared, signal) {
123
+ if (prepared.kind === "deny") {
124
+ await prepared.session.recordDurableDenial(prepared.result.runId, prepared.interruption, prepared.version, prepared.ownership);
125
+ return prepared.result;
126
+ }
127
+ return prepared.session.resumeDurable(prepared.state, prepared.runState, prepared.ownership, signal);
73
128
  }
74
129
  class AgentRunSuspended extends Error {
75
130
  state;
@@ -100,6 +155,7 @@ class RuntimeAgentSession {
100
155
  activeProvider;
101
156
  activeLedger;
102
157
  activeOwnership;
158
+ activeIdentity;
103
159
  activeIdempotencyKey;
104
160
  activeGuardrails;
105
161
  activeMetadata;
@@ -154,18 +210,23 @@ class RuntimeAgentSession {
154
210
  this.pendingSoftInterrupt = true;
155
211
  }
156
212
  }
157
- async resumeDurable(state, runState, ownership) {
158
- return this.runInternal(state.input ?? [], { runState, ownership }, state.runId, { options: runState, state, version: state.version });
213
+ async resumeDurable(state, runState, ownership, signal) {
214
+ return this.runInternal(state.input ?? [], { runState, ownership, signal }, state.runId, { options: runState, state, version: state.version });
159
215
  }
160
216
  async recordDurableDenial(runId, interruption, version, ownership) {
161
217
  this.activeLedger = this.agent.config.runLedger;
162
218
  this.activeOwnership = ownership ?? this.agent.config.ownership;
163
219
  this.activeRedactor = this.agent.config.redactor;
164
- this.emit({ type: "agent_denied", sessionId: this.id, runId, interruption, version });
165
- await this.drainLedger();
166
- this.activeLedger = undefined;
167
- this.activeOwnership = undefined;
168
- this.activeRedactor = undefined;
220
+ try {
221
+ this.emit({ type: "agent_denied", sessionId: this.id, runId, interruption, version });
222
+ await this.drainLedger();
223
+ }
224
+ finally {
225
+ this.activeLedger = undefined;
226
+ this.activeOwnership = undefined;
227
+ this.activeRedactor = undefined;
228
+ this.closeSubscribers();
229
+ }
169
230
  }
170
231
  async runInternal(input, options, runId, resumed) {
171
232
  if (this.agent.config.secure && (options.redactor !== undefined || options.ownership !== undefined || options.validate !== undefined || options.runState !== undefined)) {
@@ -202,6 +263,9 @@ class RuntimeAgentSession {
202
263
  this.activeRedactor = options.redactor ?? this.agent.config.redactor;
203
264
  this.activeLedger = options.runLedger ?? this.agent.config.runLedger;
204
265
  this.activeOwnership = options.ownership ?? this.agent.config.ownership;
266
+ this.activeIdentity = resolveRunIdentity(options.identity, this.agent.config.identity, this.activeOwnership);
267
+ if (this.activeIdentity && !this.activeOwnership)
268
+ this.activeOwnership = ownershipFromIdentity(this.activeIdentity);
205
269
  this.activeIdempotencyKey = options.idempotencyKey ?? this.agent.config.idempotencyKey;
206
270
  this.activeGuardrails = mergeGuardrails(this.agent.config.guardrails, options.guardrails);
207
271
  this.activeDurable = resumed ?? (durableOptions ? { options: durableOptions, version: 0 } : undefined);
@@ -213,7 +277,12 @@ class RuntimeAgentSession {
213
277
  let runStatus = "succeeded";
214
278
  const runUsage = createUsageAccumulator();
215
279
  let usage;
216
- const metadata = { ...this.agent.config.metadata, ...this.metadata, ...options.metadata };
280
+ const metadata = {
281
+ ...this.agent.config.metadata,
282
+ ...this.metadata,
283
+ ...options.metadata,
284
+ ...(this.activeIdentity ? identityTelemetryAttributes(this.activeIdentity) : {}),
285
+ };
217
286
  this.activeMetadata = metadata;
218
287
  const limits = new RunLimitTracker(resolvedLimits, {
219
288
  onExceeded: (breach) => {
@@ -375,7 +444,14 @@ class RuntimeAgentSession {
375
444
  dispatchToolCall: (call) => dispatchToolCall({
376
445
  call,
377
446
  registry,
378
- context: { sessionId: this.id, runId, toolCallId: call.id, signal: controller.signal, metadata },
447
+ context: {
448
+ sessionId: this.id,
449
+ runId,
450
+ toolCallId: call.id,
451
+ signal: controller.signal,
452
+ metadata,
453
+ identity: this.activeIdentity,
454
+ },
379
455
  middleware: this.agent.config.middleware,
380
456
  emit: (event) => this.emit(event),
381
457
  permission: this.agent.config.permission,
@@ -383,6 +459,7 @@ class RuntimeAgentSession {
383
459
  redactor: this.activeRedactor,
384
460
  ledger: this.activeLedger,
385
461
  ownership: this.activeOwnership,
462
+ identity: this.activeIdentity,
386
463
  guardrails: this.activeGuardrails,
387
464
  limitTracker: limits,
388
465
  beforeExecute: async (mediatedCall) => {
@@ -518,6 +595,7 @@ class RuntimeAgentSession {
518
595
  finally {
519
596
  this.activeLedger = undefined;
520
597
  this.activeOwnership = undefined;
598
+ this.activeIdentity = undefined;
521
599
  this.activeIdempotencyKey = undefined;
522
600
  this.activeGuardrails = undefined;
523
601
  this.activeMetadata = undefined;
@@ -287,6 +287,8 @@ export interface RunOptions {
287
287
  readonly redactor?: SecretRedactor;
288
288
  readonly runLedger?: RunLedger;
289
289
  readonly ownership?: OwnershipScope;
290
+ /** Host-verified identity; when set, must project onto `ownership` without widening. */
291
+ readonly identity?: import("./identity.js").AgentIdentity;
290
292
  readonly idempotencyKey?: string;
291
293
  readonly validate?: ToolValidator;
292
294
  readonly activeSkills?: readonly string[];
@@ -352,6 +354,8 @@ export interface AgentConfig {
352
354
  readonly redactor?: SecretRedactor;
353
355
  readonly runLedger?: RunLedger;
354
356
  readonly ownership?: OwnershipScope;
357
+ /** Host-verified identity default for sessions created from this agent. */
358
+ readonly identity?: import("./identity.js").AgentIdentity;
355
359
  readonly idempotencyKey?: string;
356
360
  readonly compaction?: false | CompactionOptions;
357
361
  readonly retry?: false | RetryOptions;
@@ -369,7 +373,7 @@ export interface AgentConfig {
369
373
  readonly secure?: true;
370
374
  }
371
375
  /** Opt-in fail-closed composition over the normal explicit AgentConfig API. */
372
- export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validator" | "redactor" | "permission" | "trust" | "ownership" | "limits" | "runState" | "secure"> {
376
+ export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validator" | "redactor" | "permission" | "trust" | "ownership" | "identity" | "limits" | "runState" | "secure"> {
373
377
  readonly id: string;
374
378
  readonly tools: readonly ToolDefinition[];
375
379
  readonly toolArgumentValidator: import("./tools.js").ToolArgumentValidator;
@@ -377,6 +381,8 @@ export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validat
377
381
  readonly permission: PermissionPolicy;
378
382
  readonly trust: TrustPolicy;
379
383
  readonly ownership: OwnershipScope;
384
+ /** Optional host-verified identity; when set must match `ownership`. */
385
+ readonly identity?: import("./identity.js").AgentIdentity;
380
386
  readonly limits: RunLimits;
381
387
  readonly definitionRevision: string;
382
388
  readonly runState: Omit<AgentRunStateOptions, "definitionRevision" | "interruptBeforeTool">;
@@ -449,6 +455,10 @@ export interface AgentRunResumeOptions {
449
455
  readonly ownership?: OwnershipScope;
450
456
  readonly fencingToken?: number;
451
457
  }
458
+ /** Bounded, abortable options for `resumeAgentRunStream()`. */
459
+ export interface AgentRunResumeStreamOptions extends AgentRunResumeOptions, SubscribeOptions {
460
+ readonly signal?: AbortSignal;
461
+ }
452
462
  export interface AgentRunRef {
453
463
  readonly runId: string;
454
464
  readonly sessionId?: string;
@@ -746,6 +756,8 @@ export interface ToolExecutionContext {
746
756
  readonly toolCallId: string;
747
757
  readonly signal?: AbortSignal;
748
758
  readonly metadata?: Readonly<Record<string, unknown>>;
759
+ /** Host-verified identity for this tool invocation, when enterprise identity is active. */
760
+ readonly identity?: import("./identity.js").AgentIdentity;
749
761
  progress?(progress?: unknown, metadata?: Readonly<Record<string, unknown>>): void | Promise<void>;
750
762
  }
751
763
  export interface ToolResult {
@@ -896,6 +908,9 @@ export interface ExtensionEvent {
896
908
  export interface Extension {
897
909
  readonly name: string;
898
910
  setup(api: ExtensionAPI): void | Promise<void>;
911
+ /** Host-attested signature/digest for `ExtensionLoadPolicy.verifySignature`. */
912
+ readonly signature?: string;
913
+ readonly metadata?: Readonly<Record<string, unknown>>;
899
914
  }
900
915
  export interface ProviderPackage {
901
916
  readonly name: string;
@@ -1601,6 +1616,11 @@ export interface ProductionPersistenceStore {
1601
1616
  /** DB-friendly branch read (mirrors `SessionStore.readBranchPath`): one ancestor-chain
1602
1617
  * query instead of `queryEntries({ sessionId })` + in-memory walk. Optional. */
1603
1618
  readBranchPath?(query: SessionBranchRead): Promise<PersistencePage<SessionEntry>>;
1619
+ /**
1620
+ * Optional Phase 8 retention / legal-hold / export / tenant-quota lifecycle.
1621
+ * Prefer attaching `createMemoryPersistenceLifecycle()` or adapter-native methods.
1622
+ */
1623
+ readonly lifecycle?: import("./persistence-lifecycle.js").PersistenceLifecycleStore;
1604
1624
  readonly metadata?: Readonly<Record<string, unknown>>;
1605
1625
  }
1606
1626
  export interface CompactionStrategy {
@@ -1792,3 +1812,11 @@ export interface ArtifactParseResult<T> {
1792
1812
  export type ArtifactParser<T> = (text: string, ctx: ArtifactContext) => ArtifactParseResult<T> | Promise<ArtifactParseResult<T>>;
1793
1813
  export type ArtifactValidator<T> = (value: T, ctx: ArtifactContext) => ArtifactValidation | Promise<ArtifactValidation>;
1794
1814
  export type ArtifactRepairer<T> = (value: T | undefined, failure: ArtifactValidation, ctx: ArtifactContext) => AgentInput | Promise<AgentInput>;
1815
+ /** Alias re-exports so `dist/contracts.d.ts` exposes implementer contract names. */
1816
+ export type AgentIdentity = import("./identity.js").AgentIdentity;
1817
+ export type Principal = import("./identity.js").Principal;
1818
+ export type IdentityVerifier = import("./identity.js").IdentityVerifier;
1819
+ export type PersistenceLifecycleStore = import("./persistence-lifecycle.js").PersistenceLifecycleStore;
1820
+ export type LegalHoldRecord = import("./persistence-lifecycle.js").LegalHoldRecord;
1821
+ export type TenantQuota = import("./persistence-lifecycle.js").TenantQuota;
1822
+ export type PersistenceResourceKind = import("./persistence-lifecycle.js").PersistenceResourceKind;
@@ -4,12 +4,23 @@ import { type MiddlewareRegistry } from "./middleware.js";
4
4
  import { type PermissionPolicy } from "./security.js";
5
5
  export type ExtensionEventHandler = (event: ExtensionEvent) => void | Promise<void>;
6
6
  export type ExtensionErrorPolicy = "event" | "throw";
7
+ export interface ExtensionLoadPolicy {
8
+ /** When set, only listed extension names may load. */
9
+ readonly allowList?: readonly string[];
10
+ /**
11
+ * Host signature / attestation check. Return false or throw to deny.
12
+ * Unsigned extensions fail closed when this callback is provided.
13
+ */
14
+ readonly verifySignature?: (extension: Extension) => boolean | Promise<boolean>;
15
+ }
7
16
  export interface ExtensionKernelOptions {
8
17
  readonly registries?: ContributionRegistries;
9
18
  readonly middleware?: MiddlewareRegistry;
10
19
  readonly errorPolicy?: ExtensionErrorPolicy;
11
20
  readonly secrets?: readonly (string | undefined)[];
12
21
  readonly permission?: PermissionPolicy;
22
+ /** Optional allow-list / signature policy evaluated before `setup`. */
23
+ readonly loadPolicy?: ExtensionLoadPolicy;
13
24
  }
14
25
  export interface ExtensionEventBus {
15
26
  on(type: ExtensionLifecycleEventName | string, handler: ExtensionEventHandler): () => void;
@@ -120,6 +120,7 @@ export function createExtensionKernel(options = {}) {
120
120
  for (const extension of extensions) {
121
121
  try {
122
122
  await assertPermission(options.permission, { kind: "extension", action: "setup", target: extension.name });
123
+ await assertExtensionLoadPolicy(options.loadPolicy, extension);
123
124
  await extension.setup(api);
124
125
  }
125
126
  catch (error) {
@@ -131,4 +132,18 @@ export function createExtensionKernel(options = {}) {
131
132
  },
132
133
  };
133
134
  }
135
+ async function assertExtensionLoadPolicy(policy, extension) {
136
+ if (!policy)
137
+ return;
138
+ if (policy.allowList && !policy.allowList.includes(extension.name)) {
139
+ throw new Error(`Extension "${extension.name}" is not allow-listed`);
140
+ }
141
+ if (policy.verifySignature) {
142
+ if (!extension.signature)
143
+ throw new Error(`Extension "${extension.name}" is unsigned`);
144
+ const ok = await policy.verifySignature(extension);
145
+ if (!ok)
146
+ throw new Error(`Extension "${extension.name}" failed signature verification`);
147
+ }
148
+ }
134
149
  //# sourceMappingURL=extensions.js.map
@@ -0,0 +1,92 @@
1
+ import type { OwnershipScope } from "./contracts.js";
2
+ /** Host-authenticated actor (user, service, or agent principal). */
3
+ export interface Principal {
4
+ readonly kind: "user" | "service" | "agent" | string;
5
+ readonly id: string;
6
+ readonly displayName?: string;
7
+ }
8
+ /**
9
+ * Host-verified identity context. Projects onto {@link OwnershipScope}.
10
+ * `verified: true` marks host-verifier output; trust boundaries must obtain this
11
+ * via {@link IdentityVerifier}, never by accepting caller-asserted claims alone.
12
+ */
13
+ export interface AgentIdentity {
14
+ readonly tenantId: string;
15
+ readonly accountId?: string;
16
+ readonly userId?: string;
17
+ /** Acting principal for this run/tool/delegation. */
18
+ readonly principal: Principal;
19
+ /** Human sponsor accountable for the agent lifecycle (Entra-style). */
20
+ readonly sponsor?: Principal;
21
+ /** Resource owner when distinct from sponsor. */
22
+ readonly owner?: Principal;
23
+ /** Parent principal when this identity is a narrowed delegation. */
24
+ readonly delegatedFrom?: Principal;
25
+ readonly scopes: readonly string[];
26
+ /** Late-bound credential resolver keys — never secret material. */
27
+ readonly credentialRefs?: readonly string[];
28
+ readonly issuedAt: string;
29
+ readonly expiresAt?: string;
30
+ readonly revokedAt?: string;
31
+ readonly metadata?: Readonly<Record<string, unknown>>;
32
+ readonly verified: true;
33
+ }
34
+ export interface IdentityVerifier {
35
+ verify(input: unknown): AgentIdentity | Promise<AgentIdentity>;
36
+ }
37
+ export interface AssertIdentityActiveOptions {
38
+ readonly now?: number;
39
+ /** When set, identity.tenantId must equal this value. */
40
+ readonly expectedTenantId?: string;
41
+ readonly limits?: IdentityLimits;
42
+ }
43
+ export interface NarrowIdentityOptions {
44
+ readonly scopes: readonly string[];
45
+ readonly principal?: Principal;
46
+ readonly credentialRefs?: readonly string[];
47
+ readonly expiresAt?: string;
48
+ readonly metadata?: Readonly<Record<string, unknown>>;
49
+ readonly limits?: IdentityLimits;
50
+ }
51
+ export interface IdentityLimits {
52
+ readonly maxScopes?: number;
53
+ readonly maxScopeBytes?: number;
54
+ readonly maxMetadataBytes?: number;
55
+ readonly maxCredentialRefBytes?: number;
56
+ readonly maxPrincipalIdBytes?: number;
57
+ }
58
+ export interface ResolvedIdentityLimits {
59
+ readonly maxScopes: number;
60
+ readonly maxScopeBytes: number;
61
+ readonly maxMetadataBytes: number;
62
+ readonly maxCredentialRefBytes: number;
63
+ readonly maxPrincipalIdBytes: number;
64
+ }
65
+ export declare const DEFAULT_IDENTITY_LIMITS: ResolvedIdentityLimits;
66
+ export declare const HARD_IDENTITY_LIMITS: ResolvedIdentityLimits;
67
+ export declare class IdentityError extends Error {
68
+ readonly reason: string;
69
+ readonly code = "ERR_PRISM_IDENTITY";
70
+ constructor(message: string, reason: string);
71
+ }
72
+ export declare function resolveIdentityLimits(input?: IdentityLimits): ResolvedIdentityLimits;
73
+ /** Project verified identity onto ownership scope fields used by persistence/server. */
74
+ export declare function ownershipFromIdentity(identity: AgentIdentity): OwnershipScope;
75
+ /**
76
+ * Fail closed on shape/limits/expiry/revocation/tenant mismatch.
77
+ * Sync and network-free — host {@link IdentityVerifier} owns remote checks.
78
+ */
79
+ export declare function assertIdentityActive(identity: AgentIdentity, options?: AssertIdentityActiveOptions): void;
80
+ /** Delegation may only narrow scopes; tenant and ownership ids stay immutable. */
81
+ export declare function narrowIdentity(parent: AgentIdentity, options: NarrowIdentityOptions): AgentIdentity;
82
+ /** Refuse ownership that widens or conflicts with a verified identity. */
83
+ export declare function assertIdentityMatchesOwnership(identity: AgentIdentity, ownership?: OwnershipScope): void;
84
+ /**
85
+ * Propagation check: child must share tenant, not widen scopes, and remain active.
86
+ * Used by supervisor/A2A/MCP/server when forwarding identity across a boundary.
87
+ */
88
+ export declare function assertIdentityPropagation(parent: AgentIdentity, child: AgentIdentity, options?: AssertIdentityActiveOptions): void;
89
+ /** Redacted identity refs safe for telemetry/ledger metadata (no secrets, no raw JWT). */
90
+ export declare function identityTelemetryAttributes(identity: AgentIdentity): Readonly<Record<string, string>>;
91
+ /** Resolve run identity: explicit option wins; otherwise agent default. Assert when present. */
92
+ export declare function resolveRunIdentity(runIdentity: AgentIdentity | undefined, agentIdentity: AgentIdentity | undefined, ownership: OwnershipScope | undefined, options?: AssertIdentityActiveOptions): AgentIdentity | undefined;