UNPKG

@kya-os/mcp-i

Version:

The TypeScript MCP framework with identity features built-in

134 lines (133 loc) 5.43 kB
"use strict"; /** * Delegation Verification Module * * This module provides the core interfaces and implementations for verifying * agent delegations in the MCP-I bouncer architecture. * * Architecture: * - DelegationVerifier: Abstract interface (Dependency Inversion Principle) * - Concrete adapters: CloudflareKVVerifier, AgentShieldAPIVerifier * - Factory: createDelegationVerifier() selects adapter based on config * * Related: PHASE_1_XMCP_I_SERVER.md Epic 1 (Delegation Storage Layer) */ Object.defineProperty(exports, "__esModule", { value: true }); exports.VerifyDelegationInputSchema = void 0; exports.extractScopes = extractScopes; exports.checkScopes = checkScopes; exports.validateDelegation = validateDelegation; exports.createDelegationVerifier = createDelegationVerifier; const delegation_1 = require("@kya-os/contracts/delegation"); const zod_1 = require("zod"); /** * Helper: Extract scopes from delegation (handles both simple and CRISP formats) * * @param delegation - Delegation record * @returns Array of scope strings */ function extractScopes(delegation) { // Try simple scopes first (Phase 1 format) if (delegation.constraints?.scopes && delegation.constraints.scopes.length > 0) { return delegation.constraints.scopes; } // Fall back to CRISP scopes if (delegation.constraints?.crisp?.scopes && delegation.constraints.crisp.scopes.length > 0) { // Convert CRISP scopes to simple strings (use resource as scope name) return delegation.constraints.crisp.scopes.map((s) => s.resource); } return []; } /** * Helper: Check if delegation scopes satisfy required scopes * * @param delegationScopes - Scopes granted by delegation * @param requiredScopes - Scopes required for operation * @returns true if all required scopes are present */ function checkScopes(delegationScopes, requiredScopes) { // Check if delegation has all required scopes return requiredScopes.every((required) => delegationScopes.includes(required)); } /** * Helper: Validate delegation record completeness * * @param delegation - Delegation to validate * @returns Validation result with reason */ function validateDelegation(delegation) { // Check if delegation is currently valid (active + time bounds) if (!(0, delegation_1.isDelegationCurrentlyValid)(delegation)) { if (delegation.status === 'revoked') { return { valid: false, reason: 'Delegation revoked' }; } if (delegation.status === 'expired') { return { valid: false, reason: 'Delegation expired' }; } return { valid: false, reason: 'Delegation not currently valid' }; } // Check required fields if (!delegation.subjectDid) { return { valid: false, reason: 'Missing subjectDid' }; } // Check for scopes (either simple array or CRISP scopes) const hasScopes = (delegation.constraints?.scopes && delegation.constraints.scopes.length > 0) || (delegation.constraints?.crisp?.scopes && delegation.constraints.crisp.scopes.length > 0); if (!hasScopes) { return { valid: false, reason: 'Missing scopes' }; } return { valid: true }; } /** * Validation schema for verify method inputs */ exports.VerifyDelegationInputSchema = zod_1.z.object({ agentDid: zod_1.z.string().min(1), scopes: zod_1.z.array(zod_1.z.string()).min(1), options: zod_1.z.object({ skipCache: zod_1.z.boolean().optional(), maxCacheAge: zod_1.z.number().int().positive().optional(), }).optional(), }); /** * Factory: Create delegation verifier based on config * * Note: We import all adapters statically for better compatibility. * Tree-shaking will remove unused adapters in production builds. * * Note: AgentShield API responses use standard wrapper format * { success: boolean, data: {...}, metadata?: {...} } as defined in * @kya-os/contracts/agentshield-api. This is handled in the * AgentShieldAPIDelegationVerifier implementation. * * @param config - Verifier configuration * @returns DelegationVerifier instance */ function createDelegationVerifier(config) { switch (config.type) { case 'cloudflare-kv': { const CloudflareKVDelegationVerifier = require('./delegation-verifier-kv').CloudflareKVDelegationVerifier; return new CloudflareKVDelegationVerifier(config); } case 'agentshield-api': { const AgentShieldAPIDelegationVerifier = require('./delegation-verifier-agentshield').AgentShieldAPIDelegationVerifier; return new AgentShieldAPIDelegationVerifier(config); } case 'memory': { const MemoryDelegationVerifier = require('./delegation-verifier-memory').MemoryDelegationVerifier; return new MemoryDelegationVerifier(config); } default: const configType = 'type' in config ? config.type : 'unknown'; // Use RuntimeError format from @kya-os/contracts/runtime/errors const runtimeError = { error: 'invalid_config', message: `Unknown delegation verifier type: ${configType}`, httpStatus: 500, }; // Create Error object that can be checked with RuntimeErrorSchema const error = new Error(runtimeError.message); Object.assign(error, runtimeError); throw error; } }