UNPKG

anon-identity

Version:

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

212 lines 8.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ServiceManifestValidator = exports.ServiceManifestBuilder = void 0; const scope_registry_1 = require("./scope-registry"); class ServiceManifestBuilder { constructor(serviceDID, name, description) { this.scopeRegistry = scope_registry_1.ScopeRegistry.getInstance(); this.manifest = { serviceDID, name, description, requiredScopes: [], optionalScopes: [] }; } addRequiredScope(scopeId) { const scope = this.scopeRegistry.getScope(scopeId); if (!scope) { throw new Error(`Unknown scope: ${scopeId}`); } // Add scope with its dependencies const allRequired = this.scopeRegistry.getRequiredScopes([scopeId]); for (const reqScopeId of allRequired) { const reqScope = this.scopeRegistry.getScope(reqScopeId); if (reqScope && !this.manifest.requiredScopes.some(s => s.id === reqScopeId)) { this.manifest.requiredScopes.push(reqScope); } } return this; } addOptionalScope(scopeId) { const scope = this.scopeRegistry.getScope(scopeId); if (!scope) { throw new Error(`Unknown scope: ${scopeId}`); } if (!this.manifest.optionalScopes) { this.manifest.optionalScopes = []; } // Check if already in required scopes if (this.manifest.requiredScopes.some(s => s.id === scopeId)) { throw new Error(`Scope ${scopeId} is already required`); } // Add scope with its dependencies as optional const allRequired = this.scopeRegistry.getRequiredScopes([scopeId]); for (const optScopeId of allRequired) { const optScope = this.scopeRegistry.getScope(optScopeId); if (optScope && !this.manifest.optionalScopes.some(s => s.id === optScopeId) && !this.manifest.requiredScopes.some(s => s.id === optScopeId)) { this.manifest.optionalScopes.push(optScope); } } return this; } addCustomScope(scope, required = true) { // Register the custom scope if not already registered try { this.scopeRegistry.registerScope(scope); } catch (error) { // Scope might already be registered } if (required) { this.addRequiredScope(scope.id); } else { this.addOptionalScope(scope.id); } return this; } build() { if (this.manifest.requiredScopes.length === 0 && (!this.manifest.optionalScopes || this.manifest.optionalScopes.length === 0)) { throw new Error('Service manifest must have at least one scope'); } return { ...this.manifest }; } static createBasicReadService(serviceDID, name) { return new ServiceManifestBuilder(serviceDID, name) .addRequiredScope('read:profile:basic') .addOptionalScope('read:data:all') .build(); } static createDataManagementService(serviceDID, name) { return new ServiceManifestBuilder(serviceDID, name) .addRequiredScope('read:data:own') .addRequiredScope('write:data:create') .addOptionalScope('write:data:update:own') .addOptionalScope('delete:data:own') .build(); } static createPaymentService(serviceDID, name, limit = 100) { const builder = new ServiceManifestBuilder(serviceDID, name, 'Payment processing service'); // Add transaction read as required builder.addRequiredScope('execute:transactions:read'); // Add payment scope based on limit if (limit <= 100) { builder.addRequiredScope('execute:payments:limit:100'); } else { // Create custom scope for higher limit builder.addCustomScope({ id: `execute:payments:limit:${limit}`, name: `Execute Payments up to $${limit}`, description: `Execute payments with a maximum value of $${limit}`, category: 'actions', riskLevel: 'high', dependencies: ['execute:transactions:create'] }, true); } return builder.build(); } } exports.ServiceManifestBuilder = ServiceManifestBuilder; class ServiceManifestValidator { static validateManifest(manifest) { const errors = []; if (!manifest.serviceDID) { errors.push('Service DID is required'); } if (!manifest.name) { errors.push('Service name is required'); } if (manifest.requiredScopes.length === 0 && (!manifest.optionalScopes || manifest.optionalScopes.length === 0)) { errors.push('At least one scope is required'); } // Check for duplicate scopes const allScopes = [ ...manifest.requiredScopes, ...(manifest.optionalScopes || []) ]; const scopeIds = allScopes.map(s => s.id); const uniqueScopeIds = new Set(scopeIds); if (scopeIds.length !== uniqueScopeIds.size) { errors.push('Duplicate scopes found in manifest'); } // Validate scope definitions const registry = scope_registry_1.ScopeRegistry.getInstance(); for (const scope of allScopes) { const registeredScope = registry.getScope(scope.id); if (!registeredScope) { errors.push(`Unknown scope in manifest: ${scope.id}`); } } return { valid: errors.length === 0, errors }; } static compareManifests(manifest1, manifest2) { const scopes1 = new Map(); const scopes2 = new Map(); // Build maps [...manifest1.requiredScopes, ...(manifest1.optionalScopes || [])].forEach(s => { scopes1.set(s.id, s); }); [...manifest2.requiredScopes, ...(manifest2.optionalScopes || [])].forEach(s => { scopes2.set(s.id, s); }); const added = []; const removed = []; const changed = []; // Find added and changed scopes2.forEach((scope, id) => { if (!scopes1.has(id)) { added.push(scope); } else { const oldScope = scopes1.get(id); if (JSON.stringify(oldScope) !== JSON.stringify(scope)) { changed.push(scope); } } }); // Find removed scopes1.forEach((scope, id) => { if (!scopes2.has(id)) { removed.push(scope); } }); return { added, removed, changed }; } static generateManifestSummary(manifest) { const lines = [ `Service: ${manifest.name}`, `DID: ${manifest.serviceDID}` ]; if (manifest.description) { lines.push(`Description: ${manifest.description}`); } lines.push(''); lines.push('Required Scopes:'); manifest.requiredScopes.forEach(scope => { lines.push(` - ${scope.name} (${scope.id})`); lines.push(` ${scope.description}`); lines.push(` Risk Level: ${scope.riskLevel}`); }); if (manifest.optionalScopes && manifest.optionalScopes.length > 0) { lines.push(''); lines.push('Optional Scopes:'); manifest.optionalScopes.forEach(scope => { lines.push(` - ${scope.name} (${scope.id})`); lines.push(` ${scope.description}`); lines.push(` Risk Level: ${scope.riskLevel}`); }); } return lines.join('\n'); } } exports.ServiceManifestValidator = ServiceManifestValidator; //# sourceMappingURL=service-manifest.js.map