anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
309 lines • 11.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DelegationDepthController = void 0;
class DelegationDepthController {
constructor(agentManager, chainValidator, config) {
this.agentManager = agentManager;
this.chainValidator = chainValidator;
this.depthCache = new Map();
this.configuration = {
globalMaxDepth: 5,
perAgentOverrides: new Map(),
depthCalculationStrategy: 'absolute',
warningThreshold: 0.8,
...config
};
}
/**
* Updates the global maximum depth
*/
setGlobalMaxDepth(depth) {
if (depth < 1 || depth > 10) {
throw new Error('Global max depth must be between 1 and 10');
}
this.configuration.globalMaxDepth = depth;
this.clearCache();
}
/**
* Sets a depth override for a specific agent
*/
setAgentDepthOverride(agentDID, maxDepth) {
if (maxDepth < 0) {
throw new Error('Agent max depth cannot be negative');
}
this.configuration.perAgentOverrides.set(agentDID, maxDepth);
this.clearCache();
}
/**
* Validates if a new delegation would exceed depth limits
*/
async validateDelegationDepth(parentAgentDID, childAgentConfig) {
const warnings = [];
const parentAgent = this.agentManager.getAgent(parentAgentDID);
if (!parentAgent) {
return {
valid: false,
currentDepth: 0,
maxAllowedDepth: 0,
remainingDepth: 0,
warnings: ['Parent agent not found']
};
}
// Calculate effective max depth for this agent
const effectiveMaxDepth = this.getEffectiveMaxDepth(parentAgent);
const currentDepth = parentAgent.delegationDepth;
const wouldBeDepth = currentDepth + 1;
// Check if delegation would exceed limits
const valid = wouldBeDepth <= effectiveMaxDepth;
const remainingDepth = Math.max(0, effectiveMaxDepth - wouldBeDepth);
// Add warnings if approaching limit
const depthPercentage = wouldBeDepth / effectiveMaxDepth;
if (depthPercentage >= this.configuration.warningThreshold) {
warnings.push(`Delegation depth reaching ${Math.round(depthPercentage * 100)}% of maximum`);
}
if (remainingDepth === 0 && valid) {
warnings.push('This will be the last possible delegation level');
}
// Dynamic depth calculation if enabled
let metadata;
if (this.configuration.depthCalculationStrategy === 'dynamic') {
const dynamicAnalysis = await this.performDynamicDepthAnalysis(parentAgent);
metadata = { dynamicAnalysis };
if (dynamicAnalysis.suggestedMaxDepth < effectiveMaxDepth) {
warnings.push(`Dynamic analysis suggests lower max depth: ${dynamicAnalysis.suggestedMaxDepth}`);
}
}
return {
valid,
currentDepth: wouldBeDepth,
maxAllowedDepth: effectiveMaxDepth,
remainingDepth,
warnings,
metadata
};
}
/**
* Gets the effective maximum depth for an agent considering all rules
*/
getEffectiveMaxDepth(agent) {
// Check for agent-specific override
const override = this.configuration.perAgentOverrides.get(agent.did);
if (override !== undefined) {
return Math.min(override, this.configuration.globalMaxDepth);
}
// Check agent's own max depth setting
if (agent.maxDelegationDepth !== undefined) {
return Math.min(agent.maxDelegationDepth, this.configuration.globalMaxDepth);
}
// Use global default
return this.configuration.globalMaxDepth;
}
/**
* Calculates the remaining delegation depth for an agent
*/
getRemainingDepth(agentDID) {
const agent = this.agentManager.getAgent(agentDID);
if (!agent)
return 0;
const effectiveMaxDepth = this.getEffectiveMaxDepth(agent);
return Math.max(0, effectiveMaxDepth - agent.delegationDepth);
}
/**
* Analyzes delegation depth across all agents
*/
async analyzeDepthDistribution() {
const allAgents = this.getAllAgents();
const depthDistribution = new Map();
const deepestChains = [];
let totalDepth = 0;
let maxDepthReached = 0;
for (const agent of allAgents) {
const depth = agent.delegationDepth;
totalDepth += depth;
maxDepthReached = Math.max(maxDepthReached, depth);
// Update distribution
depthDistribution.set(depth, (depthDistribution.get(depth) || 0) + 1);
// Track deepest chains
if (depth >= 3) {
const path = await this.buildAgentPath(agent.did);
deepestChains.push({
leafAgentDID: agent.did,
depth,
path
});
}
}
// Sort deepest chains by depth
deepestChains.sort((a, b) => b.depth - a.depth);
return {
averageDepth: allAgents.length > 0 ? totalDepth / allAgents.length : 0,
maxDepthReached,
depthDistribution,
deepestChains: deepestChains.slice(0, 10) // Top 10 deepest
};
}
/**
* Performs dynamic depth analysis to suggest optimal max depth
*/
async performDynamicDepthAnalysis(agent) {
const factors = {};
let suggestedMaxDepth = this.configuration.globalMaxDepth;
// Factor 1: Agent's scope count
const credentials = this.agentManager.getDelegationCredentials(agent.did);
const totalScopes = new Set();
credentials.forEach(cred => {
cred.credentialSubject.scopes.forEach(scope => totalScopes.add(scope));
});
factors.scopeCount = totalScopes.size;
// More scopes = potentially lower max depth
if (totalScopes.size > 10) {
suggestedMaxDepth = Math.min(suggestedMaxDepth, 3);
factors.scopeImpact = 'high scope count suggests lower depth';
}
// Factor 2: Time since creation
const ageInDays = (Date.now() - agent.createdAt.getTime()) / (1000 * 60 * 60 * 24);
factors.ageInDays = ageInDays;
// Newer agents might get more restrictive depths
if (ageInDays < 1) {
suggestedMaxDepth = Math.min(suggestedMaxDepth, 2);
factors.ageImpact = 'new agent suggests lower depth';
}
// Factor 3: Current chain complexity
try {
const rootDID = await this.findRootDID(agent.did);
if (rootDID) {
const chainResult = await this.chainValidator.validateDelegationChain(agent.did, rootDID);
if (chainResult.chain) {
factors.currentChainDepth = chainResult.chain.currentDepth;
// If already in a deep chain, limit further delegation
if (chainResult.chain.currentDepth >= 2) {
suggestedMaxDepth = Math.min(suggestedMaxDepth, chainResult.chain.currentDepth + 1);
factors.chainImpact = 'already in deep chain';
}
}
}
}
catch (error) {
factors.chainAnalysisError = error;
}
return { suggestedMaxDepth, factors };
}
/**
* Builds the path from an agent to the root
*/
async buildAgentPath(agentDID) {
const path = [agentDID];
let currentDID = agentDID;
const maxIterations = 10; // Prevent infinite loops
for (let i = 0; i < maxIterations; i++) {
const agent = this.agentManager.getAgent(currentDID);
if (!agent)
break;
path.push(agent.parentDID);
// Check if parent is also an agent
const parentAgent = this.agentManager.getAgent(agent.parentDID);
if (!parentAgent) {
// Reached a user DID
break;
}
currentDID = agent.parentDID;
}
return path.reverse();
}
/**
* Finds the root DID for an agent
*/
async findRootDID(agentDID) {
let currentDID = agentDID;
const visited = new Set();
while (true) {
if (visited.has(currentDID)) {
// Circular reference detected
return null;
}
visited.add(currentDID);
const agent = this.agentManager.getAgent(currentDID);
if (!agent) {
// Current DID is not an agent, so it might be the root user
return currentDID;
}
currentDID = agent.parentDID;
}
}
/**
* Gets all agents managed by the system
*/
getAllAgents() {
// This is a simplified implementation
// In practice, you'd need a method to get all agents
const agents = [];
// For now, return empty array
// In a real implementation, this would query all agents
return agents;
}
/**
* Clears the depth cache
*/
clearCache() {
this.depthCache.clear();
}
/**
* Enforces depth limits by preventing over-deep delegations
*/
async enforceDepthLimits() {
const violations = [];
let processed = 0;
const allAgents = this.getAllAgents();
for (const agent of allAgents) {
processed++;
const effectiveMaxDepth = this.getEffectiveMaxDepth(agent);
if (agent.delegationDepth > effectiveMaxDepth) {
violations.push({
agentDID: agent.did,
currentDepth: agent.delegationDepth,
maxAllowed: effectiveMaxDepth,
action: 'Would revoke delegation capability'
});
// In a real implementation, you might:
// - Revoke the agent's delegation capability
// - Notify administrators
// - Log the violation
}
}
return { processed, violations };
}
/**
* Exports depth configuration
*/
exportConfiguration() {
return {
globalMaxDepth: this.configuration.globalMaxDepth,
overrides: Array.from(this.configuration.perAgentOverrides.entries()).map(([agentDID, maxDepth]) => ({ agentDID, maxDepth })),
strategy: this.configuration.depthCalculationStrategy,
warningThreshold: this.configuration.warningThreshold
};
}
/**
* Imports depth configuration
*/
importConfiguration(config) {
if (config.globalMaxDepth !== undefined) {
this.setGlobalMaxDepth(config.globalMaxDepth);
}
if (config.overrides) {
this.configuration.perAgentOverrides.clear();
config.overrides.forEach(({ agentDID, maxDepth }) => {
this.setAgentDepthOverride(agentDID, maxDepth);
});
}
if (config.strategy) {
this.configuration.depthCalculationStrategy = config.strategy;
}
if (config.warningThreshold !== undefined) {
this.configuration.warningThreshold = config.warningThreshold;
}
this.clearCache();
}
}
exports.DelegationDepthController = DelegationDepthController;
//# sourceMappingURL=delegation-depth-controller.js.map