anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
243 lines • 8.49 kB
JavaScript
"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