Policy Service
apf-policy-service is APF’s Policy Administration Point (PAP). It loads a signed bundle, verifies it, compiles it into the documents each enforcement surface consumes, and serves those documents with a signed provenance token. It never evaluates requests, and it does not author or sign bundles.
Startup Sequence
The service checks its configuration before it accepts any connection. Every step fails closed: if one fails, the process exits and serves nothing.
- Load trust roots. Read every
*.pub,*.pem, and*.p256file in--trust-root-dir. The service refuses to start if the directory holds no keys. - Load the document signing key. Read the Ed25519 seed from
--document-signing-key. If none is configured, the service generates an ephemeral key, logs its public half, and records the weakened control. - Load the counter store. Read the anti-rollback high-water mark from
--counter-store. A corrupt counter file stops startup. - Open the audit log. Create
apf-policy-service-audit.jsonlin--audit-log-dir. The service refuses to start without an audit directory. - Check the HTTP surface. If
--http-addris set, the service requires--http-bearer-token-file. - Record the startup posture. Write one
policy_service_startupaudit record withsecurity_statesecureordegradedand the list of weakened controls. - Load the bundle. Read the bundle from the configured policy source, verify it, compile it, and advance the counter. A bundle that fails any check stops startup.
- Bind the socket. Create the
PolicyServiceUnix socket with mode0600and accept only peers whose UID matches--allowed-uid, which defaults to the service’s own UID.
Policy Sources
The --policy-source flag selects where the bundle comes from. The two sources are mutually exclusive.
Local Source
The default source reads a signed manifest from --bundle-path. Member paths in the manifest resolve relative to the manifest’s directory. An operator can load a new bundle without restarting the service by calling POST /v1/refresh on the HTTP surface with a bundle_path in the JSON body. The refreshed bundle goes through the same verification and counter checks as the startup bundle.
HTTP Source
With --policy-source http, the service fetches a gzipped tarball of the bundle directory from --bundle-source-url.
- Authentication. The service sends
Authorization: Bearer <token>when--bundle-source-token-fileor--bundle-source-tokenis set. An empty token is an error. With neither set, the service fetches anonymously and records the weakened control. - Manifest discovery. After unpacking, the service looks for the first
.yamlfile whose signature verifies against the trust roots and whose payload parses as a bundle. It triesmanifest.yamlfirst, then files whose name containsbundle. - Initial load. The first fetch happens at startup and fails closed.
- Polling. A background task polls every
--bundle-source-poll-interval-secsseconds, 30 by default. It sends aHEADrequest first, and a failedHEADrequest fails the poll. It skips the download when thex-checksum-sha256orETagheader equals the hex SHA-256 of the archive it already has, so a quoted or opaqueETagnever skips. A polling download is retried up to three times with backoff. - Hot swap. A fetched bundle replaces the served projections only if it verifies and its revision passes the counter check. A failed poll leaves the current bundle in place.
- Variants. The source code supports a
{variant}placeholder in the URL for per-caller bundles, but the service does not load variants in this release. Use a literal URL. Refer to Publish and Distribute.
The service accepts a plain http:// bundle source URL without a warning. Use https://. A compromised or misconfigured origin cannot get an unsigned bundle accepted, but the transport and its token are still part of the trust boundary.
Verification
The service verifies a bundle once, when it ingests it. It checks the signature first and stops if the signature fails or the payload does not parse. It then checks every manifest member’s digest, the validity window, the syntax of the runtime_compatibility entries, and the anti-rollback counter, and reports every failure at once. The service presents no runtime versions, so no compatibility comparison happens in this release. Refer to Verify and Activate for each check and its rejection reason.
The counter advances only after the bundle compiles, so a bundle that fails compilation never consumes a revision. Compilation here parses the documents and produces the projections. It does not build the Cedar evaluator, so a Cedar or annotator error passes the policy service and consumes the revision. Refer to Validate and Test Policies.
Compilation and Projection
A verified bundle is compiled into surfaces. Each surface is a document kind that one consumer understands.
--surfaces limits which surface kinds the service serves. A request for any other kind is refused with kind '<kind>' is not served by this instance. The policy gateway needs apf.policy.v1, and the interceptor needs openshell.sandbox.v1 and openshell.provider-profile.v1.
Refer to Policy Projection for how each surface is built.
Serving Documents
The policy gateway calls GetDocument with a surface kind and a document name. The response carries:
body: the projected document bytes.digest: the hex SHA-256 ofbody.version: the bundle’spolicy_revision.valid_until_ms: zero unless--document-ttl-secsis set, in which case it is the time after which the caller should re-fetch.provenance_token: a compact EdDSA JWT minted for this response.
The provenance token is signed with the document signing key and has the key ID as its kid header. Its claims bind the document to the bundle:
The service publishes the document signing public key at /.well-known/jwks.json on its HTTP surface, so the gateway can verify every token it receives.
Policy Name Resolution
--resolver controls how a requested document name maps to a bundle variant.
HTTP Surface
The HTTP surface is off by default. Enable it with --http-addr and --http-bearer-token-file.
The token is compared in constant time. A missing or wrong token returns 401 and writes an authentication audit record.
Audit Events
The policy service writes policy_service_startup, policy_verification, policy_activation, policy_distribution, policy_refresh, provenance_signing, and authentication records. Refer to Audit Event Schema.
Next Steps
- To see how the gateway consumes these documents, refer to Policy Gateway.
- For every flag and environment variable, refer to CLI Commands.