Skip to main content
[AVAILABLE]. packages/policy, 72 tests. CLAIMS.md 2.2/2.3.

Purpose

Evaluates a PolicySignals object against a Policy’s ordered rules and returns exactly one Decision. See Policies and the decision for the concept, this page is the export reference.
PolicyEngine.evaluate() alone does not check Policy.boundSignals — that binding is enforced one layer up, by SignalIntentBinder, which RuntimeEngine (@parmana/runtime) invokes immediately before calling PolicyEngine.evaluate(). Calling PolicyEngine.evaluate() directly, as the minimal example below does, bypasses signal/intent binding entirely — verified by actually running it. See Policies and the decision for why this split exists.

Install

Key exports

Engine, [AVAILABLE]

Routing and loading, [AVAILABLE]

Validation, [AVAILABLE]

boundSignals coverage is fail-closed, not advisory. A rule can decide on a fact (e.g. amount) that isn’t declared in boundSignals, silently forfeiting SignalIntentBinder’s protection for that fact. PolicyValidator.validate() throws PolicyValidationError for any such fact unless it’s explicitly acknowledged in unboundSignalReasons with a reason. A fact with no genuine Intent-side equivalent (vendorVerified, riskScore) still doesn’t belong in boundSignals; it belongs in unboundSignalReasons instead, with a reason.

Types

Policy (including its optional boundSignals: Record<string, string> and unboundSignalReasons: Record<string, string> fields — see the note below), PolicyRule, PolicyCondition, PolicyRuleOutcome, PolicyInput, PolicySignals, PolicyDecision, PolicyAction (enum: APPROVE, REJECT), PolicyOutcome (enum: APPROVE, REJECT), SignalIntentBindingViolation ({ signalKey, intentPath, signalValue, intentValue }).
Both enums previously also had a third value, REQUIRE_OVERRIDE: defined but never used by any real policy, and DecisionBuilder collapsed it to the same DecisionOutcome.REJECTED as an ordinary REJECT in any case. Removed as dead code.

Minimal example

Full runnable version: Write your first policy.

Next

Write your first policy

Write a policy and confirm both the approve and reject paths.

@parmana/runtime

Where PolicyEngine is actually invoked as part of executing a transaction.