Effects and Findings
Effects say what happens to a request that policy allows. Findings say what policy observed, whether the request was allowed or denied. Both are named documents that any rule in the bundle can reference.
A First Example
This effect replaces the whole body of a request that carries a secret, tags the request with the kind of secret, and records a finding:
A control rule attaches them:
PolicyEffect
The body block is optional, so an effect can change only headers, the verdict, or findings. If you set body, set exactly one of body.replace and body.patches. A replace or add patch, and a set or add header, takes exactly one of value and source. A remove takes neither.
Reading Values from Annotations
source copies an annotation’s value into a patch or header at evaluation time. It must start with context.annotations., for example context.annotations.secret_kind. If the annotation was not produced for the request, the whole evaluation fails closed and the request is denied with the reason runtime_error:missing_annotation_source:<source>.
Header Rules on OpenShell
The OpenShell middleware enforces extra rules on header mutations. A mutation that breaks them denies the request.
setandaddmay only write headers whose names start withx-openshell-middleware-.removemay not removeauthorization,proxy-authorization,proxy-authenticate,cookie,host,content-length,transfer-encoding,connection,proxy-connection,keep-alive,te,trailer, orupgrade, or any header that starts withx-amz-orx-openshell-credential.- Header values must be printable text.
Patches
Patches apply to the parsed JSON body in firing order. A patch on a request whose body is not JSON, or a replace or remove on a path the body does not contain, denies the request. add creates the target member where RFC 6902 allows it.
Aggregation
When several permits with effects fire, APF combines them deterministically: patches accumulate in firing order, the last body replacement wins and takes precedence over patches, header mutations accumulate in order, and the strongest verdict wins. The reason and message come from the first fired effect that carries the final verdict.
PolicyFinding
An inline finding inside an effect has the same fields plus an optional confidence from 0 to 100.
A finding with label_source fails closed: if the annotation is absent when the finding is resolved, the request is denied, even if label is also set. Keep the patterns of a detection flag and its classification label aligned so the label is always produced when the flag is.
Load-Time Checks
The evaluator refuses to build, and the gateway keeps or refuses the policy, when:
@apf_effectappears on aforbid.@apf_effector@apf_findingnames an effect or finding that is not in the bundle.- An effect’s
findingnames a finding that is not in the bundle. - A
sourceorlabel_sourcedoes not start withcontext.annotations.. - An effect sets both or neither of
body.replaceandbody.patches, or a patch or header has the wrong operands.
Two effects or two findings with the same name are rejected earlier, when the policy service loads the bundle.
Where Findings Go
Findings travel with the decision to OpenShell and into the findings array of the authorization audit record. A finding does not change the decision, unless it cannot be resolved, as with a missing label_source annotation, or the request exceeds the finding limits. Both deny the request. Refer to Understand Decisions and Findings.
Next Steps
- To check effects and findings before you sign, refer to Validate and Test Policies.
- To see effects applied end to end, refer to Protect Sensitive Data.