import type { UserRole } from "../env.js"; /** Foundation + forward-looking actions used by the RBAC matrix. */ export const RBAC_ACTIONS = [ "read:me", "read:invoices", "write:invoices", "approve:invoices", "admin:settings", ] as const; export type RbacAction = (typeof RBAC_ACTIONS)[number]; const MATRIX: Readonly>> = { admin: new Set(RBAC_ACTIONS), ap_processor: new Set(["read:me", "read:invoices", "write:invoices"]), approver: new Set(["read:me", "read:invoices", "approve:invoices"]), viewer: new Set(["read:me", "read:invoices"]), }; export function can(role: UserRole, action: RbacAction): boolean { return MATRIX[role].has(action); } export function requireRole(role: UserRole, action: RbacAction): void { if (!can(role, action)) { throw new RbacDeniedError(role, action); } } export class RbacDeniedError extends Error { readonly status = 403 as const; constructor( readonly role: UserRole, readonly action: RbacAction, ) { super(`Role ${role} is not allowed to ${action}.`); this.name = "RbacDeniedError"; } }