Skip to content

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.

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.

  • 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.
  1. Diagnose - a request is denied and you capture its audit request_id. The audit explain endpoint reconstructs the denied policy_input along with the diagnostics and determining policies.
  2. 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.
  3. 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.
  4. 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.
  5. Activate - with ACTIVATE=true and a clean verdict, the example activates the version and polls activation status until the STS runtime reports it loaded.
Terminal window
git clone https://github.com/Garudex-Labs/examples.git caracal-examples
cd caracal-examples/policyIterate
CARACAL_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 iterate

The 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.

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.

Terminal window
cd caracal-examples/policyIterate
npm test

The tests inject the Admin API transport and do not call a live Caracal stack.

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.

Continue to Launch Research Agent to see runtime credential injection for a plain CLI agent.