import { ALL_CAPABILITIES } from './capabilities'; import { DEFAULT_ROLE_CAPABILITIES } from './default-role-capabilities'; export interface PermissionOverrides { [role: string]: { grant?: string[]; revoke?: string[]; }; } /** * Resolve effective capabilities for a role, applying tenant overrides. * * 1. Start with default capabilities for the role * 2. Add any granted capabilities from overrides * 3. Remove any revoked capabilities from overrides * * Unknown capabilities in grant/revoke are silently ignored (they may * come from an older version of the overrides). */ export function resolveCapabilities( role: string, overrides?: PermissionOverrides | null, ): Set { const defaults = DEFAULT_ROLE_CAPABILITIES[role] || []; const result = new Set(defaults); if (overrides && overrides[role]) { const roleOverride = overrides[role]; if (roleOverride.grant) { for (const cap of roleOverride.grant) { if (ALL_CAPABILITIES.has(cap)) { result.add(cap); } } } if (roleOverride.revoke) { for (const cap of roleOverride.revoke) { result.delete(cap); } } } return result; } /** * Convenience: resolve to a sorted array (for API responses). */ export function resolveCapabilitiesArray( role: string, overrides?: PermissionOverrides | null, ): string[] { return Array.from(resolveCapabilities(role, overrides)).sort(); }