Files
openmaic/OpenMAIC/lib/server/authz/identity-enforcement.ts
2026-08-16 14:58:47 +08:00

64 lines
2.0 KiB
TypeScript

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<ResourceAuthorizationEvaluation> {
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 } : {}),
}),
};
}