@kya-os/mcp-i 1.5.0 → 1.5.2
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.
|
@@ -42,6 +42,8 @@ export interface AgentReputation {
|
|
|
42
42
|
export interface AuthHandshakeConfig {
|
|
43
43
|
/** Delegation verifier instance */
|
|
44
44
|
delegationVerifier: DelegationVerifier;
|
|
45
|
+
/** Resume token store (REQUIRED to persist tokens across calls) */
|
|
46
|
+
resumeTokenStore: ResumeTokenStore;
|
|
45
47
|
/** KTA API configuration (optional, for reputation checks) */
|
|
46
48
|
kta?: {
|
|
47
49
|
apiUrl: string;
|
|
@@ -120,9 +120,12 @@ async function verifyOrHints(agentDid, scopes, config, resumeToken) {
|
|
|
120
120
|
}
|
|
121
121
|
catch (error) {
|
|
122
122
|
console.error('[AuthHandshake] Delegation verification failed:', error);
|
|
123
|
+
const errorMessage = `Delegation verification error: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
|
124
|
+
const authError = await buildNeedsAuthorizationError(agentDid, scopes, config, errorMessage);
|
|
123
125
|
return {
|
|
124
126
|
authorized: false,
|
|
125
|
-
|
|
127
|
+
authError,
|
|
128
|
+
reason: errorMessage,
|
|
126
129
|
};
|
|
127
130
|
}
|
|
128
131
|
// Step 3: If delegation exists and valid, authorize immediately
|
|
@@ -202,9 +205,8 @@ async function fetchAgentReputation(agentDid, ktaConfig) {
|
|
|
202
205
|
* @returns NeedsAuthorizationError
|
|
203
206
|
*/
|
|
204
207
|
async function buildNeedsAuthorizationError(agentDid, scopes, config, message) {
|
|
205
|
-
//
|
|
206
|
-
const
|
|
207
|
-
const resumeToken = await resumeTokenStore.create(agentDid, scopes, {
|
|
208
|
+
// Use the persistent resume token store from config
|
|
209
|
+
const resumeToken = await config.resumeTokenStore.create(agentDid, scopes, {
|
|
208
210
|
requestedAt: Date.now(),
|
|
209
211
|
});
|
|
210
212
|
const expiresAt = Date.now() + (config.bouncer.resumeTokenTtl || 600_000);
|
|
@@ -100,10 +100,9 @@ class CloudflareKVDelegationVerifier {
|
|
|
100
100
|
if (this.debug) {
|
|
101
101
|
console.log(`[KV] Cache MISS for ${agentDid}, querying KV...`);
|
|
102
102
|
}
|
|
103
|
-
//
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
if (!delegationId) {
|
|
103
|
+
// List all delegations for this agent (to support subset scope matching)
|
|
104
|
+
const listResult = await this.kv.list({ prefix: `agent:${agentDid}:scopes:` });
|
|
105
|
+
if (!listResult.keys || listResult.keys.length === 0) {
|
|
107
106
|
const result = {
|
|
108
107
|
valid: false,
|
|
109
108
|
reason: 'No delegation found for agent',
|
|
@@ -116,17 +115,37 @@ class CloudflareKVDelegationVerifier {
|
|
|
116
115
|
}
|
|
117
116
|
return result;
|
|
118
117
|
}
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
// Try each delegation to find one that matches the requested scopes
|
|
119
|
+
let matchingDelegation = null;
|
|
120
|
+
for (const key of listResult.keys) {
|
|
121
|
+
const delegationId = await this.kv.get(key.name, 'text');
|
|
122
|
+
if (!delegationId)
|
|
123
|
+
continue;
|
|
124
|
+
const delegation = await this.get(delegationId);
|
|
125
|
+
if (!delegation)
|
|
126
|
+
continue;
|
|
127
|
+
// Check if this delegation has the required scopes
|
|
128
|
+
const delegationScopes = (0, delegation_verifier_1.extractScopes)(delegation);
|
|
129
|
+
const scopesMatch = (0, delegation_verifier_1.checkScopes)(delegationScopes, scopes);
|
|
130
|
+
if (scopesMatch) {
|
|
131
|
+
// Found a matching delegation!
|
|
132
|
+
matchingDelegation = delegation;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!matchingDelegation) {
|
|
122
137
|
const result = {
|
|
123
138
|
valid: false,
|
|
124
|
-
reason: '
|
|
139
|
+
reason: 'No delegation found with required scopes',
|
|
125
140
|
cached: false,
|
|
126
141
|
};
|
|
127
142
|
this.cache.set(cacheKey, result, this.cacheTtl / 2);
|
|
143
|
+
if (this.debug) {
|
|
144
|
+
console.log(`[KV] No matching delegation found (${Date.now() - startTime}ms)`);
|
|
145
|
+
}
|
|
128
146
|
return result;
|
|
129
147
|
}
|
|
148
|
+
const delegation = matchingDelegation;
|
|
130
149
|
// Validate delegation
|
|
131
150
|
const validation = (0, delegation_verifier_1.validateDelegation)(delegation);
|
|
132
151
|
if (!validation.valid) {
|
|
@@ -28,6 +28,7 @@ class MCPIRuntime {
|
|
|
28
28
|
debugManager;
|
|
29
29
|
demoManager;
|
|
30
30
|
delegationVerifier; // NEW - Phase 1
|
|
31
|
+
resumeTokenStore; // NEW - Phase 1
|
|
31
32
|
config;
|
|
32
33
|
cachedIdentity;
|
|
33
34
|
constructor(config = {}) {
|
|
@@ -41,6 +42,9 @@ class MCPIRuntime {
|
|
|
41
42
|
this.sessionManager = new session_1.SessionManager(config.session);
|
|
42
43
|
// Initialize audit logger
|
|
43
44
|
this.auditLogger = new audit_1.AuditLogger(config.audit);
|
|
45
|
+
// Initialize resume token store (NEW - Phase 1)
|
|
46
|
+
// Use in-memory store by default (sufficient for most use cases)
|
|
47
|
+
this.resumeTokenStore = new auth_handshake_1.MemoryResumeTokenStore(config.delegation?.authorization?.resumeTokenTtl || 600_000);
|
|
44
48
|
// Initialize delegation verifier (NEW - Phase 1)
|
|
45
49
|
if (config.delegation?.enabled && config.delegation?.verifier) {
|
|
46
50
|
this.delegationVerifier = (0, delegation_verifier_1.createDelegationVerifier)(config.delegation.verifier);
|
|
@@ -113,6 +117,7 @@ class MCPIRuntime {
|
|
|
113
117
|
// Build auth handshake config
|
|
114
118
|
const authConfig = {
|
|
115
119
|
delegationVerifier: this.delegationVerifier,
|
|
120
|
+
resumeTokenStore: this.resumeTokenStore,
|
|
116
121
|
kta: this.config.delegation.authorization?.kta,
|
|
117
122
|
bouncer: {
|
|
118
123
|
authorizationUrl: this.config.delegation.authorization?.authorizationUrl ||
|
|
@@ -127,6 +132,9 @@ class MCPIRuntime {
|
|
|
127
132
|
const verifyResult = await (0, auth_handshake_1.verifyOrHints)(options.agentDid, requiredScopes, authConfig);
|
|
128
133
|
// If not authorized, return needs_authorization error
|
|
129
134
|
if (!verifyResult.authorized) {
|
|
135
|
+
if (!verifyResult.authError) {
|
|
136
|
+
throw new Error('Authorization failed but no authError was provided');
|
|
137
|
+
}
|
|
130
138
|
return verifyResult.authError;
|
|
131
139
|
}
|
|
132
140
|
// If authorized, log the delegation ID for audit trail
|