Adapter Contracts
This page lists the contracts an APF adapter is written against. For the design and a walkthrough, refer to APF Adapter.
Projector
A projector lowers the bundle’s canonical policy into a runtime’s native documents when the policy service loads a bundle.
The policy service serves each surface through GetDocument under its kind and name. A projection error fails the bundle load, so a projector should reject what its runtime cannot represent rather than drop it silently. APF does not yet follow this fully: the compiler drops binary harness flags, and the OpenShell projector drops credential_binding and allow_uninspected_credentials.
Evaluator
EvalInput
EvalInput::for_tool_call(tool, capability, user_subject, args) builds an input with no body or target.
EvalResult
EvalError::Engine is displayed as evaluator engine error: <detail>. A request adapter must deny when evaluation returns an error. EvaluationService returns gRPC INTERNAL instead, and leaves the deny to its caller.
Apply Effects
Use this function rather than applying effects yourself, so every enforcement point mutates requests the same way. Deny the request on any error. Runtime-specific rules, such as OpenShell’s header restrictions, are the adapter’s to enforce on top.
ActivePolicy
The gateway publishes the active policy on a watch channel. Read it once per request and use the same value for the decision and its audit record, so a hot swap between two reads cannot attribute a decision to the wrong policy.
Policy Client
apf-policy-client wraps the PolicyService gRPC API over the policy service’s Unix socket.
An admission adapter should check the response digest against the body and verify the provenance_token against the policy service’s JWKS before it hands a document to the runtime. APF’s interceptor does both at sandbox creation. On a configuration refresh it checks the body digest against the token’s claims without verifying the token’s signature, and relies on the validate phase to verify it. Refer to Sandbox Admission.
Audit
Each component writes its own JSONL file through apf-audit. ComponentAudit::to_jsonl_in(dir, identity) opens <dir>/<component>-audit.jsonl. emit_required returns an error the caller must treat as fatal for the operation, and emit_best_effort returns an error the caller may log. Every record is validated against the apf.audit.event.v1 schema and scanned for credential-like strings before it is written. Refer to Audit Event Schema.
OpenShell Gateway Interceptor
apf-openshell-interceptor implements OpenShell’s gateway interceptor service on the gateway’s --openshell-interceptor-addr listener.
A governance denial returns gRPC OK with allowed: false. On CreateSandbox and UpdateConfig modify, infrastructure failures return a gRPC status: INVALID_ARGUMENT for a CreateSandbox operation with no name, UNAVAILABLE when the policy service cannot be reached, and INTERNAL when patch generation fails. Provider bindings report an unreachable policy service as a denial instead. APF’s manifest declares every governance binding fail-closed and the two post-commit bindings fail-open, so with OpenShell’s default dynamic binding policy, OpenShell refuses the operation in all of these cases. Describe and SnapshotProviderProfiles are RPCs, not bindings: a Describe failure stops the OpenShell gateway from starting, and a snapshot failure returns FAILED_PRECONDITION or INTERNAL. Refer to Gateway Interceptor for the bindings and their checks.
OpenShell Supervisor Middleware
apf-openshell-middleware implements OpenShell’s supervisor middleware service on the --openshell-middleware-addr listener, under the name apf-content-policy.
Every decision returns gRPC OK. A supervisor whose token is bound to a different sandbox than the request gets PERMISSION_DENIED. Refer to Supervisor Middleware for the request mapping, limits, and reason codes.
Extension Authentication
Both OpenShell listeners use the same contract unless they run in insecure mode.
Failures are recorded as extension_auth.* authentication events in the surface’s audit file. Refer to Configure Service Authentication for the trust profile.
Dependency Rules
cargo xtask dag-guard checks these rules:
- Library crates do not depend on service or adapter crates.
- Service crates do not depend on each other.
- An adapter depends on another adapter only if that adapter is a leaf.
- Runtime-specific code belongs in
apf-<runtime>-*crates. This check is a text search foropenshell_that runs only whenrgis installed. Service and adapter crates are exempt, butapf-proto, which generates OpenShell’s protobuf types, is not, so onmainthe check fails whereverrgis available. - Only
apf-bundle’s signing backend andapf-compileimport the yaml-sigil crates.
Next Steps
- For the APIs adapters call, refer to Service APIs.
- For the existing adapters, refer to OpenShell Integration.