8cd5d9b248
LocalDevPorts = permissive in-service default (no testkit at runtime); decideOrThrow turns OPA deny/throw/timeout into PolicyDeniedError. Tests drive deny/timeout via testkit fakes. 12 tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
22 lines
841 B
TypeScript
22 lines
841 B
TypeScript
import { IiosPlatformPorts, PolicyDecision, PolicyDeniedError } from '@insignia/iios-contracts';
|
|
|
|
/**
|
|
* Fail-closed authorization (Bottom-Up hard gate; Critics KG-03).
|
|
*
|
|
* Calls the OPA port. The kernel proceeds ONLY on an explicit allow. A denial,
|
|
* a thrown error, or a timeout all become a PolicyDeniedError — never an
|
|
* implicit allow. Callers must let this propagate so nothing is written.
|
|
*/
|
|
export async function decideOrThrow(ports: IiosPlatformPorts, input: unknown): Promise<PolicyDecision> {
|
|
let decision: PolicyDecision;
|
|
try {
|
|
decision = await ports.opa.decide(input);
|
|
} catch (err) {
|
|
throw new PolicyDeniedError(`policy port unavailable: ${(err as Error).message}`);
|
|
}
|
|
if (!decision.allow) {
|
|
throw new PolicyDeniedError(decision.obligations[0]?.reason ?? 'policy denied');
|
|
}
|
|
return decision;
|
|
}
|