UNPKG

anon-identity

Version:

Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure

243 lines 8.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ScopeRegistry = void 0; class ScopeRegistry { constructor() { this.scopes = new Map(); this.categories = new Set(['profile', 'data', 'actions', 'admin', 'analytics']); this.initializeDefaultScopes(); } static getInstance() { if (!ScopeRegistry.instance) { ScopeRegistry.instance = new ScopeRegistry(); } return ScopeRegistry.instance; } initializeDefaultScopes() { // Profile scopes this.registerScope({ id: 'read:profile:basic', name: 'Read Basic Profile', description: 'Read basic profile information including name and public identifiers', category: 'profile', riskLevel: 'low' }); this.registerScope({ id: 'read:profile:full', name: 'Read Full Profile', description: 'Read complete profile information including sensitive data', category: 'profile', riskLevel: 'medium', dependencies: ['read:profile:basic'] }); this.registerScope({ id: 'write:profile:basic', name: 'Update Basic Profile', description: 'Update basic profile information', category: 'profile', riskLevel: 'medium' }); // Data scopes this.registerScope({ id: 'read:data:own', name: 'Read Own Data', description: 'Read data created by this agent', category: 'data', riskLevel: 'low' }); this.registerScope({ id: 'read:data:all', name: 'Read All Data', description: 'Read all user data regardless of creator', category: 'data', riskLevel: 'medium' }); this.registerScope({ id: 'write:data:create', name: 'Create Data', description: 'Create new data entries', category: 'data', riskLevel: 'medium' }); this.registerScope({ id: 'write:data:update:own', name: 'Update Own Data', description: 'Update data created by this agent', category: 'data', riskLevel: 'medium', dependencies: ['read:data:own'] }); this.registerScope({ id: 'delete:data:own', name: 'Delete Own Data', description: 'Delete data created by this agent', category: 'data', riskLevel: 'medium', dependencies: ['read:data:own'] }); // Action scopes this.registerScope({ id: 'execute:transactions:read', name: 'View Transactions', description: 'View transaction history and details', category: 'actions', riskLevel: 'low' }); this.registerScope({ id: 'execute:transactions:create', name: 'Create Transactions', description: 'Create new transactions', category: 'actions', riskLevel: 'high' }); this.registerScope({ id: 'execute:payments:limit:100', name: 'Limited Payments', description: 'Execute payments up to $100', category: 'actions', riskLevel: 'high', dependencies: ['execute:transactions:create'] }); // Admin scopes this.registerScope({ id: 'admin:agents:read', name: 'View Other Agents', description: 'View information about other agents', category: 'admin', riskLevel: 'low' }); this.registerScope({ id: 'admin:agents:manage', name: 'Manage Agents', description: 'Create, update, or delete other agents', category: 'admin', riskLevel: 'high', dependencies: ['admin:agents:read'] }); // Analytics scopes this.registerScope({ id: 'analytics:read:aggregate', name: 'Read Aggregate Analytics', description: 'Access aggregated analytics data', category: 'analytics', riskLevel: 'low' }); this.registerScope({ id: 'analytics:read:detailed', name: 'Read Detailed Analytics', description: 'Access detailed analytics including individual events', category: 'analytics', riskLevel: 'medium', dependencies: ['analytics:read:aggregate'] }); } registerScope(scope) { if (!this.categories.has(scope.category)) { throw new Error(`Invalid category: ${scope.category}`); } // Validate scope ID format if (!this.isValidScopeId(scope.id)) { throw new Error(`Invalid scope ID format: ${scope.id}`); } // Check dependencies exist if (scope.dependencies) { for (const dep of scope.dependencies) { if (!this.scopes.has(dep)) { throw new Error(`Dependency scope not found: ${dep}`); } } } this.scopes.set(scope.id, scope); } getScope(scopeId) { return this.scopes.get(scopeId); } getAllScopes() { return Array.from(this.scopes.values()); } getScopesByCategory(category) { return this.getAllScopes().filter(scope => scope.category === category); } getScopesByRiskLevel(riskLevel) { return this.getAllScopes().filter(scope => scope.riskLevel === riskLevel); } validateScopes(scopeIds) { const errors = []; const validScopes = new Set(); for (const scopeId of scopeIds) { const scope = this.scopes.get(scopeId); if (!scope) { errors.push(`Unknown scope: ${scopeId}`); continue; } validScopes.add(scopeId); // Check if dependencies are included if (scope.dependencies) { for (const dep of scope.dependencies) { if (!scopeIds.includes(dep)) { errors.push(`Scope ${scopeId} requires dependency: ${dep}`); } } } } return { valid: errors.length === 0, errors }; } getRequiredScopes(scopeIds) { const required = new Set(); const toProcess = [...scopeIds]; while (toProcess.length > 0) { const scopeId = toProcess.pop(); if (required.has(scopeId)) continue; const scope = this.scopes.get(scopeId); if (!scope) continue; required.add(scopeId); if (scope.dependencies) { toProcess.push(...scope.dependencies); } } return Array.from(required); } isValidScopeId(scopeId) { // Format: action:resource[:constraint[:value]] const parts = scopeId.split(':'); if (parts.length < 2 || parts.length > 4) return false; // All parts should be non-empty and contain only allowed characters const validPartRegex = /^[a-z0-9]+$/; return parts.every(part => validPartRegex.test(part)); } addCategory(category) { this.categories.add(category); } getCategories() { return Array.from(this.categories); } exportScopeDefinitions() { const result = {}; this.scopes.forEach((scope, id) => { result[id] = scope; }); return result; } importScopeDefinitions(definitions) { // First pass: register all scopes without dependencies for (const [id, scope] of Object.entries(definitions)) { if (!scope.dependencies || scope.dependencies.length === 0) { this.registerScope({ ...scope, id }); } } // Second pass: register scopes with dependencies for (const [id, scope] of Object.entries(definitions)) { if (scope.dependencies && scope.dependencies.length > 0) { this.registerScope({ ...scope, id }); } } } } exports.ScopeRegistry = ScopeRegistry; //# sourceMappingURL=scope-registry.js.map