Policy Gateway
apf-policy-gateway is APF’s host-side policy agent. It embeds the local Policy Decision Point (PDP): it fetches the compiled policy set from the policy service, builds a Cedar evaluator from it, and decides every governed request in process. It also hosts APF’s OpenShell gateway interceptor and supervisor middleware, which are libraries linked into this binary rather than separate processes.
Startup Sequence
The gateway validates its listener configuration before it does anything else, so a misconfigured listener never reports ready.
- Resolve each OpenShell listener. For the interceptor and the middleware separately, the gateway requires either the full authenticated set (address, extension trust profile, TLS certificate, TLS key) or the address with the explicit insecure flag. Partial sets, conflicting modes, and security files without an address stop startup. The trust profile, certificate, and key are opened without following symlinks, checked for safe permissions, and parsed before any listener starts.
- Load the provider registration from
--pip-config, when set, through the same checked file path, and validate every registration. An invalid file stops startup. Without the flag the Enrichment stage is off. Refer to Policy Information Providers. - Connect to the policy service over its Unix socket and call
Health. A failed health check is logged and startup continues. - Fetch the JWKS from
--jwks-urlto get the policy service’s document signing key. The interceptor and the sandbox policy refresher use it to verify provenance tokens. The gateway does not verify the token on the policy set it evaluates. If the fetch fails, startup stops. Without--jwks-url, provenance verification is disabled and the gateway logs a warning, and the interceptor cannot be enabled. - Fetch the policy set. Call
GetDocumentforapf.policy.v1/defaultand build the Cedar evaluator. If any rule, annotator, effect, or finding fails to compile, startup stops. - Open the audit log in
--audit-log-dirand record apolicy_activationevent with reason codepolicy.bundle_activated. If the record cannot be written, startup stops. - Start background tasks: the digest watcher, the evaluator hot swap, and, when configured, provider profile reconciliation and sandbox refresh.
- Bind the listeners: the
EvaluationServiceUnix socket and any enabled OpenShell listeners.
Hot Swap
The gateway keeps the active policy in a watch channel. Every reader takes the evaluator together with the digest and revision of the policy it was built from, so a decision can never be attributed to a different policy than the one that made it.
A digest watcher polls apf.policy.v1/default every --bundle-refresh-interval-secs seconds, 10 by default. Setting the interval to 0 disables refresh.
- The first successful poll sets a baseline. A change that lands between startup and that first poll is not detected until the next change.
- When the digest changes, the gateway fetches the document again, decodes it, builds a new evaluator, and swaps it in. It then records a
policy_activationevent with reason codepolicy.bundle_hot_swapped. - If the fetch, decode, or build fails, the gateway logs a warning and keeps the evaluator it already has. A bad policy never replaces a working one. The baseline has already moved to the new digest, so the gateway does not retry until the digest changes again.
- Change events travel on a channel that holds 16 events. If the hot-swap task falls more than 16 events behind, it stops, and the gateway needs a restart to resume hot swaps.
- If the hot-swap record cannot be written, the gateway exits. The new evaluator is already active at that point, so decisions made in the interval are not covered by an activation record.
The gateway does not re-verify the bundle signature on this path. The policy service verified the bundle when it ingested it, and the gateway trusts the policy service’s responses over the owner-only Unix socket.
Decisions
Decisions run in process on the active evaluator. In the current deployment, there is no network call to the policy service on the request path. The only per-request calls go to the policy information providers registered with --pip-config, each under a budget. Every request passes four stages: enrichment, annotators, Cedar rules, and effects. Refer to Request Evaluation.
Two surfaces reach the evaluator.
Refer to Service APIs for both contracts.
Provenance Key Rotation
When --jwks-url is set, the gateway re-fetches the JWKS every --jwks-refresh-interval-secs seconds, 60 by default, and replaces the verification key it uses for provenance tokens. Setting the interval to 0 disables rotation.
OpenShell Background Tasks
Two optional tasks keep OpenShell in step with the active bundle. Both need --openshell-gateway-url, the outbound address of the OpenShell gateway.
Both tasks are driven by the digest watcher, which watches only apf.policy.v1. A bundle that changes only SandboxPolicy or Provider documents does not trigger them. Setting --bundle-refresh-interval-secs to 0 disables them along with the digest watcher. Both connect to OpenShell without TLS and without credentials, so they work only with an OpenShell gateway that accepts such connections.
--openshell-gateway-url is where the gateway connects. --openshell-interceptor-addr is where it listens. Keep the two distinct.
Audit Files
The gateway writes one file per component in --audit-log-dir.
Next Steps
- To see the evaluation pipeline in detail, refer to Request Evaluation.
- To configure the OpenShell listeners, refer to Configure Service Authentication.
- For every flag, refer to CLI Commands.