PDP Admin Guide — Domain & Application Policy Model
Config locations
Root: SERVICE_CONFIG_DIR (Compose mounts ../ServiceConfigs/pdp/config).
- Applications:
config/applications/*.yaml - Domains:
config/domains/*.yaml - PIP Registry:
config/pip_registry.yaml - Policies:
- Global:
config/policies/global/ - Domain shared:
config/policies/domains/{domain}/shared/ - Environment:
config/policies/domains/{domain}/{environment}/ - Application:
config/policies/applications/{app_id}/
- Global:
Admin APIs (via BFF)
- Apps:
/api/authz/applications(GET, POST),/api/authz/applications/{id}(GET, PUT, DELETE) - Domains:
/api/authz/domains(GET, POST),/api/authz/domains/{id}(GET, PUT, DELETE) - PIPs:
/api/authz/pips(GET, PUT),/api/authz/pips/{name}(GET, PUT, DELETE) - Debug:
/api/authz/debug/applications/{app_id}/policy-sources
Policy review and merge workflow
- Feature flag:
FEATURE_POLICY_MERGE_ENABLED(default: off). See flag reference:../reference/settings-flags.md#evaluation-behavior. - Self-authorization: PDP evaluates an AuthZEN request internally to authorize merges.
- Resource:
pdp:policy - Action:
merge - Required permit example:
- Resource:
id: pdp-merge-admin
rules:
- resource: pdp:policy
action: merge
effect: PERMIT
when: "'pdp_admin' in subject.properties.roles"
End-to-end steps
- Open workspace in Authorization Studio → edit YAML (Diff/Lints/Impact tabs).
- Click “Review & Merge” → client validates and posts draft to PDP validate endpoint.
- If clean, client calls
POST /access/v1/policies/mergewith{ policy_id, yaml, message }. - PDP checks flag, performs self-authorization, writes YAML, refreshes caches.
- UI shows success with updated effective policies; failures include PDP explanation.
cURL example (authorized)
curl -sS -X POST https://authz.ocg.labs.empowernow.ai/access/v1/policies/merge \
-H "Cookie: <session>" \
-H "Content-Type: application/json" \
-d '{"policy_id":"global-base-security","yaml":"id: global-base-security\n...","message":"Tighten base guards"}'
Troubleshooting
- 404: feature flag off → set
FEATURE_POLICY_MERGE_ENABLED=trueand restart PDP. - 403: missing
pdp:policy mergepermit → add/adjust admin policy and reload. - 400: YAML invalid → use
/access/v1/policies/validatefirst; fix lints.
Observability: Grafana dashboards
- Grafana provisioned via
ServiceConfigs/observability/grafana. - “PDP Debugging” includes:
- Explain requests/min (Loki
api.request.start+debug_explain). - Sandbox streams/min (Loki
api.request.start+sandbox_stream). - Explain latency p50/p95 from
duration_ms. - Cache hits/min from
cache.hit.
- Explain requests/min (Loki
Restart Grafana:
docker compose -f docker-compose-authzen4.yml restart grafana
SPA performance
- ETag + Last-Modified on GETs;
Cache-Control: public, max-age=60 - Client sends
If-None-Match/If-Modified-Sincefor 304s
Expected headers when cached:
ETag: W/"<sha256>"
Last-Modified: Tue, 24 Sep 2025 20:41:15 GMT
Cache-Control: public, max-age=60
Feature flags
FEATURE_POLICY_ADMIN_SELF_AUTH(default: false): PDP self-authorizes admin ops by evaluating AuthZEN requests (pdp:domain edit,pdp:application delete). See../reference/settings-flags.md#evaluation-behavior.
Example policy snippet (enable domain edits for pdp_admin):
id: pdp-admin-ops
policy_type: AuthZ
rules:
- resource: pdp:domain
action: edit
effect: PERMIT
allowIf: "subject.role == 'pdp_admin'"
Curl checks
curl -i https://authz.ocg.labs.empowernow.ai/api/authz/applications -H "Cookie: <session>"
# Conditional GET
curl -i https://authz.ocg.labs.empowernow.ai/api/authz/applications \
-H "If-None-Match: W/\"<etag>\"" -H "Cookie: <session>"
# Domains list
curl -i https://authz.ocg.labs.empowernow.ai/api/authz/domains -H "Cookie: <session>"
Playwright
cd pdp_ui/frontend
npx playwright test --project=chromium
Recovery
- Revert YAML under
ServiceConfigs/pdp/configvia Git. - Disable self-auth quickly by unsetting
FEATURE_POLICY_ADMIN_SELF_AUTHand restarting PDP.
Operations playbook
Restart services
docker compose -f docker-compose-authzen4.yml restart bff
docker compose -f docker-compose-authzen4.yml restart pdp
docker compose -f docker-compose-authzen4.yml restart traefik
Verify health:
curl -sf https://authz.ocg.labs.empowernow.ai/api/authz/health || echo fail
Verify config mount
docker exec -it pdp_app sh -c 'ls -la /app/config && grep -H "id:" /app/config/applications/*.yaml | head'
Add an application (UI)
Admin → Applications → New Application → Save. YAML is written under config/applications/<id>.yaml.
Add a domain (UI)
Admin → Domains → New Domain → set environments and shared folder → Save.
Toggle a PIP
Admin → PIPs → switch a PIP on/off. Configuration persists to pip_registry.yaml.
Concepts and architecture
- Single identifier (
pdp_application) selects app; domain/env resolution is internal. - Inheritance order (if defined): global → domain shared → env → app-specific.
- SPA calls BFF; BFF proxies to PDP. Traefik routes
/api/**from SPA hosts to BFF.
Troubleshooting
- HTML instead of JSON: ensure Traefik SPA static routers exclude
/access/v1/and BFF API router includes/access/v1/and/api/for SPA hosts. - 403 on admin ops: either self-auth flag is on and policy denies, or session missing. Check PDP logs and BFF logs; disable self-auth to confirm.
- No 304 responses: confirm ETag/Last-Modified present; check intermediary stripping headers; retry with direct curl; ensure clocks are reasonably synced.
- Admin routes 404: ensure BFF routes include
/api/authz/{applications,domains,pips,debug}and BFF is restarted.