anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
171 lines • 7.45 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentIdentityManager = void 0;
const crypto_1 = require("../core/crypto");
const did_1 = require("../core/did");
class AgentIdentityManager {
constructor() {
this.agents = new Map();
this.accessGrants = new Map();
this.delegationCredentials = new Map();
}
async createAgent(parentDID, config) {
// Generate new key pair for agent
const keyPair = await (0, crypto_1.generateKeyPair)();
// Create agent DID
const didObject = did_1.DIDService.createDIDKey(keyPair.publicKey);
const agentDID = didObject.id;
// Determine if parent is an agent (for delegation depth calculation)
const parentAgent = this.agents.get(parentDID);
const delegationDepth = parentAgent ? parentAgent.delegationDepth + 1 : 0;
// Create agent identity
const agent = {
did: agentDID,
name: config.name,
description: config.description,
parentDID,
createdAt: new Date(),
keyPair,
maxDelegationDepth: config.maxDelegationDepth ?? 3, // Default max depth of 3
delegationDepth,
canDelegate: config.canDelegate ?? true,
delegatedBy: parentAgent ? parentDID : undefined
};
// Store agent
this.agents.set(agentDID, agent);
this.accessGrants.set(agentDID, []);
this.delegationCredentials.set(agentDID, []);
return agent;
}
async createSubAgent(parentAgentDID, config) {
const parentAgent = this.agents.get(parentAgentDID);
if (!parentAgent) {
throw new Error(`Parent agent ${parentAgentDID} not found`);
}
if (!parentAgent.canDelegate) {
throw new Error(`Parent agent ${parentAgentDID} cannot delegate`);
}
// Check delegation depth
if (parentAgent.delegationDepth >= (parentAgent.maxDelegationDepth ?? 3)) {
throw new Error(`Maximum delegation depth (${parentAgent.maxDelegationDepth}) reached`);
}
// Apply delegation options
const delegationOptions = config.delegationOptions || {};
const maxDepth = Math.min(delegationOptions.maxDepth ?? parentAgent.maxDelegationDepth ?? 3, (parentAgent.maxDelegationDepth ?? 3) - parentAgent.delegationDepth - 1);
// Create the sub-agent with appropriate config
const subAgentConfig = {
name: config.name,
description: config.description,
maxValidityPeriod: config.maxValidityPeriod,
maxDelegationDepth: maxDepth,
canDelegate: config.canDelegate ?? true
};
return this.createAgent(parentAgentDID, subAgentConfig);
}
reduceScopesForDelegation(parentScopes, requestedScopes, policy) {
const strategy = policy?.strategy || 'intersection';
switch (strategy) {
case 'intersection':
// Only allow scopes that both parent has and child requests
return requestedScopes.filter(scope => parentScopes.includes(scope));
case 'subset':
// Ensure all requested scopes are in parent's scope set
const isSubset = requestedScopes.every(scope => parentScopes.includes(scope));
return isSubset ? requestedScopes : [];
case 'custom':
if (policy?.customReducer) {
return policy.customReducer(parentScopes, requestedScopes);
}
// Fall back to intersection if no custom reducer
return requestedScopes.filter(scope => parentScopes.includes(scope));
default:
return requestedScopes.filter(scope => parentScopes.includes(scope));
}
}
validateDelegationDepth(agentDID) {
const agent = this.agents.get(agentDID);
if (!agent)
return false;
return agent.delegationDepth < (agent.maxDelegationDepth ?? 3);
}
getAgent(agentDID) {
return this.agents.get(agentDID);
}
listAgents(parentDID) {
return Array.from(this.agents.values()).filter(agent => agent.parentDID === parentDID);
}
deleteAgent(agentDID) {
const agent = this.agents.get(agentDID);
if (!agent)
return false;
this.agents.delete(agentDID);
this.accessGrants.delete(agentDID);
this.delegationCredentials.delete(agentDID);
return true;
}
getAllAgents() {
return Array.from(this.agents.values());
}
addAccessGrant(agentDID, grant) {
const grants = this.accessGrants.get(agentDID) || [];
grants.push(grant);
this.accessGrants.set(agentDID, grants);
}
getAccessGrants(agentDID) {
return this.accessGrants.get(agentDID) || [];
}
hasServiceAccess(agentDID, serviceDID) {
const grants = this.getAccessGrants(agentDID);
return grants.some(grant => grant.serviceDID === serviceDID &&
grant.expiresAt > new Date());
}
revokeServiceAccess(agentDID, serviceDID) {
const grants = this.accessGrants.get(agentDID);
if (!grants)
return false;
const filteredGrants = grants.filter(grant => grant.serviceDID !== serviceDID);
this.accessGrants.set(agentDID, filteredGrants);
// Also remove delegation credentials for this service
const credentials = this.delegationCredentials.get(agentDID) || [];
const filteredCredentials = credentials.filter(cred => !cred.credentialSubject.services[serviceDID]);
this.delegationCredentials.set(agentDID, filteredCredentials);
return grants.length !== filteredGrants.length;
}
addDelegationCredential(agentDID, credential) {
const credentials = this.delegationCredentials.get(agentDID) || [];
credentials.push(credential);
this.delegationCredentials.set(agentDID, credentials);
}
getDelegationCredentials(agentDID) {
return this.delegationCredentials.get(agentDID) || [];
}
async createPresentation(agentDID, options) {
const agent = this.agents.get(agentDID);
if (!agent)
return null;
// Find relevant delegation credential
const credentials = this.getDelegationCredentials(agentDID);
const relevantCredential = credentials.find(cred => cred.credentialSubject.services[options.serviceDID] &&
new Date(cred.expirationDate) > new Date());
if (!relevantCredential)
return null;
// Create presentation
const presentation = {
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiablePresentation', 'AgentPresentation'],
verifiableCredential: [relevantCredential],
proof: {
type: 'Ed25519Signature2020',
created: new Date().toISOString(),
verificationMethod: `${agentDID}#key-1`,
proofPurpose: 'authentication',
jws: 'mock-signature' // In real implementation, this would be signed
}
};
// Add holder as a custom property
presentation.holder = agentDID;
return presentation;
}
}
exports.AgentIdentityManager = AgentIdentityManager;
//# sourceMappingURL=agent-identity.js.map