Skip to main content
Version: Latest (4.0.3)

AuthZEN Simulation (Live vs Simulation)

cidaas AuthZEN has two evaluation channels:

ChannelPolicy sourcePDP path prefix
LiveliveVersionId pin, or the working-copy script if the pin is empty/policy-decision-srv/access/v1/*
SimulationsimulationVersionId 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

ScopeUse
cidaas:authzen_evaluateLive evaluation and search
cidaas:authzen_simulateSimulation evaluation, search, explain, and simulation cache invalidate
cidaas:authzen_explainLive explain
cidaas:authzen_writeCreate versions and pin modes
cidaas:authzen_readRead 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

  1. Create a policy (working copy).
  2. Create a version from that copy.
  3. 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.changeMeaning
unchangedLive and simulation decisions match
deny_to_permitLive deny, simulation permit
permit_to_denyLive 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.

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.

ChannelWhat it cachesInvalidate (optional)
LiveEvaluators, PIP, Discovery, SearchConfigInvalidate policy cache
SimulationSimulation evaluators onlyInvalidate 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

  1. Keep live pinned to a known-good version (or a stable working copy).
  2. Edit the working copy or create a new version. Pin it with simulationVersionId only.
  3. Wait about 10 seconds for the simulation cache, or optionally invalidate simulation cache.
  4. Call simulation evaluation with compare_baseline: true. Review diff.change.
  5. If post-eval search matters, compare live vs simulation search.
  6. When results look correct, pin the same version as liveVersionId.
  7. 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.

info
Need Support?

Please contact us on our support page or reach out to cidaas support at [email protected].