[AVAILABLE], every command below was run in this session against the repo’s actual code, commit
651497a.Goal
Write a new Policy from scratch, distinct from the shippedvendor-payment one, and confirm
it approves and rejects correctly.
Prerequisites
- The repo cloned and
npm installrun. - Read Policies and the decision first if you haven’t, this guide assumes you know what first-match-wins and fail-closed mean.
Steps
1. Write the policy document
A Policy is a JSON file at<policyDir>/<name>/<version>/policy.json. Create
policies/high-value-payment/1.0.0/policy.json:
reject-default rule: without it, an unmatched transaction still
rejects (fail-closed is the engine’s default, not something the policy has to opt into),
but writing it explicitly documents the reject-by-default behavior for anyone reading the
policy file itself.
2. Reference it from a Business Transaction
3. Evaluate it
This exact scenario already exists asexamples/tutorials/14-custom-policy/, reuse it
rather than writing a parallel harness: it builds a FilePolicyRepository pointed at a
local policies/ directory and executes a transaction through RuntimeFactory.create()
directly, no server required.
Verify
Real output, this session:transaction.json, set
"financeDirectorApproved": false, and rerun. This is what actually happens, tested in this
session, not what you might expect:
REJECTED decision does not come back as a normal object with outcome: "REJECTED",
RuntimeFactory’s ExecutionTrustApplication.execute() throws a RuntimeError whose
message is the matched rule’s rejection reason. examples/tutorials/14-custom-policy/run.ts
doesn’t catch this specially, so an uncaught rejection crashes the script, that’s expected,
not a bug in the tutorial, a caller that wants to handle rejection gracefully needs a
try/catch around execute(). The reject-high-value-without-director-approval rule is
what matched, confirmed by the message, first-match-wins doing its job on different signals,
same policy document, no code change.
Troubleshoot
- Decision comes back
REJECTEDwith"reason": "One or more required policy conditions were not satisfied.", not the reason you expected. Your transaction’s signals matched no earlier rule, only the trailing default. ChecksignalsSchemaagainst what you actually sent, a typo’d signal name is silentlyundefined, which fails everyeq/gt/ltecondition. PolicyValidatorthrows about policy identity. Your Business Transaction’spolicy.name/policy.versiondoesn’t match the loaded file’spolicyId/policyVersionexactly, these are checked, not inferred from the file path.- Wrong policy loaded, or “policy not found.”
FilePolicyRepositoryresolves<policyDir>/<name>/<version>/policy.jsonliterally, confirm the directory structure matches, including the version folder.
Next
Authorize and execute an action end to end
What happens after a policy approves: signing, gateway verification, execution.
Policies and the decision
The concept this guide exercises.