import { resolveRequestPrincipal, type PrincipalResolution, type RequestPrincipalResolver, } from '@/lib/server/authz/principal'; import { decideResourceAuthorization, type ResourceAuthorizationAction, type ResourceAuthorizationDecision, type ResourceOwnership, } from '@/lib/server/authz/resource-ownership'; export type IdentityEnforcementMode = 'shadow' | 'required'; /** * Identity enforcement is explicitly activated. Until a real session or * device-proof resolver is installed, the default remains shadow-compatible * so existing desktop deployments keep working. */ export function resolveIdentityEnforcementMode( raw = process.env.OPENMAIC_IDENTITY_ENFORCEMENT, ): IdentityEnforcementMode { return raw?.trim().toLowerCase() === 'required' ? 'required' : 'shadow'; } export interface ResourceAuthorizationEvaluation { readonly principal: PrincipalResolution; readonly decision: ResourceAuthorizationDecision; } export interface EvaluateResourceAuthorizationInput { readonly request: Request; readonly ownership: ResourceOwnership; readonly action: ResourceAuthorizationAction; readonly overrideCapability?: string; } export interface IdentityEvaluationDeps { readonly resolvePrincipal?: RequestPrincipalResolver; } /** Evaluate a resource request without deciding how an API should respond. */ export async function evaluateResourceAuthorization( input: EvaluateResourceAuthorizationInput, deps: IdentityEvaluationDeps = {}, ): Promise { let principal: PrincipalResolution; try { principal = await (deps.resolvePrincipal ?? resolveRequestPrincipal)(input.request); } catch { principal = { state: 'unavailable', reason: 'resolver_failed' }; } return { principal, decision: decideResourceAuthorization({ principal, ownership: input.ownership, action: input.action, ...(input.overrideCapability ? { overrideCapability: input.overrideCapability } : {}), }), }; }