@kya-os/mcp-i
Version:
The TypeScript MCP framework with identity features built-in
134 lines (133 loc) • 5.43 kB
JavaScript
;
/**
* 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;
}
}