@kya-os/mcp-i-core 1.7.0 → 1.8.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 (121) hide show
  1. package/README.md +1 -1
  2. package/dist/conformance/capability-verifier-adapter.d.ts +66 -0
  3. package/dist/conformance/capability-verifier-adapter.js +61 -0
  4. package/dist/conformance/index.d.ts +10 -0
  5. package/dist/conformance/index.js +19 -0
  6. package/dist/conformance/validate-level2.d.ts +203 -0
  7. package/dist/conformance/validate-level2.js +294 -0
  8. package/dist/conformance/vc-jwt-verifier.d.ts +55 -0
  9. package/dist/conformance/vc-jwt-verifier.js +147 -0
  10. package/dist/delegation/did-web-resolver.d.ts +60 -0
  11. package/dist/delegation/did-web-resolver.js +129 -0
  12. package/dist/delegation/outbound-proof.d.ts +3 -2
  13. package/dist/delegation/outbound-proof.js +3 -2
  14. package/dist/delegation/utils.d.ts +3 -1
  15. package/dist/index.d.ts +9 -63
  16. package/dist/index.js +22 -161
  17. package/dist/utils/base58.d.ts +4 -28
  18. package/dist/utils/base58.js +18 -98
  19. package/dist/utils/base64.d.ts +4 -29
  20. package/dist/utils/base64.js +18 -167
  21. package/dist/utils/did-helpers.d.ts +4 -165
  22. package/dist/utils/did-helpers.js +18 -217
  23. package/package.json +5 -7
  24. package/dist/auth/handshake.d.ts +0 -119
  25. package/dist/auth/handshake.js +0 -250
  26. package/dist/auth/index.d.ts +0 -6
  27. package/dist/auth/index.js +0 -11
  28. package/dist/auth/types.d.ts +0 -46
  29. package/dist/auth/types.js +0 -10
  30. package/dist/cache/oauth-config-cache.d.ts +0 -69
  31. package/dist/cache/oauth-config-cache.js +0 -76
  32. package/dist/cache/tool-protection-cache.d.ts +0 -89
  33. package/dist/cache/tool-protection-cache.js +0 -118
  34. package/dist/compliance/index.d.ts +0 -8
  35. package/dist/compliance/index.js +0 -24
  36. package/dist/compliance/schema-registry.d.ts +0 -50
  37. package/dist/compliance/schema-registry.js +0 -438
  38. package/dist/compliance/schema-verifier.d.ts +0 -110
  39. package/dist/compliance/schema-verifier.js +0 -518
  40. package/dist/config/remote-config.d.ts +0 -173
  41. package/dist/config/remote-config.js +0 -253
  42. package/dist/config.d.ts +0 -182
  43. package/dist/config.js +0 -148
  44. package/dist/identity/idp-token-resolver.d.ts +0 -69
  45. package/dist/identity/idp-token-resolver.js +0 -136
  46. package/dist/identity/idp-token-storage.interface.d.ts +0 -80
  47. package/dist/identity/idp-token-storage.interface.js +0 -14
  48. package/dist/identity/user-did-manager.d.ts +0 -228
  49. package/dist/identity/user-did-manager.js +0 -356
  50. package/dist/logging/index.d.ts +0 -5
  51. package/dist/logging/index.js +0 -10
  52. package/dist/logging/logger.d.ts +0 -33
  53. package/dist/logging/logger.js +0 -104
  54. package/dist/proof/generator.d.ts +0 -109
  55. package/dist/proof/generator.js +0 -236
  56. package/dist/proof/index.d.ts +0 -5
  57. package/dist/proof/index.js +0 -11
  58. package/dist/providers/base.d.ts +0 -95
  59. package/dist/providers/base.js +0 -47
  60. package/dist/providers/memory.d.ts +0 -42
  61. package/dist/providers/memory.js +0 -121
  62. package/dist/runtime/audit-logger.d.ts +0 -37
  63. package/dist/runtime/audit-logger.js +0 -9
  64. package/dist/runtime/base.d.ts +0 -375
  65. package/dist/runtime/base.js +0 -1491
  66. package/dist/runtime/ext-apps-constants.d.ts +0 -14
  67. package/dist/runtime/ext-apps-constants.js +0 -17
  68. package/dist/services/access-control.service.d.ts +0 -138
  69. package/dist/services/access-control.service.js +0 -721
  70. package/dist/services/authorization/authorization-registry.d.ts +0 -29
  71. package/dist/services/authorization/authorization-registry.js +0 -58
  72. package/dist/services/authorization/types.d.ts +0 -53
  73. package/dist/services/authorization/types.js +0 -10
  74. package/dist/services/batch-delegation.service.d.ts +0 -53
  75. package/dist/services/batch-delegation.service.js +0 -95
  76. package/dist/services/crypto.service.d.ts +0 -69
  77. package/dist/services/crypto.service.js +0 -225
  78. package/dist/services/delegation-error-formatter.d.ts +0 -124
  79. package/dist/services/delegation-error-formatter.js +0 -214
  80. package/dist/services/errors.d.ts +0 -49
  81. package/dist/services/errors.js +0 -66
  82. package/dist/services/index.d.ts +0 -9
  83. package/dist/services/index.js +0 -15
  84. package/dist/services/oauth-config.service.d.ts +0 -53
  85. package/dist/services/oauth-config.service.js +0 -141
  86. package/dist/services/oauth-provider-registry.d.ts +0 -88
  87. package/dist/services/oauth-provider-registry.js +0 -128
  88. package/dist/services/oauth-service.d.ts +0 -122
  89. package/dist/services/oauth-service.js +0 -442
  90. package/dist/services/oauth-token-retrieval.service.d.ts +0 -49
  91. package/dist/services/oauth-token-retrieval.service.js +0 -150
  92. package/dist/services/policy.service.d.ts +0 -130
  93. package/dist/services/policy.service.js +0 -399
  94. package/dist/services/proof-verifier.d.ts +0 -98
  95. package/dist/services/proof-verifier.js +0 -319
  96. package/dist/services/provider-resolver.d.ts +0 -89
  97. package/dist/services/provider-resolver.js +0 -196
  98. package/dist/services/provider-validator.d.ts +0 -55
  99. package/dist/services/provider-validator.js +0 -135
  100. package/dist/services/session-registration.service.d.ts +0 -80
  101. package/dist/services/session-registration.service.js +0 -174
  102. package/dist/services/storage.service.d.ts +0 -116
  103. package/dist/services/storage.service.js +0 -411
  104. package/dist/services/tool-context-builder.d.ts +0 -74
  105. package/dist/services/tool-context-builder.js +0 -215
  106. package/dist/services/tool-protection.service.d.ts +0 -193
  107. package/dist/services/tool-protection.service.js +0 -736
  108. package/dist/session/index.d.ts +0 -5
  109. package/dist/session/index.js +0 -11
  110. package/dist/session/manager.d.ts +0 -113
  111. package/dist/session/manager.js +0 -273
  112. package/dist/types/oauth-required-error.d.ts +0 -46
  113. package/dist/types/oauth-required-error.js +0 -42
  114. package/dist/types/tool-protection.d.ts +0 -144
  115. package/dist/types/tool-protection.js +0 -48
  116. package/dist/utils/cors.d.ts +0 -44
  117. package/dist/utils/cors.js +0 -71
  118. package/dist/utils/index.d.ts +0 -8
  119. package/dist/utils/index.js +0 -24
  120. package/dist/utils/storage-keys.d.ts +0 -120
  121. package/dist/utils/storage-keys.js +0 -217
@@ -1,319 +0,0 @@
1
- "use strict";
2
- /**
3
- * ProofVerifier
4
- *
5
- * Centralized proof verification service that validates DetachedProof
6
- * signatures, enforces nonce replay protection, and checks timestamp skew.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.ProofVerifier = void 0;
10
- const crypto_service_js_1 = require("./crypto.service.js");
11
- const proof_1 = require("@kya-os/contracts/proof");
12
- const json_canonicalize_1 = require("json-canonicalize");
13
- const errors_js_1 = require("./errors.js");
14
- class ProofVerifier {
15
- cryptoService;
16
- clock;
17
- nonceCache;
18
- fetch;
19
- timestampSkewSeconds;
20
- nonceTtlSeconds;
21
- constructor(config) {
22
- this.cryptoService = new crypto_service_js_1.CryptoService(config.cryptoProvider);
23
- this.clock = config.clockProvider;
24
- this.nonceCache = config.nonceCacheProvider;
25
- this.fetch = config.fetchProvider;
26
- this.timestampSkewSeconds = config.timestampSkewSeconds ?? 300; // Default 5 minutes
27
- this.nonceTtlSeconds = config.nonceTtlSeconds ?? 300; // Default 5 minutes
28
- }
29
- /**
30
- * Verify a DetachedProof
31
- * Automatically reconstructs canonical payload from proof.meta for signature verification
32
- * @param proof - The proof to verify
33
- * @param publicKeyJwk - Ed25519 public key in JWK format (from DID document)
34
- * @returns Verification result
35
- */
36
- async verifyProof(proof, publicKeyJwk) {
37
- try {
38
- // 1. Validate proof structure
39
- const structureValidation = await this.validateProofStructure(proof);
40
- if (!structureValidation.valid) {
41
- return structureValidation;
42
- }
43
- const validatedProof = structureValidation.proof;
44
- // 2. Check nonce replay protection (scoped to agent DID to prevent cross-agent replay attacks)
45
- const nonceValidation = await this.validateNonce(validatedProof.meta.nonce, validatedProof.meta.did);
46
- if (!nonceValidation.valid) {
47
- return nonceValidation;
48
- }
49
- // 3. Check timestamp skew
50
- const timestampValidation = await this.validateTimestamp(validatedProof.meta.ts);
51
- if (!timestampValidation.valid) {
52
- return timestampValidation;
53
- }
54
- // 4. Reconstruct canonical payload from proof meta
55
- const canonicalPayloadString = this.buildCanonicalPayload(validatedProof.meta);
56
- const canonicalPayloadBytes = new TextEncoder().encode(canonicalPayloadString);
57
- // 5. Verify JWS signature with detached canonical payload
58
- const signatureValidation = await this.verifySignature(validatedProof.jws, publicKeyJwk, canonicalPayloadBytes, validatedProof.meta.kid);
59
- if (!signatureValidation.valid) {
60
- return signatureValidation;
61
- }
62
- // 6. Add nonce to cache to prevent replay (scoped to agent DID)
63
- await this.addNonceToCache(validatedProof.meta.nonce, validatedProof.meta.did);
64
- return {
65
- valid: true,
66
- };
67
- }
68
- catch (error) {
69
- // Security-safe failure: never throw, always return error result
70
- return {
71
- valid: false,
72
- reason: "Proof verification error",
73
- errorCode: errors_js_1.PROOF_VERIFICATION_ERROR_CODES.VERIFICATION_ERROR,
74
- error: error instanceof Error ? error : new Error(String(error)),
75
- details: {
76
- errorMessage: error instanceof Error ? error.message : String(error),
77
- },
78
- };
79
- }
80
- }
81
- /**
82
- * Verify proof with detached payload (for CLI/verifier compatibility)
83
- * @param proof - The proof to verify
84
- * @param canonicalPayload - Canonical JSON payload (for detached JWS) as string or Uint8Array
85
- * @param publicKeyJwk - Ed25519 public key in JWK format
86
- * @returns Verification result
87
- */
88
- async verifyProofDetached(proof, canonicalPayload, publicKeyJwk) {
89
- try {
90
- // 1. Validate proof structure
91
- const structureValidation = await this.validateProofStructure(proof);
92
- if (!structureValidation.valid) {
93
- return structureValidation;
94
- }
95
- const validatedProof = structureValidation.proof;
96
- // 2. Check nonce replay protection (scoped to agent DID to prevent cross-agent replay attacks)
97
- const nonceValidation = await this.validateNonce(validatedProof.meta.nonce, validatedProof.meta.did);
98
- if (!nonceValidation.valid) {
99
- return nonceValidation;
100
- }
101
- // 3. Check timestamp skew
102
- const timestampValidation = await this.validateTimestamp(validatedProof.meta.ts);
103
- if (!timestampValidation.valid) {
104
- return timestampValidation;
105
- }
106
- // 4. Convert canonical payload to Uint8Array if needed
107
- const canonicalPayloadBytes = canonicalPayload instanceof Uint8Array
108
- ? canonicalPayload
109
- : new TextEncoder().encode(canonicalPayload);
110
- // 5. Verify JWS signature with detached payload
111
- const signatureValidation = await this.verifySignature(validatedProof.jws, publicKeyJwk, canonicalPayloadBytes, validatedProof.meta.kid);
112
- if (!signatureValidation.valid) {
113
- return signatureValidation;
114
- }
115
- // 6. Add nonce to cache (scoped to agent DID)
116
- await this.addNonceToCache(validatedProof.meta.nonce, validatedProof.meta.did);
117
- return {
118
- valid: true,
119
- };
120
- }
121
- catch (error) {
122
- // Security-safe failure: never throw, always return error result
123
- return {
124
- valid: false,
125
- reason: "Proof verification error",
126
- errorCode: errors_js_1.PROOF_VERIFICATION_ERROR_CODES.VERIFICATION_ERROR,
127
- error: error instanceof Error ? error : new Error(String(error)),
128
- details: {
129
- errorMessage: error instanceof Error ? error.message : String(error),
130
- },
131
- };
132
- }
133
- }
134
- /**
135
- * Validate proof structure using Zod schema
136
- * @private
137
- */
138
- async validateProofStructure(proof) {
139
- const validationResult = proof_1.DetachedProofSchema.safeParse(proof);
140
- if (!validationResult.success) {
141
- return {
142
- valid: false,
143
- reason: "Invalid proof structure",
144
- errorCode: errors_js_1.PROOF_VERIFICATION_ERROR_CODES.INVALID_PROOF_STRUCTURE,
145
- error: new Error(`Proof validation failed: ${validationResult.error.message}`),
146
- details: {
147
- zodErrors: validationResult.error.errors,
148
- },
149
- };
150
- }
151
- return {
152
- valid: true,
153
- proof: validationResult.data,
154
- };
155
- }
156
- /**
157
- * Validate nonce replay protection
158
- * @private
159
- */
160
- async validateNonce(nonce, agentDid) {
161
- const nonceUsed = await this.nonceCache.has(nonce, agentDid);
162
- if (nonceUsed) {
163
- return {
164
- valid: false,
165
- reason: "Nonce already used (replay attack detected)",
166
- errorCode: errors_js_1.PROOF_VERIFICATION_ERROR_CODES.NONCE_REPLAY_DETECTED,
167
- details: {
168
- nonce,
169
- agentDid,
170
- },
171
- };
172
- }
173
- return { valid: true };
174
- }
175
- /**
176
- * Validate timestamp skew
177
- * @private
178
- */
179
- async validateTimestamp(timestamp) {
180
- // Convert seconds to milliseconds for clock provider (which uses Date.now())
181
- const timestampMs = timestamp * 1000;
182
- if (!this.clock.isWithinSkew(timestampMs, this.timestampSkewSeconds)) {
183
- return {
184
- valid: false,
185
- reason: `Timestamp out of skew window (skew: ${this.timestampSkewSeconds}s)`,
186
- errorCode: errors_js_1.PROOF_VERIFICATION_ERROR_CODES.TIMESTAMP_SKEW_EXCEEDED,
187
- details: {
188
- timestamp,
189
- timestampMs,
190
- skewSeconds: this.timestampSkewSeconds,
191
- currentTime: this.clock.now(),
192
- },
193
- };
194
- }
195
- return { valid: true };
196
- }
197
- /**
198
- * Verify JWS signature
199
- * @private
200
- */
201
- async verifySignature(jws, publicKeyJwk, canonicalPayloadBytes, expectedKid) {
202
- const signatureValid = await this.cryptoService.verifyJWS(jws, publicKeyJwk, {
203
- detachedPayload: canonicalPayloadBytes,
204
- expectedKid,
205
- alg: "EdDSA",
206
- });
207
- if (!signatureValid) {
208
- return {
209
- valid: false,
210
- reason: "Invalid JWS signature",
211
- errorCode: errors_js_1.PROOF_VERIFICATION_ERROR_CODES.INVALID_JWS_SIGNATURE,
212
- details: {
213
- jwsLength: jws.length,
214
- expectedKid,
215
- actualKid: publicKeyJwk.kid,
216
- },
217
- };
218
- }
219
- return { valid: true };
220
- }
221
- /**
222
- * Add nonce to cache to prevent replay (scoped to agent DID)
223
- * @private
224
- */
225
- async addNonceToCache(nonce, agentDid) {
226
- // Pass TTL in seconds, not absolute timestamp
227
- await this.nonceCache.add(nonce, this.nonceTtlSeconds, agentDid);
228
- }
229
- /**
230
- * Fetch public key from DID document
231
- * @param did - DID to resolve
232
- * @param kid - Key ID (optional, defaults to first verification method)
233
- * @returns Ed25519 JWK or null if not found
234
- * @throws {ProofVerificationError} If DID resolution fails with specific error code
235
- */
236
- async fetchPublicKeyFromDID(did, kid) {
237
- try {
238
- const didDoc = await this.fetch.resolveDID(did);
239
- if (!didDoc) {
240
- throw new errors_js_1.ProofVerificationError(errors_js_1.PROOF_VERIFICATION_ERROR_CODES.DID_DOCUMENT_NOT_FOUND, `DID document not found: ${did}`, { did });
241
- }
242
- if (!didDoc.verificationMethod ||
243
- didDoc.verificationMethod.length === 0) {
244
- throw new errors_js_1.ProofVerificationError(errors_js_1.PROOF_VERIFICATION_ERROR_CODES.VERIFICATION_METHOD_NOT_FOUND, `No verification methods found in DID document: ${did}`, { did });
245
- }
246
- // Find verification method by kid or use first one
247
- let verificationMethod;
248
- if (kid) {
249
- const kidWithHash = kid.startsWith("#") ? kid : `#${kid}`;
250
- verificationMethod = didDoc.verificationMethod.find((vm) => vm.id === kidWithHash || vm.id === `${did}${kidWithHash}`);
251
- if (!verificationMethod) {
252
- throw new errors_js_1.ProofVerificationError(errors_js_1.PROOF_VERIFICATION_ERROR_CODES.VERIFICATION_METHOD_NOT_FOUND, `Verification method not found for kid: ${kid}`, {
253
- did,
254
- kid,
255
- availableKids: didDoc.verificationMethod.map((vm) => vm.id),
256
- });
257
- }
258
- }
259
- else {
260
- verificationMethod = didDoc.verificationMethod[0];
261
- }
262
- if (!verificationMethod?.publicKeyJwk) {
263
- throw new errors_js_1.ProofVerificationError(errors_js_1.PROOF_VERIFICATION_ERROR_CODES.PUBLIC_KEY_NOT_FOUND, `Public key JWK not found in verification method`, { did, kid, verificationMethodId: verificationMethod?.id });
264
- }
265
- const jwk = verificationMethod.publicKeyJwk;
266
- // Validate it's an Ed25519 key
267
- if (jwk.kty !== "OKP" || jwk.crv !== "Ed25519" || !jwk.x) {
268
- throw new errors_js_1.ProofVerificationError(errors_js_1.PROOF_VERIFICATION_ERROR_CODES.INVALID_JWK_FORMAT, `Unsupported key type or curve: kty=${jwk.kty}, crv=${jwk.crv}`, { did, kid, jwk: { kty: jwk.kty, crv: jwk.crv } });
269
- }
270
- return jwk;
271
- }
272
- catch (error) {
273
- if (error instanceof errors_js_1.ProofVerificationError) {
274
- throw error;
275
- }
276
- console.error("[ProofVerifier] Failed to fetch public key from DID:", error);
277
- throw new errors_js_1.ProofVerificationError(errors_js_1.PROOF_VERIFICATION_ERROR_CODES.DID_RESOLUTION_FAILED, `DID resolution failed: ${error instanceof Error ? error.message : String(error)}`, {
278
- did,
279
- kid,
280
- originalError: error instanceof Error ? error.message : String(error),
281
- });
282
- }
283
- }
284
- /**
285
- * Build canonical payload from proof meta
286
- *
287
- * CRITICAL: This must reconstruct the exact JWS payload structure that was originally signed.
288
- * The original JWS payload uses standard JWT claims (aud, sub, iss) plus custom proof claims,
289
- * NOT the proof.meta structure directly.
290
- *
291
- * @param meta - Proof metadata
292
- * @returns Canonical JSON string matching the original JWS payload structure
293
- */
294
- buildCanonicalPayload(meta) {
295
- // Reconstruct the original JWS payload structure that was signed
296
- // This matches the structure used in proof generation (proof.ts, proof-generator.ts)
297
- const payload = {
298
- // Standard JWT claims (RFC 7519) - these are what was actually signed
299
- aud: meta.audience, // Audience (who the token is for)
300
- sub: meta.did, // Subject (agent DID)
301
- iss: meta.did, // Issuer (agent DID - self-issued)
302
- // Custom MCP-I proof claims
303
- requestHash: meta.requestHash,
304
- responseHash: meta.responseHash,
305
- ts: meta.ts,
306
- nonce: meta.nonce,
307
- sessionId: meta.sessionId,
308
- // Optional claims (only include if present)
309
- ...(meta.scopeId && { scopeId: meta.scopeId }),
310
- ...(meta.delegationRef && { delegationRef: meta.delegationRef }),
311
- ...(meta.clientDid && { clientDid: meta.clientDid }),
312
- };
313
- // Canonicalize the reconstructed payload using the same function as proof generation
314
- // CRITICAL: Must use json-canonicalize canonicalize() to match proof.ts exactly
315
- return (0, json_canonicalize_1.canonicalize)(payload);
316
- }
317
- }
318
- exports.ProofVerifier = ProofVerifier;
319
- //# sourceMappingURL=proof-verifier.js.map
@@ -1,89 +0,0 @@
1
- /**
2
- * Provider Resolver
3
- *
4
- * Resolves OAuth provider for tools using priority-based resolution strategy.
5
- * Supports Phase 2+ tool-specific providers with backward compatibility for Phase 1.
6
- *
7
- * @package @kya-os/mcp-i-core
8
- */
9
- import type { ToolProtection } from "@kya-os/contracts/tool-protection";
10
- import type { OAuthProviderRegistry } from "./oauth-provider-registry.js";
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
- }
20
- /**
21
- * Error thrown when a tool requires credential/password-based authentication
22
- * This is NOT an error condition - it's a signal to use credential auth flow
23
- * (username/password, email/password, etc.) instead of OAuth
24
- */
25
- export declare class CredentialAuthModeError extends Error {
26
- readonly toolProtection: ToolProtection;
27
- /** The credential provider ID configured for this tool */
28
- readonly provider: string;
29
- constructor(toolProtection: ToolProtection, provider: string);
30
- }
31
- /**
32
- * Resolves OAuth provider for tools with priority-based fallback strategy
33
- *
34
- * Priority order:
35
- * 0. Check for consent-only mode (authorization.type === 'none') - skip OAuth
36
- * 1. Tool-specific oauthProvider field (Phase 2+ preferred)
37
- * 2. Scope prefix inference (fallback)
38
- * 3. Project-configured provider from AgentShield dashboard
39
- * 4. Error if no provider can be resolved
40
- */
41
- export declare class ProviderResolver {
42
- private registry;
43
- private configService;
44
- constructor(registry: OAuthProviderRegistry, configService: OAuthConfigService);
45
- /**
46
- * Check if a tool is configured for consent-only mode
47
- * Consent-only means delegation is required but no OAuth provider is needed
48
- *
49
- * @param toolProtection - Tool protection configuration
50
- * @returns true if consent-only mode
51
- */
52
- isConsentOnlyMode(toolProtection: ToolProtection): boolean;
53
- /**
54
- * Check if a tool is configured for credential/password-based authentication
55
- * This includes username/password, email/password, etc.
56
- *
57
- * @param toolProtection - Tool protection configuration
58
- * @returns Object with isCredential flag and optional provider ID
59
- */
60
- isCredentialAuthMode(toolProtection: ToolProtection): {
61
- isCredential: boolean;
62
- provider?: string;
63
- };
64
- /**
65
- * Resolve OAuth provider for a tool
66
- *
67
- * @param toolProtection - Tool protection configuration
68
- * @param projectId - Project ID for fetching provider config
69
- * @returns Provider name (never null - throws if cannot resolve)
70
- * @throws ConsentOnlyModeError if tool is consent-only (not a real error)
71
- * @throws CredentialAuthModeError if tool requires password/credential auth
72
- * @throws Error if provider cannot be resolved
73
- */
74
- resolveProvider(toolProtection: ToolProtection, projectId: string): Promise<string>;
75
- /**
76
- * Infer provider from scope prefixes
77
- *
78
- * Used as Priority 2 fallback when oauthProvider is not specified.
79
- * Examples:
80
- * - github:repo:read → github
81
- * - gmail:read → google
82
- * - microsoft:calendar:read → microsoft
83
- *
84
- * @param scopes - Required scopes for the tool
85
- * @returns Provider name if uniquely inferred, null otherwise
86
- */
87
- private inferProviderFromScopes;
88
- }
89
- //# sourceMappingURL=provider-resolver.d.ts.map
@@ -1,196 +0,0 @@
1
- "use strict";
2
- /**
3
- * Provider Resolver
4
- *
5
- * Resolves OAuth provider for tools using priority-based resolution strategy.
6
- * Supports Phase 2+ tool-specific providers with backward compatibility for Phase 1.
7
- *
8
- * @package @kya-os/mcp-i-core
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.ProviderResolver = exports.CredentialAuthModeError = 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;
25
- /**
26
- * Error thrown when a tool requires credential/password-based authentication
27
- * This is NOT an error condition - it's a signal to use credential auth flow
28
- * (username/password, email/password, etc.) instead of OAuth
29
- */
30
- class CredentialAuthModeError extends Error {
31
- toolProtection;
32
- /** The credential provider ID configured for this tool */
33
- provider;
34
- constructor(toolProtection, provider) {
35
- super(`Tool requires credential authentication with provider "${provider}"`);
36
- this.toolProtection = toolProtection;
37
- this.name = "CredentialAuthModeError";
38
- this.provider = provider;
39
- }
40
- }
41
- exports.CredentialAuthModeError = CredentialAuthModeError;
42
- /**
43
- * Resolves OAuth provider for tools with priority-based fallback strategy
44
- *
45
- * Priority order:
46
- * 0. Check for consent-only mode (authorization.type === 'none') - skip OAuth
47
- * 1. Tool-specific oauthProvider field (Phase 2+ preferred)
48
- * 2. Scope prefix inference (fallback)
49
- * 3. Project-configured provider from AgentShield dashboard
50
- * 4. Error if no provider can be resolved
51
- */
52
- class ProviderResolver {
53
- registry;
54
- configService;
55
- constructor(registry, configService) {
56
- this.registry = registry;
57
- this.configService = configService;
58
- }
59
- /**
60
- * Check if a tool is configured for consent-only mode
61
- * Consent-only means delegation is required but no OAuth provider is needed
62
- *
63
- * @param toolProtection - Tool protection configuration
64
- * @returns true if consent-only mode
65
- */
66
- isConsentOnlyMode(toolProtection) {
67
- // Check explicit authorization.type === 'none'
68
- if (toolProtection.authorization?.type === "none") {
69
- return true;
70
- }
71
- return false;
72
- }
73
- /**
74
- * Check if a tool is configured for credential/password-based authentication
75
- * This includes username/password, email/password, etc.
76
- *
77
- * @param toolProtection - Tool protection configuration
78
- * @returns Object with isCredential flag and optional provider ID
79
- */
80
- isCredentialAuthMode(toolProtection) {
81
- // Check explicit authorization.type === 'password'
82
- if (toolProtection.authorization?.type === "password") {
83
- return {
84
- isCredential: true,
85
- provider: toolProtection.authorization.provider || "credentials",
86
- };
87
- }
88
- return { isCredential: false };
89
- }
90
- /**
91
- * Resolve OAuth provider for a tool
92
- *
93
- * @param toolProtection - Tool protection configuration
94
- * @param projectId - Project ID for fetching provider config
95
- * @returns Provider name (never null - throws if cannot resolve)
96
- * @throws ConsentOnlyModeError if tool is consent-only (not a real error)
97
- * @throws CredentialAuthModeError if tool requires password/credential auth
98
- * @throws Error if provider cannot be resolved
99
- */
100
- async resolveProvider(toolProtection, projectId) {
101
- // Priority 0a: Check for consent-only mode (no OAuth required)
102
- if (this.isConsentOnlyMode(toolProtection)) {
103
- console.error(`[ProviderResolver] Tool is consent-only mode (authorization.type=none), skipping OAuth resolution`);
104
- throw new ConsentOnlyModeError(toolProtection);
105
- }
106
- // Priority 0b: Check for credential/password auth mode (not OAuth)
107
- const credentialCheck = this.isCredentialAuthMode(toolProtection);
108
- if (credentialCheck.isCredential) {
109
- console.error(`[ProviderResolver] Tool requires credential auth (authorization.type=password), provider="${credentialCheck.provider}"`);
110
- throw new CredentialAuthModeError(toolProtection, credentialCheck.provider);
111
- }
112
- // Priority 1: Tool-specific provider (Phase 2+ preferred)
113
- if (toolProtection.oauthProvider) {
114
- // Ensure registry is loaded before checking
115
- if (this.registry.getProviderNames().length === 0) {
116
- await this.registry.loadFromAgentShield(projectId);
117
- }
118
- if (!this.registry.hasProvider(toolProtection.oauthProvider)) {
119
- throw new Error(`Provider "${toolProtection.oauthProvider}" not configured for project "${projectId}". ` +
120
- `Add provider in project settings.`);
121
- }
122
- return toolProtection.oauthProvider;
123
- }
124
- // Priority 2: Scope prefix inference (fallback)
125
- const inferredProvider = this.inferProviderFromScopes(toolProtection.requiredScopes || []);
126
- if (inferredProvider) {
127
- // Ensure registry is loaded before checking
128
- if (this.registry.getProviderNames().length === 0) {
129
- await this.registry.loadFromAgentShield(projectId);
130
- }
131
- if (this.registry.hasProvider(inferredProvider)) {
132
- console.error(`[ProviderResolver] Inferred provider "${inferredProvider}" from scopes`);
133
- return inferredProvider;
134
- }
135
- }
136
- // Priority 3: Use explicitly configured provider from AgentShield dashboard
137
- // This is the provider the user has actually configured, not just any available provider
138
- await this.registry.loadFromAgentShield(projectId);
139
- const configuredProvider = this.registry.getConfiguredProvider();
140
- if (configuredProvider && this.registry.hasProvider(configuredProvider)) {
141
- console.warn(`[ProviderResolver] Tool does not specify oauthProvider. ` +
142
- `Using project-configured provider "${configuredProvider}" as fallback. ` +
143
- `Consider explicitly setting oauthProvider in tool protection config.`);
144
- return configuredProvider;
145
- }
146
- // Priority 4: Error if no provider is configured
147
- // NOTE: We intentionally do NOT fall back to "first available provider" anymore
148
- // because AgentShield returns ALL providers (even unconfigured ones).
149
- // Only use providers explicitly configured by the user.
150
- throw new Error(`Tool requires OAuth but no provider is configured for project "${projectId}". ` +
151
- `Configure an OAuth provider in AgentShield dashboard.`);
152
- }
153
- /**
154
- * Infer provider from scope prefixes
155
- *
156
- * Used as Priority 2 fallback when oauthProvider is not specified.
157
- * Examples:
158
- * - github:repo:read → github
159
- * - gmail:read → google
160
- * - microsoft:calendar:read → microsoft
161
- *
162
- * @param scopes - Required scopes for the tool
163
- * @returns Provider name if uniquely inferred, null otherwise
164
- */
165
- inferProviderFromScopes(scopes) {
166
- if (!scopes || scopes.length === 0) {
167
- return null;
168
- }
169
- // Extract first part of scope (before first colon)
170
- const scopePrefixes = scopes.map((scope) => {
171
- const parts = scope.split(":");
172
- return parts[0].toLowerCase();
173
- });
174
- // Provider mapping
175
- const providerMap = {
176
- github: "github",
177
- google: "google",
178
- gmail: "google", // gmail:read → google
179
- calendar: "google", // calendar:read → google (if ambiguous, use project default)
180
- microsoft: "microsoft",
181
- outlook: "microsoft",
182
- slack: "slack",
183
- auth0: "auth0",
184
- okta: "okta",
185
- };
186
- // Find unique provider
187
- const providers = new Set(scopePrefixes.map((prefix) => providerMap[prefix]).filter(Boolean));
188
- if (providers.size === 1) {
189
- return Array.from(providers)[0];
190
- }
191
- // Ambiguous or no prefix → return null (use project-level provider)
192
- return null;
193
- }
194
- }
195
- exports.ProviderResolver = ProviderResolver;
196
- //# sourceMappingURL=provider-resolver.js.map
@@ -1,55 +0,0 @@
1
- /**
2
- * Provider Validator
3
- *
4
- * Validates OAuth provider configurations for custom IDP support.
5
- * Ensures provider configurations are valid before registration.
6
- *
7
- * @package @kya-os/mcp-i-core
8
- */
9
- import type { OAuthProvider } from "@kya-os/contracts/config";
10
- /**
11
- * Validation error for provider configuration issues
12
- */
13
- export declare class ProviderValidationError extends Error {
14
- readonly field?: string | undefined;
15
- constructor(message: string, field?: string | undefined);
16
- }
17
- /**
18
- * Service for validating OAuth provider configurations
19
- */
20
- export declare class ProviderValidator {
21
- /**
22
- * Validate provider configuration
23
- *
24
- * @param provider - Provider configuration to validate
25
- * @param name - Provider name (for error messages)
26
- * @throws ProviderValidationError if validation fails
27
- */
28
- validate(provider: OAuthProvider, name: string): void;
29
- /**
30
- * Validate URL format
31
- *
32
- * @param url - URL to validate
33
- * @param providerName - Provider name (for error messages)
34
- * @param fieldName - Field name (for error messages)
35
- * @throws ProviderValidationError if URL is invalid
36
- */
37
- private validateUrl;
38
- /**
39
- * Validate custom parameters don't override reserved OAuth parameters
40
- *
41
- * @param customParams - Custom parameters to validate
42
- * @param providerName - Provider name (for error messages)
43
- * @throws ProviderValidationError if reserved parameter is overridden
44
- */
45
- private validateCustomParams;
46
- /**
47
- * Test provider endpoint reachability (optional)
48
- *
49
- * @param provider - Provider configuration
50
- * @param fetchProvider - Fetch implementation
51
- * @returns True if endpoint is reachable, false otherwise
52
- */
53
- testProvider(provider: OAuthProvider, fetchProvider: typeof fetch): Promise<boolean>;
54
- }
55
- //# sourceMappingURL=provider-validator.d.ts.map