Iterate Policy Safely
Policy Iterate is an audit-driven policy rollout loop in the Caracal examples repository under policyIterate/. It tests a candidate policy change against the exact redaction-safe audit input of a real denial - and proves the change does not alter other decisions - before activation.
When to use it
Section titled “When to use it”Use it when a real request was denied and the fix must be proven safe before rollout: the candidate has to repair that denial and keep every regression case’s decision. Do not use it as a substitute for the policy authoring contract or activation workflow; it automates their verification loop.
Prerequisites
Section titled “Prerequisites”- A denied request ID with an explainable audit trace.
- A staged immutable policy-set version and current active version recorded for rollback.
- Regression cases covering nearby allow and deny behavior.
- Diagnose - a request is denied and you capture its audit
request_id. The audit explain endpoint reconstructs the deniedpolicy_inputalong with the diagnostics and determining policies. - Simulate - you edit the policy data, stage a candidate policy-set version, and the example replays the denied input against it through the same policy engine that serves live traffic.
- Regress - the example replays your expected-decision cases against the same candidate, so loosening a policy for one caller cannot silently change decisions for everyone else.
- Decide - activation is gated on evidence: the candidate allows the denied input, the rollout contract validates, simulation produced no warnings, and every regression case keeps its expected decision.
- Activate - with
ACTIVATE=trueand a clean verdict, the example activates the version and polls activation status until the STS runtime reports it loaded.
Run the iteration
Section titled “Run the iteration”git clone https://github.com/Garudex-Labs/examples.git caracal-examplescd caracal-examples/policyIterateCARACAL_API_URL=http://127.0.0.1:3000 \CARACAL_ADMIN_TOKEN=<admin-token> \CARACAL_ZONE_ID=<zone-id> \DENIED_REQUEST_ID=<denied-request-id> \POLICY_SET_ID=<policy-set-id> \CANDIDATE_VERSION_ID=<staged-version-id> \REGRESSION_FILE=./regressions.json \npm run iterateThe run is a dry run by default: it narrates each phase on stderr, prints a JSON report on stdout, and exits 0 only when the verdict is clean. Re-run with ACTIVATE=true to roll out the version and wait for propagation.
REGRESSION_FILE is optional and points to a JSON array of { name, expect, input } cases - see regressions.example.json in the example directory for the format.
Claims note
Section titled “Claims note”Actor and subject claims are not written to audit, so reconstructed input does not contain them. For a claim-dependent denial, add the relevant context.actor_claims to a regression case built from the printed policyInput and iterate with that case instead.
cd caracal-examples/policyIteratenpm testThe tests inject the Admin API transport and do not call a live Caracal stack.
Validate the iteration
Section titled “Validate the iteration”Keep ACTIVATE unset first. Expect the candidate to repair the target denial while every regression retains its decision. Only then activate and wait for loaded; verify the first real exchange names the candidate manifest.
Next Step
Section titled “Next Step”Continue to Launch Research Agent to see runtime credential injection for a plain CLI agent.

