/** * Adjustable multi-level RBAC — capability catalog + factory defaults. * Browser-safe (no Node APIs). Single source for server enforce + web UI. */ import type { OperationLevel, SystemRole } from './types.js'; /** Stable capability ids used in API, policies, and UI. */ export type CapabilityId = 'dashboard.read' | 'logs.read' | 'metrics.read' | 'projects.read' | 'mail.read' | 'dns.read' | 'ssl.read' | 'backups.read' | 'updates.read' | 'services.read' | 'firewall.read' | 'validators.read' | 'docker.read' | 'approvals.view' | 'users.self' | 'projects.write' | 'mail.write' | 'db.write' | 'ssl.upload' | 'files.project' | 'approvals.respond' | 'cron.manage' | 'backups.run' | 'services.control' | 'updates.apply' | 'dns.apply' | 'ssl.issue' | 'publish.apply' | 'firewall.edit' | 'mail.apply' | 'runtime.tuning' | 'mysql.console.write' | 'validators.manage' | 'docker.manage' | 'projects.delete' | 'db.drop' | 'backups.restore' | 'firewall.flush' | 'logs.purge' | 'validators.wipe' | 'docker.wipe' | 'users.manage' | 'packages.manage' | 'users.impersonate' | 'security.policy' | 'rbac.policy' | 'settings.system' | 'network.browse' | 'network.vpn' | 'network.vnc' | 'audit.export' | 'security.api_keys.admin'; export interface CapabilityDef { id: CapabilityId; /** Danger band — used for maxLevel filter + UI grouping */ band: OperationLevel; /** i18n key under rbac.cap.* */ labelKey: string; } /** Bump when factory grants change so dirty merge can reason about versions. */ export declare const RBAC_DEFAULTS_VERSION = 1; export declare const OPERATION_LEVELS: OperationLevel[]; export declare const SYSTEM_ROLES: SystemRole[]; /** Full catalog — add new capabilities here first. */ export declare const CAPABILITY_CATALOG: readonly CapabilityDef[]; export declare function isCapabilityId(value: string): value is CapabilityId; export declare function getCapabilityDef(id: CapabilityId): CapabilityDef | undefined; export declare function capabilitiesInBand(band: OperationLevel): CapabilityId[]; export declare function capabilitiesUpToLevel(maxLevel: OperationLevel): CapabilityId[]; export declare function levelRank(level: OperationLevel): number; export declare function compareLevels(a: OperationLevel, b: OperationLevel): number; /** Persisted / API shape for one role's policy */ export interface RolePolicy { maxLevel: OperationLevel; /** Explicit grants (after maxLevel filter on write) */ capabilities: CapabilityId[]; /** When set, diverged from factory for this defaultsVersion */ defaultsVersion?: number; } /** Factory max level per role */ export declare const ROLE_FACTORY_MAX_LEVEL: Record; /** Code-level factory defaults — restore target */ export declare function factoryRolePolicy(role: SystemRole): RolePolicy; export declare function factoryRolePolicies(): Record; /** Normalize + filter caps by maxLevel; drop unknown ids */ export declare function normalizeRolePolicy(input: { maxLevel?: OperationLevel; capabilities?: string[]; }): RolePolicy; /** Whether policy matches factory for role (order-independent) */ export declare function isFactoryPolicy(role: SystemRole, policy: RolePolicy): boolean; /** * Resolve stored policy against current factory. * - missing / exact factory / pure subset of factory (same maxLevel) → full factory, not dirty * (auto-picks new catalog caps after defaultsVersion bumps without re-adding intentional extras) * - otherwise keep stored list as dirty custom policy */ export declare function resolveRolePolicy(role: SystemRole, stored: RolePolicy | null | undefined): { policy: RolePolicy; dirty: boolean; }; /** * Critical privilege set that must never be fully removed from the panel * (at least one non-suspended holder must keep these). */ export declare const CRITICAL_PRIVILEGE_CAPS: readonly CapabilityId[]; /** True if set contains the minimum privilege pair to recover the panel. */ export declare function hasCriticalPrivilege(caps: readonly CapabilityId[]): boolean; /** * Effective capabilities for an actor. * roles → union of (rolePolicy ?? factory), then +grants −revokes. * * **Hard guarantee:** any principal with the `admin` system role always keeps * the full admin factory pack (cannot be stripped by dirty role policy or * per-user revokes). This ensures at least panel admins stay fully open. */ export declare function computeEffectiveCapabilities(input: { roles: SystemRole[]; /** Custom policies; missing role → factory */ rolePolicies?: Partial>; grants?: CapabilityId[] | string[]; revokes?: CapabilityId[] | string[]; }): CapabilityId[]; export declare function hasCapability(effective: readonly CapabilityId[] | Set, cap: CapabilityId): boolean; /** Batch: all caps in band for toggle-all UI */ export declare function applyBandToCapabilities(current: CapabilityId[], band: OperationLevel, enabled: boolean, maxLevel: OperationLevel): CapabilityId[]; //# sourceMappingURL=capabilities.d.ts.map