@kya-os/mcp-i 1.10.0 → 1.11.1

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 (51) hide show
  1. package/dist/317.js +1 -0
  2. package/dist/342.js +1 -0
  3. package/dist/354.js +1 -1
  4. package/dist/95.js +1 -1
  5. package/dist/auth/oauth/router.js +2 -2
  6. package/dist/cli-adapter/index.js +1 -1
  7. package/dist/providers/node-providers.d.ts +1 -1
  8. package/dist/providers/node-providers.js +9 -9
  9. package/dist/runtime/337.js +1 -0
  10. package/dist/runtime/adapter-express.js +3 -3
  11. package/dist/runtime/adapter-nextjs.js +5 -5
  12. package/dist/runtime/audit.d.ts +1 -1
  13. package/dist/runtime/auth-handshake.d.ts +1 -1
  14. package/dist/runtime/auth-handshake.js +4 -4
  15. package/dist/runtime/debug.d.ts +1 -1
  16. package/dist/runtime/debug.js +3 -2
  17. package/dist/runtime/delegation-hooks.d.ts +1 -1
  18. package/dist/runtime/delegation-verifier-agentshield.js +1 -0
  19. package/dist/runtime/http.js +3 -3
  20. package/dist/runtime/identity.d.ts +4 -4
  21. package/dist/runtime/identity.js +4 -4
  22. package/dist/runtime/index.d.ts +6 -2
  23. package/dist/runtime/index.js +10 -2
  24. package/dist/runtime/mcpi-runtime-wrapper.d.ts +1 -1
  25. package/dist/runtime/mcpi-runtime-wrapper.js +4 -4
  26. package/dist/runtime/mcpi-runtime.d.ts +9 -1
  27. package/dist/runtime/mcpi-runtime.js +21 -3
  28. package/dist/runtime/outbound-delegation.d.ts +5 -3
  29. package/dist/runtime/outbound-delegation.js +15 -8
  30. package/dist/runtime/outbound-identity-bridge.d.ts +40 -0
  31. package/dist/runtime/outbound-identity-bridge.js +119 -0
  32. package/dist/runtime/proof-batch-queue.d.ts +1 -1
  33. package/dist/runtime/proof.d.ts +2 -2
  34. package/dist/runtime/proof.js +3 -3
  35. package/dist/runtime/request-context.d.ts +10 -0
  36. package/dist/runtime/request-context.js +4 -0
  37. package/dist/runtime/resume-token-store-kv.d.ts +44 -0
  38. package/dist/runtime/resume-token-store-kv.js +93 -0
  39. package/dist/runtime/resume-token-store.d.ts +30 -0
  40. package/dist/runtime/resume-token-store.js +46 -0
  41. package/dist/runtime/session.d.ts +2 -2
  42. package/dist/runtime/session.js +12 -6
  43. package/dist/runtime/stdio.js +3 -3
  44. package/dist/runtime/utils/tools.d.ts +2 -2
  45. package/dist/runtime/utils/tools.js +33 -10
  46. package/dist/runtime/well-known.d.ts +12 -1
  47. package/dist/runtime/well-known.js +13 -2
  48. package/package.json +6 -4
  49. package/dist/225.js +0 -1
  50. package/dist/runtime/verifier-middleware.d.ts +0 -99
  51. package/dist/runtime/verifier-middleware.js +0 -416
@@ -113,16 +113,16 @@ export declare class IdentityManager {
113
113
  export declare const defaultIdentityManager: IdentityManager;
114
114
  /**
115
115
  * Extract agent ID from DID
116
- * @deprecated Use extractAgentId from @kya-os/mcp-i-core/utils/did-helpers instead
116
+ * @deprecated Use extractAgentId from @kya-os/mcp-i-runtime/utils/did-helpers instead
117
117
  * This re-export is maintained for backward compatibility
118
118
  */
119
- export { extractAgentId } from '@kya-os/mcp-i-core/utils/did-helpers';
119
+ export { extractAgentId } from '@kya-os/mcp-i-runtime/utils/did-helpers';
120
120
  /**
121
121
  * Extract agent slug from DID
122
- * @deprecated Use extractAgentSlug from @kya-os/mcp-i-core/utils/did-helpers instead
122
+ * @deprecated Use extractAgentSlug from @kya-os/mcp-i-runtime/utils/did-helpers instead
123
123
  * This re-export is maintained for backward compatibility
124
124
  */
125
- export { extractAgentSlug } from '@kya-os/mcp-i-core/utils/did-helpers';
125
+ export { extractAgentSlug } from '@kya-os/mcp-i-runtime/utils/did-helpers';
126
126
  /**
127
127
  * Convenience function to ensure identity
128
128
  */
@@ -293,17 +293,17 @@ exports.IdentityManager = IdentityManager;
293
293
  exports.defaultIdentityManager = new IdentityManager();
294
294
  /**
295
295
  * Extract agent ID from DID
296
- * @deprecated Use extractAgentId from @kya-os/mcp-i-core/utils/did-helpers instead
296
+ * @deprecated Use extractAgentId from @kya-os/mcp-i-runtime/utils/did-helpers instead
297
297
  * This re-export is maintained for backward compatibility
298
298
  */
299
- var did_helpers_1 = require("@kya-os/mcp-i-core/utils/did-helpers");
299
+ var did_helpers_1 = require("@kya-os/mcp-i-runtime/utils/did-helpers");
300
300
  Object.defineProperty(exports, "extractAgentId", { enumerable: true, get: function () { return did_helpers_1.extractAgentId; } });
301
301
  /**
302
302
  * Extract agent slug from DID
303
- * @deprecated Use extractAgentSlug from @kya-os/mcp-i-core/utils/did-helpers instead
303
+ * @deprecated Use extractAgentSlug from @kya-os/mcp-i-runtime/utils/did-helpers instead
304
304
  * This re-export is maintained for backward compatibility
305
305
  */
306
- var did_helpers_2 = require("@kya-os/mcp-i-core/utils/did-helpers");
306
+ var did_helpers_2 = require("@kya-os/mcp-i-runtime/utils/did-helpers");
307
307
  Object.defineProperty(exports, "extractAgentSlug", { enumerable: true, get: function () { return did_helpers_2.extractAgentSlug; } });
308
308
  /**
309
309
  * Convenience function to ensure identity
@@ -16,6 +16,9 @@ export { DebugManager, createDebugEndpoint, type DebugVerificationResult, type D
16
16
  export { DemoManager, createDemoManager, DemoConsole, formatVerifyLink, type DemoConfig, } from "./demo";
17
17
  export { type DelegationVerifier, type DelegationVerifierConfig, type VerifyDelegationResult, type VerifyDelegationOptions, createDelegationVerifier, checkScopes, validateDelegation, extractScopes, } from "./delegation-verifier";
18
18
  export { type AuthHandshakeConfig, type VerifyOrHintsResult, type AgentReputation, type ResumeTokenStore, verifyOrHints, hasSensitiveScopes, MemoryResumeTokenStore, } from "./auth-handshake";
19
+ export { createResumeTokenStore, type ResumeTokenStoreConfig, } from "./resume-token-store";
20
+ export { CloudflareKVResumeTokenStore, type ResumeTokenKVNamespace, } from "./resume-token-store-kv";
21
+ export { ensureOutboundIdentityBridge } from "./outbound-identity-bridge";
19
22
  export { type ProofDestination, type ProofBatchQueueConfig, ProofBatchQueue, KTAProofDestination, AgentShieldProofDestination, createProofBatchQueue, } from "./proof-batch-queue";
20
23
  export { CloudflareKVDelegationVerifier, } from "./delegation-verifier-kv";
21
24
  export { AgentShieldAPIDelegationVerifier, } from "./delegation-verifier-agentshield";
@@ -23,5 +26,6 @@ export { MemoryDelegationVerifier, } from "./delegation-verifier-memory";
23
26
  export { type ToolProtectionConfig, type ToolProtectionMap, type ToolProtectionConfigSource, ToolProtectionResolver, createToolProtectionResolver, InlineToolProtectionSource, FileToolProtectionSource, AgentShieldToolProtectionSource, } from "./tool-protection";
24
27
  export { toolProtectionRegistry, isToolProtected, getToolProtection, } from "./tool-protection-registry";
25
28
  export type { HandshakeRequest, SessionContext, NonceCache, NonceCacheEntry, NonceCacheConfig, } from "@kya-os/contracts/handshake";
26
- export type { ProofMeta, DetachedProof, CanonicalHashes, AuditRecord, } from "@kya-os/contracts/proof";
27
- export type { DelegationRecord, DelegationStatus, DelegationChain, DelegationConstraints, } from "@kya-os/contracts/delegation";
29
+ export type { ProofMeta, DetachedProof, CanonicalHashes, AuditRecord, } from "@kya-os/mcp/types" with { "resolution-mode": "import" };
30
+ export type { DelegationRecord, DelegationStatus, DelegationConstraints, } from "@kya-os/mcp/types" with { "resolution-mode": "import" };
31
+ export type { DelegationChain } from "@kya-os/contracts/delegation";
@@ -6,8 +6,8 @@
6
6
  * audit logging, and well-known endpoints.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.FileToolProtectionSource = exports.InlineToolProtectionSource = exports.createToolProtectionResolver = exports.ToolProtectionResolver = exports.MemoryDelegationVerifier = exports.AgentShieldAPIDelegationVerifier = exports.CloudflareKVDelegationVerifier = exports.createProofBatchQueue = exports.AgentShieldProofDestination = exports.KTAProofDestination = exports.ProofBatchQueue = exports.MemoryResumeTokenStore = exports.hasSensitiveScopes = exports.verifyOrHints = exports.extractScopes = exports.validateDelegation = exports.checkScopes = exports.createDelegationVerifier = exports.formatVerifyLink = exports.DemoConsole = exports.createDemoManager = exports.DemoManager = exports.createDebugEndpoint = exports.DebugManager = exports.extractDIDFromPath = exports.validateAgentDocument = exports.validateDIDDocument = exports.createWellKnownHandler = exports.WellKnownManager = exports.validateAuditRecord = exports.parseAuditLine = exports.logKeyRotationAudit = exports.defaultAuditLogger = exports.AuditLogger = exports.extractCanonicalData = exports.createProofResponse = exports.ProofGenerator = exports.validateHandshakeFormat = exports.createHandshakeRequest = exports.defaultSessionManager = exports.SessionManager = exports.IDENTITY_ERRORS = exports.ensureIdentity = exports.defaultIdentityManager = exports.IdentityManager = exports.RUNTIME_ERRORS = exports.RuntimeFactory = exports.createMCPIRuntime = exports.MCPIRuntime = exports.MCPINodeRuntimeWrapper = void 0;
10
- exports.getToolProtection = exports.isToolProtected = exports.toolProtectionRegistry = exports.AgentShieldToolProtectionSource = void 0;
9
+ exports.ToolProtectionResolver = exports.MemoryDelegationVerifier = exports.AgentShieldAPIDelegationVerifier = exports.CloudflareKVDelegationVerifier = exports.createProofBatchQueue = exports.AgentShieldProofDestination = exports.KTAProofDestination = exports.ProofBatchQueue = exports.ensureOutboundIdentityBridge = exports.CloudflareKVResumeTokenStore = exports.createResumeTokenStore = exports.MemoryResumeTokenStore = exports.hasSensitiveScopes = exports.verifyOrHints = exports.extractScopes = exports.validateDelegation = exports.checkScopes = exports.createDelegationVerifier = exports.formatVerifyLink = exports.DemoConsole = exports.createDemoManager = exports.DemoManager = exports.createDebugEndpoint = exports.DebugManager = exports.extractDIDFromPath = exports.validateAgentDocument = exports.validateDIDDocument = exports.createWellKnownHandler = exports.WellKnownManager = exports.validateAuditRecord = exports.parseAuditLine = exports.logKeyRotationAudit = exports.defaultAuditLogger = exports.AuditLogger = exports.extractCanonicalData = exports.createProofResponse = exports.ProofGenerator = exports.validateHandshakeFormat = exports.createHandshakeRequest = exports.defaultSessionManager = exports.SessionManager = exports.IDENTITY_ERRORS = exports.ensureIdentity = exports.defaultIdentityManager = exports.IdentityManager = exports.RUNTIME_ERRORS = exports.RuntimeFactory = exports.createMCPIRuntime = exports.MCPIRuntime = exports.MCPINodeRuntimeWrapper = void 0;
10
+ exports.getToolProtection = exports.isToolProtected = exports.toolProtectionRegistry = exports.AgentShieldToolProtectionSource = exports.FileToolProtectionSource = exports.InlineToolProtectionSource = exports.createToolProtectionResolver = void 0;
11
11
  // Main runtime - Node.js implementation with providers
12
12
  var mcpi_runtime_wrapper_1 = require("./mcpi-runtime-wrapper");
13
13
  Object.defineProperty(exports, "MCPINodeRuntimeWrapper", { enumerable: true, get: function () { return mcpi_runtime_wrapper_1.MCPINodeRuntimeWrapper; } });
@@ -69,6 +69,14 @@ var auth_handshake_1 = require("./auth-handshake");
69
69
  Object.defineProperty(exports, "verifyOrHints", { enumerable: true, get: function () { return auth_handshake_1.verifyOrHints; } });
70
70
  Object.defineProperty(exports, "hasSensitiveScopes", { enumerable: true, get: function () { return auth_handshake_1.hasSensitiveScopes; } });
71
71
  Object.defineProperty(exports, "MemoryResumeTokenStore", { enumerable: true, get: function () { return auth_handshake_1.MemoryResumeTokenStore; } });
72
+ // Durable resume-token store factory (pluggable persistence)
73
+ var resume_token_store_1 = require("./resume-token-store");
74
+ Object.defineProperty(exports, "createResumeTokenStore", { enumerable: true, get: function () { return resume_token_store_1.createResumeTokenStore; } });
75
+ var resume_token_store_kv_1 = require("./resume-token-store-kv");
76
+ Object.defineProperty(exports, "CloudflareKVResumeTokenStore", { enumerable: true, get: function () { return resume_token_store_kv_1.CloudflareKVResumeTokenStore; } });
77
+ // Outbound identity bridge (mcp-i → compute interceptor)
78
+ var outbound_identity_bridge_1 = require("./outbound-identity-bridge");
79
+ Object.defineProperty(exports, "ensureOutboundIdentityBridge", { enumerable: true, get: function () { return outbound_identity_bridge_1.ensureOutboundIdentityBridge; } });
72
80
  // Proof batching (NEW - Phase 1)
73
81
  var proof_batch_queue_1 = require("./proof-batch-queue");
74
82
  Object.defineProperty(exports, "ProofBatchQueue", { enumerable: true, get: function () { return proof_batch_queue_1.ProofBatchQueue; } });
@@ -4,7 +4,7 @@
4
4
  * Node.js-specific runtime that extends the core runtime with Node.js providers.
5
5
  * Provides backward compatibility by accepting legacy configuration format.
6
6
  */
7
- import { MCPIRuntimeBase, AccessControlApiService, ProofVerifier } from "@kya-os/mcp-i-core";
7
+ import { MCPIRuntimeBase, AccessControlApiService, ProofVerifier } from "@kya-os/mcp-i-runtime";
8
8
  import type { MCPIRuntimeConfig } from "./mcpi-runtime";
9
9
  /**
10
10
  * Node.js-specific runtime implementation
@@ -11,7 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.MCPIRuntimeWrapper = exports.MCPINodeRuntimeWrapper = void 0;
13
13
  exports.createMCPIRuntime = createMCPIRuntime;
14
- const mcp_i_core_1 = require("@kya-os/mcp-i-core");
14
+ const mcp_i_runtime_1 = require("@kya-os/mcp-i-runtime");
15
15
  const node_providers_1 = require("../providers/node-providers");
16
16
  const path_1 = __importDefault(require("path"));
17
17
  /**
@@ -56,7 +56,7 @@ function createProvidersFromConfig(config) {
56
56
  /**
57
57
  * Node.js-specific runtime implementation
58
58
  */
59
- class MCPINodeRuntimeWrapper extends mcp_i_core_1.MCPIRuntimeBase {
59
+ class MCPINodeRuntimeWrapper extends mcp_i_runtime_1.MCPIRuntimeBase {
60
60
  legacyConfig;
61
61
  // accessControlService is inherited from MCPIRuntimeBase (protected), no need to redeclare
62
62
  // proofVerifier is inherited from MCPIRuntimeBase (protected), no need to redeclare
@@ -66,7 +66,7 @@ class MCPINodeRuntimeWrapper extends mcp_i_core_1.MCPIRuntimeBase {
66
66
  this.legacyConfig = config;
67
67
  // Instantiate ProofVerifier
68
68
  // Access protected property from base class using type assertion
69
- this.proofVerifier = new mcp_i_core_1.ProofVerifier({
69
+ this.proofVerifier = new mcp_i_runtime_1.ProofVerifier({
70
70
  cryptoProvider: coreConfig.cryptoProvider,
71
71
  clockProvider: coreConfig.clockProvider,
72
72
  nonceCacheProvider: coreConfig.nonceCacheProvider,
@@ -77,7 +77,7 @@ class MCPINodeRuntimeWrapper extends mcp_i_core_1.MCPIRuntimeBase {
77
77
  const apiKey = process.env.AGENTSHIELD_API_KEY;
78
78
  const apiUrl = process.env.AGENTSHIELD_API_URL || "https://kya.vouched.id";
79
79
  if (apiKey) {
80
- this.accessControlService = new mcp_i_core_1.AccessControlApiService({
80
+ this.accessControlService = new mcp_i_runtime_1.AccessControlApiService({
81
81
  baseUrl: apiUrl,
82
82
  apiKey,
83
83
  fetchProvider: coreConfig.fetchProvider,
@@ -9,7 +9,8 @@ import { ToolRequest, ToolResponse } from "./proof";
9
9
  import { WellKnownConfig } from "./well-known";
10
10
  import { DemoManager } from "./demo";
11
11
  import { DelegationVerifierConfig } from "./delegation-verifier";
12
- import { NeedsAuthorizationError } from "@kya-os/contracts/runtime";
12
+ import { ResumeTokenStoreConfig } from "./resume-token-store";
13
+ import type { NeedsAuthorizationError } from "@kya-os/mcp/types" with { "resolution-mode": "import" };
13
14
  import { ToolProtectionMap, ToolProtectionResolver } from "./tool-protection";
14
15
  /**
15
16
  * Runtime environment check
@@ -89,6 +90,13 @@ export interface MCPIRuntimeConfig {
89
90
  minReputationScore?: number;
90
91
  /** Resume token TTL in milliseconds */
91
92
  resumeTokenTtl?: number;
93
+ /**
94
+ * Resume-token store selection. Omit for the in-memory single-process
95
+ * dev default (tokens lost on restart, not shared across instances).
96
+ * Set `{ type: 'cloudflare-kv', kvNamespace }` for durable consent→reuse
97
+ * on multi-instance / serverless deployments.
98
+ */
99
+ resumeTokenStore?: ResumeTokenStoreConfig;
92
100
  /** Require authorization for unknown agents */
93
101
  requireAuthForUnknown?: boolean;
94
102
  };
@@ -17,9 +17,12 @@ const debug_1 = require("./debug");
17
17
  const demo_1 = require("./demo");
18
18
  const delegation_verifier_1 = require("./delegation-verifier");
19
19
  const auth_handshake_1 = require("./auth-handshake");
20
+ const resume_token_store_1 = require("./resume-token-store");
20
21
  const request_context_1 = require("./request-context");
22
+ const outbound_identity_bridge_1 = require("./outbound-identity-bridge");
21
23
  const tool_protection_1 = require("./tool-protection");
22
24
  const tool_protection_registry_1 = require("./tool-protection-registry");
25
+ // C4 drain: delegation-layer symbol stays on @kya-os/mcp-i-core (src/delegation/** not relocated to mcp-i-runtime - pinned by E3.5 #2904).
23
26
  const mcp_i_core_1 = require("@kya-os/mcp-i-core");
24
27
  /**
25
28
  * XMCP-I Runtime class
@@ -51,9 +54,16 @@ class MCPIRuntime {
51
54
  this.sessionManager = new session_1.SessionManager(config.session);
52
55
  // Initialize audit logger
53
56
  this.auditLogger = new audit_1.AuditLogger(config.audit);
54
- // Initialize resume token store (NEW - Phase 1)
55
- // Use in-memory store by default (sufficient for most use cases)
56
- this.resumeTokenStore = new auth_handshake_1.MemoryResumeTokenStore(config.delegation?.authorization?.resumeTokenTtl || 600_000);
57
+ // Initialize resume token store (NEW - Phase 1).
58
+ // Durable stores (e.g. Cloudflare KV) are selected from config so a token
59
+ // minted at consent time survives cold starts / restarts / multi-instance
60
+ // — otherwise the user is re-prompted. Memory is the EXPLICIT single-process
61
+ // dev default. Mirrors the delegation-verifier factory pattern.
62
+ const resumeTtl = config.delegation?.authorization?.resumeTokenTtl || 600_000;
63
+ const resumeStoreConfig = config.delegation?.authorization?.resumeTokenStore;
64
+ this.resumeTokenStore = resumeStoreConfig
65
+ ? (0, resume_token_store_1.createResumeTokenStore)({ ttlMs: resumeTtl, ...resumeStoreConfig })
66
+ : new auth_handshake_1.MemoryResumeTokenStore(resumeTtl);
57
67
  // Initialize delegation verifier (NEW - Phase 1)
58
68
  if (config.delegation?.enabled && config.delegation?.verifier) {
59
69
  this.delegationVerifier = (0, delegation_verifier_1.createDelegationVerifier)(config.delegation.verifier);
@@ -99,6 +109,10 @@ class MCPIRuntime {
99
109
  identityBadge: this.config.demo?.identityBadge || false,
100
110
  environment: this.config.identity?.environment || "development",
101
111
  });
112
+ // Bridge AsyncLocalStorage delegation/session context into the compute
113
+ // outbound-identity interceptor when it is preloaded in this process.
114
+ // Best-effort + idempotent — a no-op when compute is not present.
115
+ (0, outbound_identity_bridge_1.ensureOutboundIdentityBridge)();
102
116
  console.error(`✅ XMCP-I Runtime initialized`);
103
117
  console.error(` DID: ${this.cachedIdentity.did}`);
104
118
  console.error(` Key ID: ${this.cachedIdentity.kid}`);
@@ -207,6 +221,10 @@ class MCPIRuntime {
207
221
  delegationId: options.delegationRef,
208
222
  delegationChain: options.delegationChain,
209
223
  delegationScopes: options.delegationScopes,
224
+ // JWS-compact DelegationCredential VC from the verified result —
225
+ // emitted on KYA-OS-Delegation-Credential when the verifier
226
+ // returned a presentable credential.
227
+ delegationCredential: verifyResult.credential?.credential_jwt,
210
228
  identity,
211
229
  });
212
230
  }
@@ -5,15 +5,17 @@
5
5
  * HTTP requests made during delegated tool handler execution.
6
6
  *
7
7
  * Reads delegation context from AsyncLocalStorage (via getContext()),
8
- * builds a signed Ed25519 JWT, and injects:
9
- * KYA-Delegation-Id, KYA-Delegation-Chain, KYA-Delegation-Proof, KYA-Granted-Scopes
8
+ * builds a signed Ed25519 JWT, and injects the canonical KYA-OS-* Layer 2
9
+ * delegation headers:
10
+ * KYA-OS-Delegation-Chain, KYA-OS-Delegation-Proof, KYA-OS-Granted-Scopes,
11
+ * and KYA-OS-Delegation-Credential when a DelegationCredential VC is present.
10
12
  *
11
13
  * Behavior:
12
14
  * - Skips injection for internal hostnames (localhost, *.vouched.id, Fly IPs)
13
15
  * - On signing failure: logs warning, continues WITHOUT delegation headers
14
16
  * - Anonymous/non-delegated calls: no headers injected
15
17
  *
16
- * Related Spec: MCP-I §2 — Outbound Delegation Propagation
18
+ * Related Spec: DIF MCP-I §8 — Outbound Delegation Propagation
17
19
  */
18
20
  interface Logger {
19
21
  debug: (msg: string, meta?: Record<string, unknown>) => void;
@@ -6,20 +6,24 @@
6
6
  * HTTP requests made during delegated tool handler execution.
7
7
  *
8
8
  * Reads delegation context from AsyncLocalStorage (via getContext()),
9
- * builds a signed Ed25519 JWT, and injects:
10
- * KYA-Delegation-Id, KYA-Delegation-Chain, KYA-Delegation-Proof, KYA-Granted-Scopes
9
+ * builds a signed Ed25519 JWT, and injects the canonical KYA-OS-* Layer 2
10
+ * delegation headers:
11
+ * KYA-OS-Delegation-Chain, KYA-OS-Delegation-Proof, KYA-OS-Granted-Scopes,
12
+ * and KYA-OS-Delegation-Credential when a DelegationCredential VC is present.
11
13
  *
12
14
  * Behavior:
13
15
  * - Skips injection for internal hostnames (localhost, *.vouched.id, Fly IPs)
14
16
  * - On signing failure: logs warning, continues WITHOUT delegation headers
15
17
  * - Anonymous/non-delegated calls: no headers injected
16
18
  *
17
- * Related Spec: MCP-I §2 — Outbound Delegation Propagation
19
+ * Related Spec: DIF MCP-I §8 — Outbound Delegation Propagation
18
20
  */
19
21
  Object.defineProperty(exports, "__esModule", { value: true });
20
22
  exports.isInternalDelegationTarget = isInternalDelegationTarget;
21
23
  exports.installDelegationInterceptor = installDelegationInterceptor;
24
+ // C4 drain: delegation-layer symbol stays on @kya-os/mcp-i-core (src/delegation/** not relocated to mcp-i-runtime - pinned by E3.5 #2904).
22
25
  const mcp_i_core_1 = require("@kya-os/mcp-i-core");
26
+ // C2/C3: @kya-os/mcp-i is CJS; @kya-os/mcp is ESM-only (TS1479 blocks static import).
23
27
  const request_context_js_1 = require("./request-context.js");
24
28
  // Flag to avoid double-installing
25
29
  const DELEGATION_INTERCEPTED_FLAG = "__kyaDelegationIntercepted";
@@ -85,7 +89,7 @@ function installDelegationInterceptor(logger) {
85
89
  const baseHeaders = input instanceof Request ? input.headers : undefined;
86
90
  const headers = new Headers(init?.headers ?? baseHeaders);
87
91
  // Only inject if we have a delegation context and haven't already injected
88
- if (!headers.has("KYA-Delegation-Proof")) {
92
+ if (!headers.has("KYA-OS-Delegation-Proof")) {
89
93
  const ctx = (0, request_context_js_1.getContext)();
90
94
  if (ctx?.delegationRef &&
91
95
  ctx.delegationPrivateKeyJwk &&
@@ -108,10 +112,13 @@ function installDelegationInterceptor(logger) {
108
112
  kid: ctx.delegationAgentKid,
109
113
  targetHostname,
110
114
  });
111
- headers.set("KYA-Delegation-Id", ctx.delegationRef);
112
- headers.set("KYA-Delegation-Chain", ctx.delegationChain ?? ctx.delegationRef);
113
- headers.set("KYA-Delegation-Proof", proof);
114
- headers.set("KYA-Granted-Scopes", (ctx.delegationScopes ?? []).join(","));
115
+ headers.set("KYA-OS-Delegation-Chain", ctx.delegationChain ?? ctx.delegationRef);
116
+ headers.set("KYA-OS-Delegation-Proof", proof);
117
+ headers.set("KYA-OS-Granted-Scopes", (ctx.delegationScopes ?? []).join(","));
118
+ // Emit the JWS-compact DelegationCredential VC when the context carries one.
119
+ if (ctx.delegationCredential) {
120
+ headers.set("KYA-OS-Delegation-Credential", ctx.delegationCredential);
121
+ }
115
122
  logger?.debug("Delegation headers injected", {
116
123
  delegationRef: ctx.delegationRef,
117
124
  targetHostname,
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Outbound Identity Bridge (mcp-i → @kya-os/compute interceptor)
3
+ *
4
+ * Bridges this package's AsyncLocalStorage request context into the compute
5
+ * outbound-identity interceptor so the Layer-2 delegation headers and the
6
+ * `KYA-OS-Session-Id` anchor are emitted on the compute (OpenClaw sidecar)
7
+ * path — resolving the long-standing `interceptor.ts:183-188` TODO.
8
+ *
9
+ * Why a global rendezvous (not a direct import): neither package depends on
10
+ * the other (compute must not import the SDK; the SDK must not pull in the
11
+ * Fly.io sidecar). When the compute interceptor installs it publishes a
12
+ * registrar on `Symbol.for("kya-os.outbound-identity.registry")`; this module
13
+ * reads that registrar and registers providers backed by `getContext()`. When
14
+ * compute is absent (pure-Node / Cloudflare deployments) the registrar is
15
+ * missing and this is a clean no-op — those paths inject delegation headers via
16
+ * their own fetch wrap (`outbound-delegation.ts`).
17
+ *
18
+ * Authority model follows ADR-001: the DelegationCredential VC is
19
+ * authoritative; `-Chain` / `-Granted-Scopes` are advisory hints.
20
+ *
21
+ * Related Spec: DIF MCP-I §8 — Outbound Delegation Propagation
22
+ */
23
+ interface Logger {
24
+ debug: (msg: string, meta?: Record<string, unknown>) => void;
25
+ warn: (msg: string, meta?: Record<string, unknown>) => void;
26
+ }
27
+ /**
28
+ * Register the AsyncLocalStorage-backed delegation / session providers with the
29
+ * compute outbound-identity interceptor, if it is installed in this process.
30
+ *
31
+ * Idempotent and best-effort: safe to call from multiple init sites. Returns
32
+ * true when the registrar was found and providers were wired, false otherwise.
33
+ */
34
+ export declare function ensureOutboundIdentityBridge(logger?: Logger): boolean;
35
+ /**
36
+ * Test-only reset of the idempotency guard. Not part of the public runtime API.
37
+ * @internal
38
+ */
39
+ export declare function __resetOutboundIdentityBridgeForTests(): void;
40
+ export {};
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ /**
3
+ * Outbound Identity Bridge (mcp-i → @kya-os/compute interceptor)
4
+ *
5
+ * Bridges this package's AsyncLocalStorage request context into the compute
6
+ * outbound-identity interceptor so the Layer-2 delegation headers and the
7
+ * `KYA-OS-Session-Id` anchor are emitted on the compute (OpenClaw sidecar)
8
+ * path — resolving the long-standing `interceptor.ts:183-188` TODO.
9
+ *
10
+ * Why a global rendezvous (not a direct import): neither package depends on
11
+ * the other (compute must not import the SDK; the SDK must not pull in the
12
+ * Fly.io sidecar). When the compute interceptor installs it publishes a
13
+ * registrar on `Symbol.for("kya-os.outbound-identity.registry")`; this module
14
+ * reads that registrar and registers providers backed by `getContext()`. When
15
+ * compute is absent (pure-Node / Cloudflare deployments) the registrar is
16
+ * missing and this is a clean no-op — those paths inject delegation headers via
17
+ * their own fetch wrap (`outbound-delegation.ts`).
18
+ *
19
+ * Authority model follows ADR-001: the DelegationCredential VC is
20
+ * authoritative; `-Chain` / `-Granted-Scopes` are advisory hints.
21
+ *
22
+ * Related Spec: DIF MCP-I §8 — Outbound Delegation Propagation
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.ensureOutboundIdentityBridge = ensureOutboundIdentityBridge;
26
+ exports.__resetOutboundIdentityBridgeForTests = __resetOutboundIdentityBridgeForTests;
27
+ const mcp_i_core_1 = require("@kya-os/mcp-i-core");
28
+ const request_context_1 = require("./request-context");
29
+ /**
30
+ * Must match `OUTBOUND_IDENTITY_REGISTRY_KEY` in
31
+ * `@kya-os/compute`'s `outbound-identity/interceptor.ts`. `Symbol.for` resolves
32
+ * the same registry symbol in both packages within one process.
33
+ */
34
+ const OUTBOUND_IDENTITY_REGISTRY_KEY = Symbol.for("kya-os.outbound-identity.registry");
35
+ // Idempotency guard — the registered providers are closures over getContext(),
36
+ // so a single registration covers all subsequent requests in this process.
37
+ let bridged = false;
38
+ function readRegistry() {
39
+ // REASON: globalThis has no index signature for our Symbol key; one localized
40
+ // cast reads the typed cross-package slot compute published at install.
41
+ return globalThis[OUTBOUND_IDENTITY_REGISTRY_KEY];
42
+ }
43
+ /**
44
+ * Build a compute-compatible delegation provider from the request context.
45
+ * Returns undefined per-call when the active context carries no delegation (or
46
+ * lacks the signing material), so anonymous / non-delegated calls inject no
47
+ * delegation headers.
48
+ */
49
+ function delegationProvider() {
50
+ const ctx = (0, request_context_1.getContext)();
51
+ if (!ctx?.delegationRef ||
52
+ !ctx.delegationPrivateKeyJwk ||
53
+ !ctx.delegationAgentKid) {
54
+ return undefined;
55
+ }
56
+ const delegationChain = ctx.delegationChain ?? ctx.delegationRef;
57
+ const delegationScopes = ctx.delegationScopes ?? [];
58
+ const agentDid = ctx.session?.serverDid ?? "";
59
+ const userDid = ctx.session?.userDid ?? "";
60
+ // Surface the calling client's DID (xmcp-i#413) so the compute interceptor
61
+ // can attach it to KTA attestations. Spread conditionally below so the field
62
+ // is absent (not `undefined`) when the session carries no client identity.
63
+ const clientDid = ctx.session?.clientDid;
64
+ const privateKeyJwk = ctx.delegationPrivateKeyJwk;
65
+ const kid = ctx.delegationAgentKid;
66
+ const delegationRef = ctx.delegationRef;
67
+ return {
68
+ delegationRef,
69
+ delegationChain,
70
+ delegationScopes,
71
+ agentDid,
72
+ userDid,
73
+ ...(clientDid ? { clientDid } : {}),
74
+ kid,
75
+ delegationCredential: ctx.delegationCredential,
76
+ buildProof: (targetHostname) => (0, mcp_i_core_1.buildDelegationProofJWT)({
77
+ agentDid,
78
+ userDid,
79
+ delegationId: delegationRef,
80
+ delegationChain,
81
+ scopes: delegationScopes,
82
+ privateKeyJwk,
83
+ kid,
84
+ targetHostname,
85
+ }),
86
+ };
87
+ }
88
+ /** Resolve the stable MCP session id from the active request context. */
89
+ function sessionIdProvider() {
90
+ return (0, request_context_1.getContext)()?.session?.sessionId;
91
+ }
92
+ /**
93
+ * Register the AsyncLocalStorage-backed delegation / session providers with the
94
+ * compute outbound-identity interceptor, if it is installed in this process.
95
+ *
96
+ * Idempotent and best-effort: safe to call from multiple init sites. Returns
97
+ * true when the registrar was found and providers were wired, false otherwise.
98
+ */
99
+ function ensureOutboundIdentityBridge(logger) {
100
+ if (bridged)
101
+ return true;
102
+ const registry = readRegistry();
103
+ if (!registry?.setDelegationProvider) {
104
+ logger?.debug("Outbound identity bridge: compute interceptor not present — skipping");
105
+ return false;
106
+ }
107
+ registry.setDelegationProvider(delegationProvider);
108
+ registry.setSessionIdProvider?.(sessionIdProvider);
109
+ bridged = true;
110
+ logger?.debug("Outbound identity bridge: delegation + session providers registered");
111
+ return true;
112
+ }
113
+ /**
114
+ * Test-only reset of the idempotency guard. Not part of the public runtime API.
115
+ * @internal
116
+ */
117
+ function __resetOutboundIdentityBridgeForTests() {
118
+ bridged = false;
119
+ }
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * Related: PHASE_1_XMCP_I_SERVER.md Epic 3 (Proof Batching)
18
18
  */
19
- import { DetachedProof } from "@kya-os/contracts/proof";
19
+ import type { DetachedProof } from "@kya-os/mcp/types" with { "resolution-mode": "import" };
20
20
  /**
21
21
  * Proof submission destination
22
22
  */
@@ -7,8 +7,8 @@
7
7
  *
8
8
  * Requirements: 5.1, 5.2, 5.3, 5.6
9
9
  */
10
- import { ProofGenerator as CoreProofGenerator, type ProofAgentIdentity, type ToolRequest, type ToolResponse, type ProofOptions, extractCanonicalData } from "@kya-os/mcp-i-core";
11
- import { CryptoProvider } from "@kya-os/mcp-i-core";
10
+ import { ProofGenerator as CoreProofGenerator, type ProofAgentIdentity, type ToolRequest, type ToolResponse, type ProofOptions, extractCanonicalData } from "@kya-os/mcp-i-runtime";
11
+ import { CryptoProvider } from "@kya-os/mcp-i-runtime";
12
12
  import { SessionContext } from "@kya-os/contracts/handshake";
13
13
  export declare class ProofGenerator extends CoreProofGenerator {
14
14
  constructor(identity: ProofAgentIdentity, cryptoProvider?: CryptoProvider);
@@ -11,10 +11,10 @@
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.extractCanonicalData = exports.ProofGenerator = void 0;
13
13
  exports.createProofResponse = createProofResponse;
14
- const mcp_i_core_1 = require("@kya-os/mcp-i-core");
15
- Object.defineProperty(exports, "extractCanonicalData", { enumerable: true, get: function () { return mcp_i_core_1.extractCanonicalData; } });
14
+ const mcp_i_runtime_1 = require("@kya-os/mcp-i-runtime");
15
+ Object.defineProperty(exports, "extractCanonicalData", { enumerable: true, get: function () { return mcp_i_runtime_1.extractCanonicalData; } });
16
16
  const node_providers_1 = require("../providers/node-providers");
17
- class ProofGenerator extends mcp_i_core_1.ProofGenerator {
17
+ class ProofGenerator extends mcp_i_runtime_1.ProofGenerator {
18
18
  constructor(identity, cryptoProvider = new node_providers_1.NodeCryptoProvider()) {
19
19
  super(identity, cryptoProvider);
20
20
  }
@@ -19,6 +19,8 @@ export interface RequestContext {
19
19
  delegationChain?: string;
20
20
  /** Scopes granted by the active delegation */
21
21
  delegationScopes?: string[];
22
+ /** JWS-compact DelegationCredential VC for the active delegation (emitted on KYA-OS-Delegation-Credential when present) */
23
+ delegationCredential?: string;
22
24
  /** Agent Ed25519 private key JWK for delegation proof signing */
23
25
  delegationPrivateKeyJwk?: Ed25519PrivateJWK;
24
26
  /** Key ID used in delegation proof JWT header */
@@ -56,6 +58,7 @@ export declare function setDelegationContext(fields: {
56
58
  delegationRef: string;
57
59
  delegationChain: string;
58
60
  delegationScopes: string[];
61
+ delegationCredential?: string;
59
62
  delegationPrivateKeyJwk?: Ed25519PrivateJWK;
60
63
  delegationAgentKid?: string;
61
64
  }): void;
@@ -70,6 +73,13 @@ export declare function setDelegationContextFromIdentity(params: {
70
73
  delegationId: string;
71
74
  delegationChain: string;
72
75
  delegationScopes: string[];
76
+ /**
77
+ * JWS-compact DelegationCredential VC for the active delegation. Threaded
78
+ * through to KYA-OS-Delegation-Credential on outbound requests. Sourced
79
+ * from the verified delegation result (e.g. credential.credential_jwt).
80
+ * Omit when the verifier did not return a presentable VC.
81
+ */
82
+ delegationCredential?: string;
73
83
  identity: {
74
84
  privateKey: string;
75
85
  publicKey: string;
@@ -71,6 +71,9 @@ function setDelegationContext(fields) {
71
71
  context.delegationRef = fields.delegationRef;
72
72
  context.delegationChain = fields.delegationChain;
73
73
  context.delegationScopes = fields.delegationScopes;
74
+ if (fields.delegationCredential !== undefined) {
75
+ context.delegationCredential = fields.delegationCredential;
76
+ }
74
77
  if (fields.delegationPrivateKeyJwk !== undefined) {
75
78
  context.delegationPrivateKeyJwk = fields.delegationPrivateKeyJwk;
76
79
  }
@@ -90,6 +93,7 @@ function setDelegationContextFromIdentity(params) {
90
93
  delegationRef: params.delegationId,
91
94
  delegationChain: params.delegationChain,
92
95
  delegationScopes: params.delegationScopes,
96
+ delegationCredential: params.delegationCredential,
93
97
  delegationPrivateKeyJwk: params.identity?.privateKey
94
98
  ? {
95
99
  kty: "OKP",
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Cloudflare KV Resume Token Store
3
+ *
4
+ * Durable resume-token store backed by a Cloudflare Workers KV namespace, so a
5
+ * resume token minted at consent time survives cold starts, process restarts,
6
+ * and multi-instance deployments (the failure mode the in-memory store causes —
7
+ * the user gets re-prompted because the token vanished). Mirrors the
8
+ * delegation-verifier-kv.ts adapter shape.
9
+ *
10
+ * Key structure:
11
+ * - `resume:{token}` — JSON-encoded {@link StoredResumeToken}
12
+ *
13
+ * Tokens are minted with CSPRNG entropy (see generateResumeToken in
14
+ * @kya-os/mcp-i-core), never time+Math.random.
15
+ */
16
+ import { type ResumeTokenStore } from "@kya-os/mcp-i-core";
17
+ /**
18
+ * Minimal Cloudflare KV surface needed by the store. `put` accepts the standard
19
+ * KV `{ expirationTtl }` (seconds) so the namespace also evicts expired tokens
20
+ * natively; logical expiry via `expiresAt` is enforced regardless.
21
+ */
22
+ export interface ResumeTokenKVNamespace {
23
+ get(key: string): Promise<string | null>;
24
+ put(key: string, value: string, options?: {
25
+ expirationTtl?: number;
26
+ }): Promise<void>;
27
+ delete(key: string): Promise<void>;
28
+ }
29
+ export declare class CloudflareKVResumeTokenStore implements ResumeTokenStore {
30
+ private kv;
31
+ private ttlMs;
32
+ constructor(kv: ResumeTokenKVNamespace, ttlMs?: number);
33
+ private key;
34
+ private read;
35
+ create(agentDid: string, scopes: string[], metadata?: Record<string, unknown>): Promise<string>;
36
+ get(token: string): Promise<{
37
+ agentDid: string;
38
+ scopes: string[];
39
+ createdAt: number;
40
+ expiresAt: number;
41
+ metadata?: Record<string, unknown>;
42
+ } | null>;
43
+ fulfill(token: string): Promise<void>;
44
+ }