AuthZEN Simulation (Live vs Simulation)
cidaas AuthZEN has two evaluation channels:
| Channel | Policy source | PDP path prefix |
|---|---|---|
| Live | liveVersionId pin, or the working-copy script if the pin is empty | /policy-decision-srv/access/v1/* |
| Simulation | simulationVersionId pin, or the working-copy script if the pin is empty | /policy-decision-srv/access/v1/simulation/* |
Simulation is not a request-body flag. You pin versions in policy-management-srv, then call a different PDP URL. Simulation responses set the header X-AuthZen-Simulation: true.
Filter packages (authzen.filter_subject, filter_resource, filter_action) are shared. Discovery GraphQL URLs are also shared (your external catalog, or the sample endpoint). Simulation search only diverges from live search when post-eval is on, because post-eval uses the channel's allow policies.
See AuthZEN Search for catalog setup and SearchConfig.
Required scopes
| Scope | Use |
|---|---|
cidaas:authzen_evaluate | Live evaluation and search |
cidaas:authzen_simulate | Simulation evaluation, search, explain, and simulation cache invalidate |
cidaas:authzen_explain | Live explain |
cidaas:authzen_write | Create versions and pin modes |
cidaas:authzen_read | Read policies and simulation revision |
Use the access_token header on all examples.
export DOMAIN="https://{host}"
export TOKEN="{token}"
export AUTH_HDR=(-H "access_token: $TOKEN" -H "Content-Type: application/json")
1. Pin a version
- Create a policy (working copy).
- Create a version from that copy.
- Update policy modes to pin live and/or simulation.
POLICY_ID="<policy id>"
curl -s -X POST "$DOMAIN/policy-management-srv/admin/versions?versionType=PATCH" \
"${AUTH_HDR[@]}" -d "{\"type\":\"POLICY\",\"language\":\"rego\",\"ref\":\"$POLICY_ID\"}"
VERSION_ID="<version id>"
curl -s -X PUT "$DOMAIN/policy-management-srv/admin/policies/$POLICY_ID/modes" \
"${AUTH_HDR[@]}" -d "{\"simulationVersionId\":\"$VERSION_ID\"}"
Pin live independently:
curl -s -X PUT "$DOMAIN/policy-management-srv/admin/policies/$POLICY_ID/modes" \
"${AUTH_HDR[@]}" -d "{\"liveVersionId\":\"$VERSION_ID\"}"
Clear a pin so that channel uses the working-copy script:
curl -s -X PUT "$DOMAIN/policy-management-srv/admin/policies/$POLICY_ID/modes" \
"${AUTH_HDR[@]}" -d '{"liveVersionId":""}'
At least one of liveVersionId or simulationVersionId is required on each modes request. Omitted fields are left unchanged.
Get policy accepts ?channel=live or ?channel=simulation to return the script resolved for that channel.
The tenant simulation revision changes when simulation pins or simulation-effective scripts change. The PDP uses it as a simulation cache key (meta.simulation_revision on evaluation responses).
2. Simulate evaluation
Simulate access evaluates against the simulation channel.
options.compare_baseline defaults to true. The response then includes diff:
diff.change | Meaning |
|---|---|
unchanged | Live and simulation decisions match |
deny_to_permit | Live deny, simulation permit |
permit_to_deny | Live permit, simulation deny |
The carol subject below matches the sample catalog in AuthZEN Search (seed-samples plus the explicit carol create step).
curl -s -X POST "$DOMAIN/policy-decision-srv/access/v1/simulation/evaluation" \
"${AUTH_HDR[@]}" -d '{
"subject": {
"id": "carol",
"type": "user",
"properties": { "roles": ["admin"] }
},
"resource": { "id": "123", "type": "account" },
"action": { "name": "read" },
"options": { "compare_baseline": true }
}'
Example 200:
{
"decision": false,
"simulation": true,
"meta": {
"simulation": true,
"simulation_id": "8f3c1a2e-4b9d-4e11-9c22-1a2b3c4d5e6f",
"simulation_revision": "abc123",
"evaluated_at": "2026-08-19T06:00:00Z"
},
"diff": {
"baseline_decision": true,
"candidate_decision": false,
"change": "permit_to_deny"
}
}
Batch simulate returns { "evaluations": [ ... ], "simulation": true } with the same per-item meta and diff.
Well-known configuration lists simulation URLs (simulation_evaluation_endpoint, and so on). OpenAPI: AuthZEN configuration.
3. Simulate search
Simulate subject search, resource, and action use the same request bodies as live search.
When postEval.enabled is false, live and simulation search return the same candidates (shared filter policies). Enable post-eval to see simulation allow differences in search results.
curl -s -X POST "$DOMAIN/policy-decision-srv/access/v1/simulation/search/subject" \
"${AUTH_HDR[@]}" -d '{
"subject": { "type": "user" },
"resource": { "id": "123", "type": "account" },
"action": { "name": "read" },
"page": { "limit": 10 }
}'
4. Simulation cache
Live and simulation evaluator caches are separate. Both auto-refresh about every 10 seconds. You do not need to invalidate after every pin or policy change.
Simulation search still loads SearchConfig and Discovery from the live cache. Changing those waits on the live refresh (or live invalidate), not the simulation invalidate API.
| Channel | What it caches | Invalidate (optional) |
|---|---|---|
| Live | Evaluators, PIP, Discovery, SearchConfig | Invalidate policy cache |
| Simulation | Simulation evaluators only | Invalidate simulation cache |
curl -s -X POST "$DOMAIN/policy-decision-srv/access/v1/simulation/cache/invalidate" \
"${AUTH_HDR[@]}" -d '{}'
Simulation invalidate returns { "flushed": true, "tenant_key": "..." }. Use it only when you need a new simulation pin or policy on the next request.
5. Explain (debugging)
Explain access traces OPA evaluation on the live channel (explain: full, notes, or fails). Scope: cidaas:authzen_explain.
Simulate explain traces the simulation channel. Scope: cidaas:authzen_simulate.
curl -s -X POST "$DOMAIN/policy-decision-srv/access/v1/explain" \
"${AUTH_HDR[@]}" -d '{
"explain": "notes",
"subject": { "id": "alice", "type": "user" },
"resource": { "id": "123", "type": "account" },
"action": { "name": "read" }
}'
6. Safe rollout
- Keep live pinned to a known-good version (or a stable working copy).
- Edit the working copy or create a new version. Pin it with
simulationVersionIdonly. - Wait about 10 seconds for the simulation cache, or optionally invalidate simulation cache.
- Call simulation evaluation with
compare_baseline: true. Reviewdiff.change. - If post-eval search matters, compare live vs simulation search.
- When results look correct, pin the same version as
liveVersionId. - Wait about 10 seconds for the live cache, or optionally invalidate.
ReBAC rebac.* builtins in Rego follow the same channel: live eval uses live policy pins; simulation eval uses simulation pins. Relation Store data is shared. See ReBAC.
Related documentation
Please contact us on our support page or reach out to cidaas support at [email protected].