Policy SDK
@nexart/policy declares producer-side predicates over captured execution fields as data, never as executable code, and can be sealed into a CER as producer-declared evidence.
Overview
@nexart/policy 0.1.0 is a producer-side, standalone package. It lets a producer declare a set of declarative predicates ("rules") that are evaluated against a captured execution's fields. A policy MUST be data: it is a plain JSON-serializable structure. A policy MUST NOT contain executable code. This keeps a policy inspectable, hashable, and diffable without running untrusted logic.
A resulting evaluation MAY later be sealed into an AI Execution CER's policyEvaluation field. See Versions for how the package version relates to other axes.
The Closed v1 Type System
Policy SDK v1 defines a closed, non-extensible set of types:
- FieldType:
'number' | 'boolean' | 'string' | 'timestamp' | 'uuid' | 'identifier' | 'enum' - Operator:
eq, neq, lt, lte, gt, gte, between, exists, in, matches, before, after, within-window - Combinator:
'all' | 'any' - Verdict:
'PASS' | 'FAIL' | 'ERROR'
FAIL means the predicate was evaluated and did not hold. A verdict of ERROR means the rule could not be evaluated at all (for example, a field type mismatch or an unknown operator). Consumers of a PolicyEvaluation MUST treat these as distinct outcomes.CapturedExecutionSchema, Policy, PolicyRule
A CapturedExecutionSchema declares the field names and FieldType of each field that may be referenced by a policy. A Policy is a combinator ('all' | 'any') applied to a list of PolicyRule entries. Each PolicyRule names a field, an operator valid for that field's type, and any operator-specific arguments (for example, a literal for eq, bounds for between, or a safe pattern for matches).
The Operator / Type Matrix
Not every operator is valid for every field type. OPERATOR_MATRIX is the exported, authoritative table of which Operator is valid for which FieldType. Use isOperatorValidForType(type, operator) to check a single combination, isKnownOperator to check the operator is one of the closed set in KNOWN_OPERATORS, and isSupportedCombinator to validate 'all' | 'any' against SUPPORTED_COMBINATORS. An invalid operator/type pairing MUST produce an ERROR verdict during evaluation, or a PolicyValidationError during validatePolicy.
Core Functions
evaluatePolicy(schema, policy, execution): evaluates a Policy against a captured execution and returns a PolicyEvaluation with per-rule verdicts and an overall verdict.validateSchema(schema): validates a CapturedExecutionSchema structurally.validatePolicy(policy): validates a Policy against the closed operator/type matrix and combinator set.hashSchema(schema)/hashPolicy(policy): deterministic hashes over the canonicalized schema or policy, built oncanonicalize,canonicalJson, andhashCanonical.
Deterministic, Clock-Independent within-window
The within-window operator compares timestamp fields captured in the execution against each other. It does NOT read the wall clock at evaluation time. This makes evaluation deterministic: re-running evaluatePolicy on the same schema, policy, and captured execution always produces the same verdicts, regardless of when evaluation happens. isValidTimestamp and timestampToMs are exported to validate and normalize timestamp fields consistently.
Safe Pattern Constraints for matches
The matches operator only accepts patterns that pass validateSafePattern and can be built with compileSafePattern. This rejects pattern constructs known to cause catastrophic backtracking. A policy author MUST NOT assume arbitrary regular expression syntax is accepted; only the safe subset validated by these functions is permitted.
Sealing a policyEvaluation Into a CER
A PolicyEvaluation produced by evaluatePolicy MAY be passed into sealCerV2 or certifyDecisionV2 as the policyEvaluation option. When present, it is covered by certificateHash. This makes the evaluation producer-declared evidence: the attestation node never re-executes the policy. It only seals and later returns what the producer declared, exactly like every other producer-declared field. See AIEF for how a sealed CER is later verified end to end.
Scope Boundary
@nexart/ai-execution, the attestation node, and the relevant provider integration respectively.Runnable Example
import { evaluatePolicy, validateSchema, validatePolicy, hashPolicy } from "@nexart/policy";
import { certifyDecisionV2 } from "@nexart/ai-execution";
const schema = {
fields: {
amount: { type: "number" },
requestedAt: { type: "timestamp" },
approvedAt: { type: "timestamp" },
},
};
const policy = {
combinator: "all",
rules: [
{ field: "amount", operator: "lte", value: 5000 },
{
field: "approvedAt",
operator: "within-window",
reference: "requestedAt",
windowMs: 60_000,
},
],
};
validateSchema(schema);
validatePolicy(policy);
const execution = {
amount: 4200,
requestedAt: "2026-08-18T10:00:00.000Z",
approvedAt: "2026-08-18T10:00:12.000Z",
};
const evaluation = evaluatePolicy(schema, policy, execution);
// evaluation.verdict is 'PASS' | 'FAIL' | 'ERROR'
const bundle = await certifyDecisionV2({
provider: "openai",
model: "gpt-4o-mini",
input: { amount: execution.amount },
output: { approved: evaluation.verdict === "PASS" },
executionRole: "operative",
policyEvaluation: evaluation,
});
// policyEvaluation is now producer-declared evidence sealed inside certificateHash
console.log(hashPolicy(policy));