/**
 * Role model for the Users / access-control subsystem.
 *
 * The database enum (`UserRole`) carries six values for backward compatibility:
 * the four product-facing roles `OWNER`, `ADMIN`, `EDITOR`, `VIEWER` plus the
 * two legacy values `AUTHOR` and `CLIENT` that predate this subsystem. The admin
 * UI only ever speaks in the four product roles, so this module is the single
 * source of truth for:
 *
 *   - mapping any stored role to a product-facing display label,
 *   - mapping a display-label filter back to the enum values it covers,
 *   - which roles may be *assigned* to new/updated users,
 *   - a privilege rank used by protection checks (last-owner, self-demotion),
 *   - the permission groups each role grants.
 *
 * Everything here is pure and dependency-free so it can be unit-tested in
 * isolation and imported from the lightweight `@actuate-media/cms-core/roles`
 * subpath without pulling the full barrel.
 */
/** Roles offered in the invite modal and role dropdowns, in privilege order. */
export const ASSIGNABLE_ROLES = ['OWNER', 'ADMIN', 'EDITOR', 'VIEWER'];
/** All product-facing display roles, used for the filter pills. */
export const DISPLAY_ROLES = ['Owner', 'Admin', 'Editor', 'Viewer'];
const ENUM_TO_DISPLAY = {
    OWNER: 'Owner',
    ADMIN: 'Admin',
    EDITOR: 'Editor',
    AUTHOR: 'Editor',
    CLIENT: 'Viewer',
    VIEWER: 'Viewer',
};
const DISPLAY_TO_ENUMS = {
    Owner: ['OWNER'],
    Admin: ['ADMIN'],
    Editor: ['EDITOR', 'AUTHOR'],
    Viewer: ['VIEWER', 'CLIENT'],
};
/**
 * Privilege rank — higher is more privileged. Used to enforce "you cannot act on
 * someone more privileged than you" and last-owner / self-demotion protections.
 * Legacy roles rank with their display equivalent.
 */
export const ROLE_RANK = {
    OWNER: 100,
    ADMIN: 80,
    EDITOR: 40,
    AUTHOR: 40,
    VIEWER: 10,
    CLIENT: 10,
};
function normalizeEnum(role) {
    if (!role)
        return null;
    const upper = role.trim().toUpperCase();
    return upper in ENUM_TO_DISPLAY ? upper : null;
}
/** Map any stored role (incl. legacy) to its product-facing display label. */
export function toDisplayRole(role) {
    const e = normalizeEnum(role);
    return e ? ENUM_TO_DISPLAY[e] : 'Viewer';
}
/** Validate + normalize a role coming from the UI for assignment. */
export function normalizeAssignableRole(role) {
    const e = normalizeEnum(role);
    return e && ASSIGNABLE_ROLES.includes(e) ? e : null;
}
/**
 * The enum values a display-role filter covers. Returns `null` for "all" or an
 * unrecognized label so callers can skip filtering.
 */
export function enumRolesForDisplay(display) {
    if (!display || display.toLowerCase() === 'all')
        return null;
    const key = DISPLAY_ROLES.find((r) => r.toLowerCase() === display.trim().toLowerCase());
    return key ? DISPLAY_TO_ENUMS[key] : null;
}
export function isOwnerRole(role) {
    return normalizeEnum(role) === 'OWNER';
}
/** Rank of a role (0 for unknown). */
export function roleRank(role) {
    const e = normalizeEnum(role);
    return e ? ROLE_RANK[e] : 0;
}
// ---------------------------------------------------------------------------
// Permission groups
// ---------------------------------------------------------------------------
/** Every permission scope recognised by the system. */
export const ALL_PERMISSIONS = [
    'dashboard.view',
    'content.view',
    'content.create',
    'content.update',
    'content.publish',
    'content.delete',
    'pages.manage',
    'posts.manage',
    'media.manage',
    'forms.manage',
    'seo.manage',
    'redirects.manage',
    'scripts.manage',
    'users.view',
    'users.invite',
    'users.update',
    'users.update_role',
    'users.remove',
    'users.suspend',
    'users.reset_password',
    'users.reset_mfa',
    'sessions.view',
    'sessions.revoke',
    'api_keys.manage',
    'settings.manage',
    'security.manage',
    'audit.view',
    'billing.manage',
    'workspace.delete',
    'workspace.owner_actions',
];
const CONTENT_PERMISSIONS = [
    'dashboard.view',
    'content.view',
    'content.create',
    'content.update',
    'content.publish',
    'content.delete',
    'pages.manage',
    'posts.manage',
    'media.manage',
    'forms.manage',
    'seo.manage',
    'redirects.manage',
];
// Admin gets everything except the Owner-only billing/workspace/owner actions.
const OWNER_ONLY = ['billing.manage', 'workspace.delete', 'workspace.owner_actions'];
const ADMIN_PERMISSIONS = ALL_PERMISSIONS.filter((p) => !OWNER_ONLY.includes(p));
/** Effective permissions granted by a role. */
export function permissionsForRole(role) {
    switch (normalizeEnum(role)) {
        case 'OWNER':
            return [...ALL_PERMISSIONS];
        case 'ADMIN':
            return ADMIN_PERMISSIONS;
        case 'EDITOR':
        case 'AUTHOR':
            return [...CONTENT_PERMISSIONS];
        case 'VIEWER':
        case 'CLIENT':
            return ['dashboard.view', 'content.view'];
        default:
            return [];
    }
}
/** Whether a role grants a specific permission. */
export function roleHasPermission(role, permission) {
    return permissionsForRole(role).includes(permission);
}
//# sourceMappingURL=roles.js.map