import type { SessionPrincipal } from './auth' // Capability names, mirrored from internal/platform/security. Only the ones the interface actually // gates on are listed: an unused constant here would imply a permission the UI respects when it does not. export const CAP = { candidateWrite: 'candidate.write', requirementEdit: 'requirement.write', exportRun: 'export.run', deskReassign: 'desk.reassign', userInvite: 'user.invite', userRoleChange: 'user.role.change', userDisable: 'user.disable', orgSettings: 'org.settings.write', auditRead: 'audit.read', privacyErase: 'privacy.erase', } as const // can reports whether the signed in user holds a capability. // // Fails closed: no session, or a session from a server that does not send the list, grants nothing. That // is the safe direction, and it means an older client against a newer server simply offers less rather // than offering something that will 403. export function can(principal: SessionPrincipal | null, cap: string): boolean { return !!principal?.capabilities?.includes(cap) } // Tool names, mirrored from internal/platform/security. The vocabulary is closed on both sides. export const TOOL = { missionmatch: 'missionmatch', screenmatch: 'screenmatch', slatematch: 'slatematch', recruitmatch: 'recruitmatch', } as const // hasTool reports whether the signed in user was granted a product. // // Fails closed for the same reason can() does: no session, or a session from a server that does not send // the list, shows nothing. An older client against a newer server offers less rather than offering a tool // whose every endpoint will 404. export function hasTool(principal: SessionPrincipal | null, tool: string): boolean { return !!principal?.tools?.includes(tool) }