@kya-os/mcp-i-core 1.3.24 → 1.3.25

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.
@@ -13,7 +13,7 @@
13
13
  * 2. Session storage lookup
14
14
  * 3. Return null (session stays anonymous)
15
15
  */
16
- import { CryptoProvider } from '../providers/base';
16
+ import { CryptoProvider } from "../providers/base";
17
17
  /**
18
18
  * OAuth identity for persistent user DID lookup
19
19
  */
@@ -56,7 +56,7 @@ class UserDidManager {
56
56
  }
57
57
  }
58
58
  catch (error) {
59
- console.warn('[UserDidManager] OAuth key pair lookup failed:', error);
59
+ console.warn("[UserDidManager] OAuth key pair lookup failed:", error);
60
60
  }
61
61
  }
62
62
  // Check session storage if available
@@ -69,7 +69,7 @@ class UserDidManager {
69
69
  }
70
70
  }
71
71
  catch (error) {
72
- console.warn('[UserDidManager] Session key pair lookup failed:', error);
72
+ console.warn("[UserDidManager] Session key pair lookup failed:", error);
73
73
  }
74
74
  }
75
75
  return null;
@@ -96,13 +96,16 @@ class UserDidManager {
96
96
  return this.sessionDidCache.get(sessionId);
97
97
  }
98
98
  // PRIORITY 1: If OAuth identity provided, check for persistent user DID mapping
99
- if (oauthIdentity && oauthIdentity.provider && oauthIdentity.subject && this.config.storage?.getByOAuth) {
99
+ if (oauthIdentity &&
100
+ oauthIdentity.provider &&
101
+ oauthIdentity.subject &&
102
+ this.config.storage?.getByOAuth) {
100
103
  try {
101
104
  const persistentUserDid = await this.config.storage.getByOAuth(oauthIdentity.provider, oauthIdentity.subject);
102
105
  if (persistentUserDid) {
103
- console.log('[UserDidManager] Found persistent user DID from OAuth mapping:', {
106
+ console.error("[UserDidManager] Found persistent user DID from OAuth mapping:", {
104
107
  provider: oauthIdentity.provider,
105
- userDid: persistentUserDid.substring(0, 20) + '...',
108
+ userDid: persistentUserDid.substring(0, 20) + "...",
106
109
  });
107
110
  // Cache it for this session
108
111
  this.sessionDidCache.set(sessionId, persistentUserDid);
@@ -113,7 +116,7 @@ class UserDidManager {
113
116
  }
114
117
  catch (error) {
115
118
  // Log but continue - DID is cached and will be returned
116
- console.warn('[UserDidManager] Failed to cache persistent DID in session storage:', error);
119
+ console.warn("[UserDidManager] Failed to cache persistent DID in session storage:", error);
117
120
  }
118
121
  }
119
122
  return persistentUserDid;
@@ -121,7 +124,7 @@ class UserDidManager {
121
124
  }
122
125
  catch (error) {
123
126
  // Log but continue - will check session storage or generate new DID
124
- console.warn('[UserDidManager] OAuth lookup failed, falling back to session storage:', error);
127
+ console.warn("[UserDidManager] OAuth lookup failed, falling back to session storage:", error);
125
128
  }
126
129
  }
127
130
  // PRIORITY 2: Check session storage if available
@@ -131,18 +134,21 @@ class UserDidManager {
131
134
  if (storedDid) {
132
135
  this.sessionDidCache.set(sessionId, storedDid);
133
136
  // If OAuth identity provided but no persistent mapping found, create one now
134
- if (oauthIdentity && oauthIdentity.provider && oauthIdentity.subject && this.config.storage.setByOAuth) {
137
+ if (oauthIdentity &&
138
+ oauthIdentity.provider &&
139
+ oauthIdentity.subject &&
140
+ this.config.storage.setByOAuth) {
135
141
  try {
136
142
  await this.config.storage.setByOAuth(oauthIdentity.provider, oauthIdentity.subject, storedDid, 90 * 24 * 60 * 60 // 90 days TTL for persistent mapping
137
143
  );
138
- console.log('[UserDidManager] Created persistent OAuth mapping for existing user DID:', {
144
+ console.error("[UserDidManager] Created persistent OAuth mapping for existing user DID:", {
139
145
  provider: oauthIdentity.provider,
140
- userDid: storedDid.substring(0, 20) + '...',
146
+ userDid: storedDid.substring(0, 20) + "...",
141
147
  });
142
148
  }
143
149
  catch (error) {
144
150
  // Log but continue - mapping creation failed, but DID is still valid
145
- console.warn('[UserDidManager] Failed to create OAuth mapping:', error);
151
+ console.warn("[UserDidManager] Failed to create OAuth mapping:", error);
146
152
  }
147
153
  }
148
154
  return storedDid;
@@ -150,7 +156,7 @@ class UserDidManager {
150
156
  }
151
157
  catch (error) {
152
158
  // Log but continue - session will be anonymous
153
- console.warn('[UserDidManager] Storage.get failed:', error);
159
+ console.warn("[UserDidManager] Storage.get failed:", error);
154
160
  }
155
161
  }
156
162
  // PHASE 5: No ephemeral DID generation - session stays anonymous
@@ -176,21 +182,23 @@ class UserDidManager {
176
182
  await this.config.storage.set(sessionId, userDid, 1800); // 30 minutes TTL
177
183
  }
178
184
  catch (error) {
179
- console.warn('[UserDidManager] Failed to store user DID in session storage:', error);
185
+ console.warn("[UserDidManager] Failed to store user DID in session storage:", error);
180
186
  }
181
187
  }
182
188
  // Create OAuth mapping if provided
183
- if (oauthIdentity?.provider && oauthIdentity?.subject && this.config.storage?.setByOAuth) {
189
+ if (oauthIdentity?.provider &&
190
+ oauthIdentity?.subject &&
191
+ this.config.storage?.setByOAuth) {
184
192
  try {
185
193
  await this.config.storage.setByOAuth(oauthIdentity.provider, oauthIdentity.subject, userDid, 90 * 24 * 60 * 60 // 90 days TTL for persistent mapping
186
194
  );
187
- console.log('[UserDidManager] Created OAuth → DID mapping:', {
195
+ console.error("[UserDidManager] Created OAuth → DID mapping:", {
188
196
  provider: oauthIdentity.provider,
189
- userDid: userDid.substring(0, 20) + '...',
197
+ userDid: userDid.substring(0, 20) + "...",
190
198
  });
191
199
  }
192
200
  catch (error) {
193
- console.warn('[UserDidManager] Failed to create OAuth mapping:', error);
201
+ console.warn("[UserDidManager] Failed to create OAuth mapping:", error);
194
202
  }
195
203
  }
196
204
  }
@@ -217,7 +225,7 @@ class UserDidManager {
217
225
  // Generate did:web (requires web server setup)
218
226
  // For now, fall back to did:key
219
227
  // TODO: Implement did:web generation if needed
220
- console.warn('[UserDidManager] did:web not yet implemented, using did:key');
228
+ console.warn("[UserDidManager] did:web not yet implemented, using did:key");
221
229
  }
222
230
  // Generate Ed25519 keypair for user DID
223
231
  const keyPair = await this.config.crypto.generateKeyPair();
@@ -258,21 +266,21 @@ class UserDidManager {
258
266
  * Simple implementation for did:key generation
259
267
  */
260
268
  base58Encode(bytes) {
261
- const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
269
+ const alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
262
270
  let num = BigInt(0);
263
271
  // Convert bytes to big integer
264
272
  for (let i = 0; i < bytes.length; i++) {
265
273
  num = num * BigInt(256) + BigInt(bytes[i]);
266
274
  }
267
275
  // Convert to base58
268
- let result = '';
276
+ let result = "";
269
277
  while (num > 0) {
270
278
  result = alphabet[Number(num % BigInt(58))] + result;
271
279
  num = num / BigInt(58);
272
280
  }
273
281
  // Add leading zeros
274
282
  for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {
275
- result = '1' + result;
283
+ result = "1" + result;
276
284
  }
277
285
  return result;
278
286
  }
@@ -280,9 +288,9 @@ class UserDidManager {
280
288
  * Convert base64 string to Uint8Array
281
289
  */
282
290
  base64ToBytes(base64) {
283
- if (typeof Buffer !== 'undefined') {
291
+ if (typeof Buffer !== "undefined") {
284
292
  // Node.js environment
285
- return new Uint8Array(Buffer.from(base64, 'base64'));
293
+ return new Uint8Array(Buffer.from(base64, "base64"));
286
294
  }
287
295
  else {
288
296
  // Browser/Workers environment
@@ -323,7 +331,7 @@ class UserDidManager {
323
331
  }
324
332
  catch (error) {
325
333
  // Log but continue - cache is already cleared
326
- console.warn('[UserDidManager] Storage.delete failed, continuing:', error);
334
+ console.warn("[UserDidManager] Storage.delete failed, continuing:", error);
327
335
  }
328
336
  }
329
337
  }
package/dist/index.d.ts CHANGED
@@ -26,8 +26,8 @@ export type { OAuthServiceConfig } from "./services/oauth-service";
26
26
  export { ToolContextBuilder } from "./services/tool-context-builder";
27
27
  export type { ToolContextBuilderConfig } from "./services/tool-context-builder";
28
28
  export { OAuthProviderRegistry } from "./services/oauth-provider-registry";
29
- export { ProviderResolver } from "./services/provider-resolver";
30
- export { ProviderValidator, ProviderValidationError } from "./services/provider-validator";
29
+ export { ProviderResolver, ConsentOnlyModeError, } from "./services/provider-resolver";
30
+ export { ProviderValidator, ProviderValidationError, } from "./services/provider-validator";
31
31
  export { OAuthTokenRetrievalService } from "./services/oauth-token-retrieval.service";
32
32
  export type { OAuthTokenRetrievalServiceConfig } from "./services/oauth-token-retrieval.service";
33
33
  export { BatchDelegationService } from "./services/batch-delegation.service";
@@ -52,7 +52,7 @@ export { CascadingRevocationManager, createCascadingRevocationManager, type Revo
52
52
  export { MemoryStatusListStorage } from "./delegation/storage/memory-statuslist-storage";
53
53
  export { MemoryDelegationGraphStorage } from "./delegation/storage/memory-graph-storage";
54
54
  export { createDidKeyResolver, isEd25519DidKey, extractPublicKeyFromDidKey, publicKeyToJwk, resolveDidKeySync, } from "./delegation/did-key-resolver";
55
- export { base58Encode, base58Decode, isValidBase58, } from "./utils/base58";
55
+ export { base58Encode, base58Decode, isValidBase58 } from "./utils/base58";
56
56
  export { SchemaVerifier, createSchemaVerifier, type SchemaMetadata, type FieldComplianceResult, type SchemaComplianceReport, type FullComplianceReport, } from "./compliance/schema-verifier";
57
57
  export { SCHEMA_REGISTRY, getAllSchemas, getSchemasByCategory, getSchemaById, getCriticalSchemas, getSchemaStats, } from "./compliance/schema-registry";
58
58
  export { canonicalizeJSON, createUnsignedVCJWT, completeVCJWT, parseVCJWT, type VCJWTHeader, type VCJWTPayload, type EncodeVCAsJWTOptions, } from "./delegation/utils";
package/dist/index.js CHANGED
@@ -20,8 +20,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
20
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.createCascadingRevocationManager = exports.CascadingRevocationManager = exports.createDelegationGraph = exports.DelegationGraphManager = exports.isIndexSet = exports.BitstringManager = exports.createStatusListManager = exports.StatusList2021Manager = exports.createDelegationVerifier = exports.DelegationCredentialVerifier = exports.createDelegationIssuer = exports.DelegationCredentialIssuer = exports.OAuthRequiredError = exports.DelegationRequiredError = exports.NoOpToolProtectionCache = exports.InMemoryToolProtectionCache = exports.createProofVerificationError = exports.PROOF_VERIFICATION_ERROR_CODES = exports.ProofVerificationError = exports.migrateLegacyKeys = exports.StorageKeyHelpers = exports.createStorageProviders = exports.NoOpOAuthConfigCache = exports.InMemoryOAuthConfigCache = exports.BatchDelegationService = exports.OAuthTokenRetrievalService = exports.ProviderValidationError = exports.ProviderValidator = exports.ProviderResolver = exports.OAuthProviderRegistry = exports.ToolContextBuilder = exports.OAuthService = exports.OAuthConfigService = exports.createSessionRegistrationService = exports.SessionRegistrationService = exports.authorizationMatches = exports.AccessControlApiService = exports.ProofVerifier = exports.CryptoService = exports.ToolProtectionService = exports.MCPIRuntimeBase = exports.MemoryIdentityProvider = exports.MemoryNonceCacheProvider = exports.MemoryStorageProvider = exports.IdentityProvider = exports.NonceCacheProvider = exports.StorageProvider = exports.FetchProvider = exports.ClockProvider = exports.CryptoProvider = void 0;
24
- exports.IdpTokenResolver = exports.UserDidManager = exports.fetchRemoteConfig = exports.bytesToBase64 = exports.base64urlDecodeToString = exports.base64urlDecodeToBytes = exports.base64urlEncodeFromString = exports.base64urlEncodeFromBytes = exports.parseVCJWT = exports.completeVCJWT = exports.createUnsignedVCJWT = exports.canonicalizeJSON = exports.getSchemaStats = exports.getCriticalSchemas = exports.getSchemaById = exports.getSchemasByCategory = exports.getAllSchemas = exports.SCHEMA_REGISTRY = exports.createSchemaVerifier = exports.SchemaVerifier = exports.isValidBase58 = exports.base58Decode = exports.base58Encode = exports.resolveDidKeySync = exports.publicKeyToJwk = exports.extractPublicKeyFromDidKey = exports.isEd25519DidKey = exports.createDidKeyResolver = exports.MemoryDelegationGraphStorage = exports.MemoryStatusListStorage = void 0;
23
+ exports.CascadingRevocationManager = exports.createDelegationGraph = exports.DelegationGraphManager = exports.isIndexSet = exports.BitstringManager = exports.createStatusListManager = exports.StatusList2021Manager = exports.createDelegationVerifier = exports.DelegationCredentialVerifier = exports.createDelegationIssuer = exports.DelegationCredentialIssuer = exports.OAuthRequiredError = exports.DelegationRequiredError = exports.NoOpToolProtectionCache = exports.InMemoryToolProtectionCache = exports.createProofVerificationError = exports.PROOF_VERIFICATION_ERROR_CODES = exports.ProofVerificationError = exports.migrateLegacyKeys = exports.StorageKeyHelpers = exports.createStorageProviders = exports.NoOpOAuthConfigCache = exports.InMemoryOAuthConfigCache = exports.BatchDelegationService = exports.OAuthTokenRetrievalService = exports.ProviderValidationError = exports.ProviderValidator = exports.ConsentOnlyModeError = exports.ProviderResolver = exports.OAuthProviderRegistry = exports.ToolContextBuilder = exports.OAuthService = exports.OAuthConfigService = exports.createSessionRegistrationService = exports.SessionRegistrationService = exports.authorizationMatches = exports.AccessControlApiService = exports.ProofVerifier = exports.CryptoService = exports.ToolProtectionService = exports.MCPIRuntimeBase = exports.MemoryIdentityProvider = exports.MemoryNonceCacheProvider = exports.MemoryStorageProvider = exports.IdentityProvider = exports.NonceCacheProvider = exports.StorageProvider = exports.FetchProvider = exports.ClockProvider = exports.CryptoProvider = void 0;
24
+ exports.IdpTokenResolver = exports.UserDidManager = exports.fetchRemoteConfig = exports.bytesToBase64 = exports.base64urlDecodeToString = exports.base64urlDecodeToBytes = exports.base64urlEncodeFromString = exports.base64urlEncodeFromBytes = exports.parseVCJWT = exports.completeVCJWT = exports.createUnsignedVCJWT = exports.canonicalizeJSON = exports.getSchemaStats = exports.getCriticalSchemas = exports.getSchemaById = exports.getSchemasByCategory = exports.getAllSchemas = exports.SCHEMA_REGISTRY = exports.createSchemaVerifier = exports.SchemaVerifier = exports.isValidBase58 = exports.base58Decode = exports.base58Encode = exports.resolveDidKeySync = exports.publicKeyToJwk = exports.extractPublicKeyFromDidKey = exports.isEd25519DidKey = exports.createDidKeyResolver = exports.MemoryDelegationGraphStorage = exports.MemoryStatusListStorage = exports.createCascadingRevocationManager = void 0;
25
25
  // Base providers
26
26
  var base_1 = require("./providers/base");
27
27
  Object.defineProperty(exports, "CryptoProvider", { enumerable: true, get: function () { return base_1.CryptoProvider; } });
@@ -72,6 +72,7 @@ Object.defineProperty(exports, "OAuthProviderRegistry", { enumerable: true, get:
72
72
  // Provider Resolver (Phase 2)
73
73
  var provider_resolver_1 = require("./services/provider-resolver");
74
74
  Object.defineProperty(exports, "ProviderResolver", { enumerable: true, get: function () { return provider_resolver_1.ProviderResolver; } });
75
+ Object.defineProperty(exports, "ConsentOnlyModeError", { enumerable: true, get: function () { return provider_resolver_1.ConsentOnlyModeError; } });
75
76
  // Provider Validator (Phase 3)
76
77
  var provider_validator_1 = require("./services/provider-validator");
77
78
  Object.defineProperty(exports, "ProviderValidator", { enumerable: true, get: function () { return provider_validator_1.ProviderValidator; } });
@@ -113,14 +113,14 @@ class MCPIRuntimeBase {
113
113
  userDid = resolvedDid ?? undefined;
114
114
  if (this.config.audit?.enabled) {
115
115
  if (userDid) {
116
- console.log("[MCP-I] Resolved existing user DID for session:", {
116
+ console.error("[MCP-I] Resolved existing user DID for session:", {
117
117
  userDid: userDid.substring(0, 20) + "...",
118
118
  hasOAuth: !!oauthIdentity,
119
119
  provider: oauthIdentity?.provider,
120
120
  });
121
121
  }
122
122
  else {
123
- console.log("[MCP-I] Session started anonymous (no userDid):", {
123
+ console.error("[MCP-I] Session started anonymous (no userDid):", {
124
124
  sessionId: sessionId.substring(0, 8) + "...",
125
125
  hasOAuth: !!oauthIdentity,
126
126
  });
@@ -219,7 +219,7 @@ class MCPIRuntimeBase {
219
219
  await this.userDidManager.setUserDidForSession(sessionId, userDid, oauthIdentity);
220
220
  }
221
221
  if (this.config.audit?.enabled) {
222
- console.log("[MCP-I] Session identity updated (Phase 5):", {
222
+ console.error("[MCP-I] Session identity updated (Phase 5):", {
223
223
  sessionId: sessionId.substring(0, 8) + "...",
224
224
  userDid: userDid.substring(0, 20) + "...",
225
225
  provider: oauthIdentity?.provider,
@@ -248,7 +248,7 @@ class MCPIRuntimeBase {
248
248
  // Get agent identity to check protection
249
249
  const identity = await this.getIdentity();
250
250
  if (this.config.audit?.enabled) {
251
- console.log("[MCP-I] Checking tool protection:", {
251
+ console.error("[MCP-I] Checking tool protection:", {
252
252
  tool: toolName,
253
253
  agentDid: identity.did.slice(0, 20) + "...",
254
254
  hasDelegation: !!(session?.delegationToken || session?.consentProof),
@@ -312,7 +312,7 @@ class MCPIRuntimeBase {
312
312
  // Verify delegation token with AccessControlApiService
313
313
  try {
314
314
  if (this.config.audit?.enabled) {
315
- console.log("[MCP-I] 🔐 Verifying delegation token with AccessControlApiService", {
315
+ console.error("[MCP-I] 🔐 Verifying delegation token with AccessControlApiService", {
316
316
  tool: toolName,
317
317
  agentDid: identity.did.slice(0, 20) + "...",
318
318
  hasDelegationToken: !!delegationToken,
@@ -331,7 +331,7 @@ class MCPIRuntimeBase {
331
331
  if (session?.userDid) {
332
332
  verifyRequest.user_did = session.userDid;
333
333
  if (this.config.audit?.enabled) {
334
- console.log("[MCP-I] 🔐 Including user_did in verification request", {
334
+ console.error("[MCP-I] 🔐 Including user_did in verification request", {
335
335
  userDid: session.userDid.slice(0, 20) + "...",
336
336
  });
337
337
  }
@@ -442,7 +442,7 @@ class MCPIRuntimeBase {
442
442
  }
443
443
  // User identifier validation passed (direct match or trusted AgentShield verification)
444
444
  if (this.config.audit?.enabled) {
445
- console.log("[MCP-I] ✅ User identifier validation PASSED", {
445
+ console.error("[MCP-I] ✅ User identifier validation PASSED", {
446
446
  tool: toolName,
447
447
  agentDid: identity.did.slice(0, 20) + "...",
448
448
  userDid: sessionUserDid.substring(0, 20) + "...",
@@ -530,7 +530,7 @@ class MCPIRuntimeBase {
530
530
  }
531
531
  // Authorization method validation passed
532
532
  if (this.config.audit?.enabled) {
533
- console.log("[MCP-I] ✅ Authorization method validation PASSED", {
533
+ console.error("[MCP-I] ✅ Authorization method validation PASSED", {
534
534
  tool: toolName,
535
535
  agentDid: identity.did.slice(0, 20) + "...",
536
536
  authType: delegationAuth.type,
@@ -541,7 +541,7 @@ class MCPIRuntimeBase {
541
541
  // If credential is missing entirely (KV/Memory verifiers), skip validation for backward compatibility
542
542
  // Verification succeeded
543
543
  if (this.config.audit?.enabled) {
544
- console.log("[MCP-I] ✅ Delegation verification SUCCEEDED", {
544
+ console.error("[MCP-I] ✅ Delegation verification SUCCEEDED", {
545
545
  tool: toolName,
546
546
  agentDid: identity.did.slice(0, 20) + "...",
547
547
  delegationId: verificationResult.data.delegation_id,
@@ -614,7 +614,7 @@ class MCPIRuntimeBase {
614
614
  else {
615
615
  // No protection required - tool can be executed freely
616
616
  if (this.config.audit?.enabled) {
617
- console.log("[MCP-I] Tool protection check passed (no delegation required)", {
617
+ console.error("[MCP-I] Tool protection check passed (no delegation required)", {
618
618
  tool: toolName,
619
619
  agentDid: identity.did.slice(0, 20) + "...",
620
620
  reason: "Tool not configured to require delegation",
@@ -1120,7 +1120,7 @@ class MCPIRuntimeBase {
1120
1120
  this.config.audit.logFunction(logLine);
1121
1121
  }
1122
1122
  else {
1123
- console.log("[AUDIT]", logLine);
1123
+ console.error("[AUDIT]", logLine);
1124
1124
  }
1125
1125
  }
1126
1126
  createDIDDocument(identity) {
@@ -9,10 +9,19 @@
9
9
  import type { ToolProtection } from "@kya-os/contracts/tool-protection";
10
10
  import type { OAuthProviderRegistry } from "./oauth-provider-registry.js";
11
11
  import type { OAuthConfigService } from "./oauth-config.service.js";
12
+ /**
13
+ * Error thrown when a tool is configured for consent-only mode (no OAuth needed)
14
+ * This is NOT an error condition - it's a signal to skip OAuth flow
15
+ */
16
+ export declare class ConsentOnlyModeError extends Error {
17
+ readonly toolProtection: ToolProtection;
18
+ constructor(toolProtection: ToolProtection);
19
+ }
12
20
  /**
13
21
  * Resolves OAuth provider for tools with priority-based fallback strategy
14
22
  *
15
23
  * Priority order:
24
+ * 0. Check for consent-only mode (authorization.type === 'none') - skip OAuth
16
25
  * 1. Tool-specific oauthProvider field (Phase 2+ preferred)
17
26
  * 2. Scope prefix inference (fallback)
18
27
  * 3. Project-configured provider from AgentShield dashboard
@@ -22,12 +31,21 @@ export declare class ProviderResolver {
22
31
  private registry;
23
32
  private configService;
24
33
  constructor(registry: OAuthProviderRegistry, configService: OAuthConfigService);
34
+ /**
35
+ * Check if a tool is configured for consent-only mode
36
+ * Consent-only means delegation is required but no OAuth provider is needed
37
+ *
38
+ * @param toolProtection - Tool protection configuration
39
+ * @returns true if consent-only mode
40
+ */
41
+ isConsentOnlyMode(toolProtection: ToolProtection): boolean;
25
42
  /**
26
43
  * Resolve OAuth provider for a tool
27
44
  *
28
45
  * @param toolProtection - Tool protection configuration
29
46
  * @param projectId - Project ID for fetching provider config
30
47
  * @returns Provider name (never null - throws if cannot resolve)
48
+ * @throws ConsentOnlyModeError if tool is consent-only (not a real error)
31
49
  * @throws Error if provider cannot be resolved
32
50
  */
33
51
  resolveProvider(toolProtection: ToolProtection, projectId: string): Promise<string>;
@@ -8,11 +8,25 @@
8
8
  * @package @kya-os/mcp-i-core
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.ProviderResolver = void 0;
11
+ exports.ProviderResolver = exports.ConsentOnlyModeError = void 0;
12
+ /**
13
+ * Error thrown when a tool is configured for consent-only mode (no OAuth needed)
14
+ * This is NOT an error condition - it's a signal to skip OAuth flow
15
+ */
16
+ class ConsentOnlyModeError extends Error {
17
+ toolProtection;
18
+ constructor(toolProtection) {
19
+ super("Tool is configured for consent-only mode (no OAuth provider required)");
20
+ this.toolProtection = toolProtection;
21
+ this.name = "ConsentOnlyModeError";
22
+ }
23
+ }
24
+ exports.ConsentOnlyModeError = ConsentOnlyModeError;
12
25
  /**
13
26
  * Resolves OAuth provider for tools with priority-based fallback strategy
14
27
  *
15
28
  * Priority order:
29
+ * 0. Check for consent-only mode (authorization.type === 'none') - skip OAuth
16
30
  * 1. Tool-specific oauthProvider field (Phase 2+ preferred)
17
31
  * 2. Scope prefix inference (fallback)
18
32
  * 3. Project-configured provider from AgentShield dashboard
@@ -25,15 +39,35 @@ class ProviderResolver {
25
39
  this.registry = registry;
26
40
  this.configService = configService;
27
41
  }
42
+ /**
43
+ * Check if a tool is configured for consent-only mode
44
+ * Consent-only means delegation is required but no OAuth provider is needed
45
+ *
46
+ * @param toolProtection - Tool protection configuration
47
+ * @returns true if consent-only mode
48
+ */
49
+ isConsentOnlyMode(toolProtection) {
50
+ // Check explicit authorization.type === 'none'
51
+ if (toolProtection.authorization?.type === "none") {
52
+ return true;
53
+ }
54
+ return false;
55
+ }
28
56
  /**
29
57
  * Resolve OAuth provider for a tool
30
58
  *
31
59
  * @param toolProtection - Tool protection configuration
32
60
  * @param projectId - Project ID for fetching provider config
33
61
  * @returns Provider name (never null - throws if cannot resolve)
62
+ * @throws ConsentOnlyModeError if tool is consent-only (not a real error)
34
63
  * @throws Error if provider cannot be resolved
35
64
  */
36
65
  async resolveProvider(toolProtection, projectId) {
66
+ // Priority 0: Check for consent-only mode (no OAuth required)
67
+ if (this.isConsentOnlyMode(toolProtection)) {
68
+ console.error(`[ProviderResolver] Tool is consent-only mode (authorization.type=none), skipping OAuth resolution`);
69
+ throw new ConsentOnlyModeError(toolProtection);
70
+ }
37
71
  // Priority 1: Tool-specific provider (Phase 2+ preferred)
38
72
  if (toolProtection.oauthProvider) {
39
73
  // Ensure registry is loaded before checking
@@ -54,7 +88,7 @@ class ProviderResolver {
54
88
  await this.registry.loadFromAgentShield(projectId);
55
89
  }
56
90
  if (this.registry.hasProvider(inferredProvider)) {
57
- console.log(`[ProviderResolver] Inferred provider "${inferredProvider}" from scopes`);
91
+ console.error(`[ProviderResolver] Inferred provider "${inferredProvider}" from scopes`);
58
92
  return inferredProvider;
59
93
  }
60
94
  }
@@ -4,11 +4,23 @@
4
4
  * This service manages tool protection configuration from AgentShield API with
5
5
  * efficient caching and automatic synchronization support.
6
6
  *
7
+ * CONFIGURATION PRECEDENCE (highest to lowest):
8
+ * ---------------------------------------------
9
+ * 1. Remote config (AgentShield API) - WINS (source of truth)
10
+ * 2. Local config (localConfig) - Base defaults, overridden by remote
11
+ * 3. Framework defaults
12
+ *
13
+ * OFFLINE FALLBACK (only when API unavailable):
14
+ * ---------------------------------------------
15
+ * 1. Stale cache (if allowStaleCache=true and within maxStaleCacheAge)
16
+ * 2. offlineFallbackConfig (explicit offline-only config)
17
+ * 3. failSafeBehavior (deny-all or allow-all)
18
+ *
7
19
  * CORE FUNCTIONALITY:
8
20
  * -------------------
9
- * 1. Fetches tool protection config from AgentShield API
10
- * 2. Caches responses with configurable TTL (default 5 minutes)
11
- * 3. Falls back to local config if API unavailable
21
+ * 1. Fetches tool protection config from AgentShield API (remote wins)
22
+ * 2. Merges with local config (local serves as base defaults)
23
+ * 3. Caches responses with configurable TTL (default 5 minutes)
12
24
  * 4. Provides delegation requirement checking before tool execution
13
25
  *
14
26
  * SYNCHRONIZATION WITH AGENTSHIELD:
@@ -133,6 +145,16 @@ export declare class ToolProtectionService {
133
145
  * @param options.bypassCDNCache When true, adds cache-busting to bypass CDN caches (used by clearAndRefresh)
134
146
  */
135
147
  private fetchFromApi;
148
+ /**
149
+ * Parse tool protections from API response
150
+ *
151
+ * Extracts tool protection configs from merged config format:
152
+ * { data: { config: { toolProtection: { tools: {...} } } } }
153
+ *
154
+ * @param response API response from AgentShield
155
+ * @returns Record of tool name to ToolProtection
156
+ */
157
+ private parseToolProtectionsFromResponse;
136
158
  /**
137
159
  * Clear the cache for a project or agent (useful for testing or manual refresh)
138
160
  *