anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
289 lines • 12.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageHandlerRegistry = void 0;
const types_1 = require("./types");
const message_protocol_1 = require("./message-protocol");
const activity_logger_1 = require("../activity/activity-logger");
const types_2 = require("../activity/types");
class MessageHandlerRegistry {
constructor(agentManager, delegationManager, policyEngine, activityLogger) {
this.agentManager = agentManager;
this.delegationManager = delegationManager;
this.policyEngine = policyEngine;
this.activityLogger = activityLogger;
this.handlers = new Map();
this.defaultHandlers = new Map();
this.registerDefaultHandlers();
}
/**
* Registers a message handler for a specific message type
*/
registerHandler(type, handler) {
if (!this.handlers.has(type)) {
this.handlers.set(type, []);
}
this.handlers.get(type).push(handler);
}
/**
* Removes a message handler
*/
unregisterHandler(type, handler) {
const handlers = this.handlers.get(type);
if (handlers) {
const index = handlers.indexOf(handler);
if (index > -1) {
handlers.splice(index, 1);
}
}
}
/**
* Processes an incoming message
*/
async processMessage(message, agentIdentity, sendMessage) {
const context = {
agentIdentity,
sendMessage,
getAgent: (did) => this.agentManager.getAgent(did),
validateCredential: async (credential) => this.delegationManager.validateDelegation(credential)
};
// Log incoming message
await this.activityLogger.logActivity((0, activity_logger_1.createActivity)(types_2.ActivityType.COMMUNICATION, {
agentDID: agentIdentity.did,
parentDID: agentIdentity.parentDID,
serviceDID: 'internal',
status: types_2.ActivityStatus.SUCCESS,
scopes: [],
details: {
messageType: message.type,
messageId: message.id,
from: message.from,
direction: 'incoming'
}
}));
// Try default handler first
const defaultHandler = this.defaultHandlers.get(message.type);
if (defaultHandler) {
try {
const response = await defaultHandler(message, context);
if (response) {
return response;
}
}
catch (error) {
console.error(`Default handler error for ${message.type}:`, error);
return message_protocol_1.MessageProtocol.createErrorResponse(message, `Handler error: ${error instanceof Error ? error.message : 'Unknown error'}`, agentIdentity.did);
}
}
// Try custom handlers
const handlers = this.handlers.get(message.type) || [];
for (const handler of handlers) {
try {
const response = await handler(message, context);
if (response) {
return response;
}
}
catch (error) {
console.error(`Custom handler error for ${message.type}:`, error);
}
}
// No handler found
return message_protocol_1.MessageProtocol.createErrorResponse(message, `No handler found for message type: ${message.type}`, agentIdentity.did);
}
/**
* Registers default handlers for standard message types
*/
registerDefaultHandlers() {
this.defaultHandlers.set(types_1.AgentMessageType.DELEGATION_REQUEST, this.handleDelegationRequest.bind(this));
this.defaultHandlers.set(types_1.AgentMessageType.QUERY_STATUS, this.handleStatusQuery.bind(this));
this.defaultHandlers.set(types_1.AgentMessageType.PING, this.handlePing.bind(this));
this.defaultHandlers.set(types_1.AgentMessageType.ACK, this.handleAck.bind(this));
this.defaultHandlers.set(types_1.AgentMessageType.ERROR, this.handleError.bind(this));
}
/**
* Handles delegation requests
*/
async handleDelegationRequest(message, context) {
const { agentIdentity, sendMessage } = context;
const { requestedScopes, serviceDID, duration, purpose } = message.payload;
try {
// Check if this agent can delegate
if (!agentIdentity.canDelegate) {
return message_protocol_1.MessageProtocol.createResponse(message, types_1.AgentMessageType.DELEGATION_DENY, {
reason: 'Agent is not authorized to delegate',
violations: ['delegation_not_allowed']
}, agentIdentity.did);
}
// Evaluate delegation policy
const policyResult = await this.policyEngine.evaluatePolicy({
parentAgent: agentIdentity,
requestedScopes,
serviceDID,
metadata: { purpose, requestedDuration: duration }
});
if (!policyResult.allowed) {
return message_protocol_1.MessageProtocol.createResponse(message, types_1.AgentMessageType.DELEGATION_DENY, {
reason: 'Policy evaluation failed',
violations: policyResult.violations,
suggestedScopes: this.getSuggestedScopes(requestedScopes, agentIdentity)
}, agentIdentity.did);
}
// Create sub-agent
const subAgent = await this.agentManager.createSubAgent(agentIdentity.did, {
name: `Sub-agent for ${message.from}`,
description: `Delegated agent with purpose: ${purpose || 'Not specified'}`,
parentAgentDID: agentIdentity.did,
requestedScopes
});
// Create delegation credential
const expiresAt = duration
? new Date(Date.now() + duration)
: this.policyEngine.calculateExpiration(policyResult.policy, new Date(Date.now() + 24 * 60 * 60 * 1000));
const grant = {
serviceDID: serviceDID || 'default',
scopes: this.agentManager.reduceScopesForDelegation(await this.getAgentScopes(agentIdentity), requestedScopes, policyResult.policy?.scopeReduction),
expiresAt
};
const metadata = {
delegationDepth: agentIdentity.delegationDepth + 1,
maxDelegationDepth: agentIdentity.maxDelegationDepth,
canDelegate: grant.scopes.length > 0 && agentIdentity.canDelegate
};
const credential = await this.delegationManager.createDelegationCredential(agentIdentity.did, agentIdentity.keyPair, subAgent.did, subAgent.name, grant, metadata);
this.agentManager.addDelegationCredential(subAgent.did, credential);
// Log successful delegation
await this.activityLogger.logActivity((0, activity_logger_1.createActivity)(types_2.ActivityType.DELEGATION, {
agentDID: agentIdentity.did,
parentDID: agentIdentity.parentDID,
serviceDID: serviceDID || 'default',
status: types_2.ActivityStatus.SUCCESS,
scopes: grant.scopes,
details: {
subAgentDID: subAgent.did,
requestingAgent: message.from,
purpose,
grantedScopes: grant.scopes,
expiresAt: expiresAt.toISOString()
}
}));
return message_protocol_1.MessageProtocol.createResponse(message, types_1.AgentMessageType.DELEGATION_GRANT, {
credential,
grantedScopes: grant.scopes,
expiresAt,
limitations: policyResult.appliedConstraints
}, agentIdentity.did);
}
catch (error) {
// Log failed delegation
await this.activityLogger.logActivity((0, activity_logger_1.createActivity)(types_2.ActivityType.DELEGATION, {
agentDID: agentIdentity.did,
parentDID: agentIdentity.parentDID,
serviceDID: serviceDID || 'default',
status: types_2.ActivityStatus.FAILED,
scopes: requestedScopes,
details: {
requestingAgent: message.from,
error: error instanceof Error ? error.message : 'Unknown error',
purpose
}
}));
return message_protocol_1.MessageProtocol.createResponse(message, types_1.AgentMessageType.DELEGATION_DENY, {
reason: 'Internal error processing delegation request',
violations: ['internal_error']
}, agentIdentity.did);
}
}
/**
* Handles status queries
*/
async handleStatusQuery(message, context) {
const { agentIdentity } = context;
const { includeChain, includeScopes, includeMetrics } = message.payload;
const payload = {
status: 'active',
delegationDepth: agentIdentity.delegationDepth,
remainingDepth: this.agentManager.validateDelegationDepth(agentIdentity.did)
? (agentIdentity.maxDelegationDepth || 3) - agentIdentity.delegationDepth
: 0
};
if (includeScopes) {
payload.scopes = await this.getAgentScopes(agentIdentity);
}
if (includeMetrics) {
payload.metrics = await this.getAgentMetrics(agentIdentity);
}
return message_protocol_1.MessageProtocol.createResponse(message, types_1.AgentMessageType.RESPONSE_STATUS, payload, agentIdentity.did);
}
/**
* Handles ping messages
*/
async handlePing(message, context) {
return message_protocol_1.MessageProtocol.createResponse(message, types_1.AgentMessageType.PONG, {
timestamp: new Date(),
agentStatus: 'active'
}, context.agentIdentity.did);
}
/**
* Handles acknowledgment messages
*/
async handleAck(message, context) {
// Log acknowledgment received
await this.activityLogger.logActivity((0, activity_logger_1.createActivity)(types_2.ActivityType.COMMUNICATION, {
agentDID: context.agentIdentity.did,
parentDID: context.agentIdentity.parentDID,
serviceDID: 'internal',
status: types_2.ActivityStatus.SUCCESS,
scopes: [],
details: {
messageType: 'ack_received',
originalMessageId: message.payload.originalMessageId,
from: message.from
}
}));
}
/**
* Handles error messages
*/
async handleError(message, context) {
// Log error received
await this.activityLogger.logActivity((0, activity_logger_1.createActivity)(types_2.ActivityType.COMMUNICATION, {
agentDID: context.agentIdentity.did,
parentDID: context.agentIdentity.parentDID,
serviceDID: 'internal',
status: types_2.ActivityStatus.FAILED,
scopes: [],
details: {
messageType: 'error_received',
error: message.payload.error,
originalMessageId: message.payload.originalMessageId,
from: message.from
}
}));
}
// Helper methods
async getAgentScopes(agent) {
const credentials = this.agentManager.getDelegationCredentials(agent.did);
const allScopes = new Set();
credentials.forEach(cred => {
cred.credentialSubject.scopes.forEach(scope => allScopes.add(scope));
});
return Array.from(allScopes);
}
async getAgentMetrics(agent) {
// This would typically query actual metrics from storage
// For now, return mock data
return {
subAgentsCreated: 0,
delegationsGranted: 0,
delegationsDenied: 0,
lastActivity: new Date()
};
}
getSuggestedScopes(requestedScopes, agent) {
// This would implement logic to suggest alternative scopes
// For now, return empty array
return [];
}
}
exports.MessageHandlerRegistry = MessageHandlerRegistry;
//# sourceMappingURL=message-handler.js.map