Skip to content

feat(decision-logs): apply the mask_decision policy to events - #186

Open
sspaink wants to merge 1 commit into
open-policy-agent:mainfrom
sspaink:feat/decision-log-mask
Open

feat(decision-logs): apply the mask_decision policy to events#186
sspaink wants to merge 1 commit into
open-policy-agent:mainfrom
sspaink:feat/decision-log-mask

Conversation

@sspaink

@sspaink sspaink commented Aug 6, 2026

Copy link
Copy Markdown
Member

Fixes #73

Implements decision_logs.mask_decision: decision events are redacted before they are buffered, uploaded, or written to the console. MaskRuleSet ports v1/plugins/logs/mask.go, and a masking failure drops the event rather than logging it unmasked.

The mask policy has to be built as a plan entrypoint (opa build -t plan -e system/log/mask), since this SDK evaluates compiled plans. A configured entrypoint with no plan logs a warning.

Decision events are now redacted by the policy at
decision_logs.mask_decision (default system/log/mask) before they are
buffered, uploaded, or written to the console.

MaskRuleSet ports plugins/logs/mask.go: the shorthand string form and the
structured {op, path, value} form, url.PathUnescape/PathEscape segment
handling, Go's silent skipping of undefined paths, and the bookkeeping of
applied rules in the event's erased/masked arrays. A mask policy that
fails to prepare, evaluate, or parse drops the event rather than logging
it unmasked, matching OPA Go. The prepared query is cached until a bundle
is activated, as Go caches until its compiler is updated.

Because this SDK evaluates compiled IR plans rather than running a
compiler, the mask policy has to be built as an entrypoint
(opa build -t plan -e system/log/mask). When an explicitly configured
entrypoint has no plan, masking is inactive and says so with a warning.

IR plans wrap results as {"result": <value>}. That envelope is now
stripped before the decision is returned or logged, so mask rules address
/result/<field> and callers get the decision value itself -- the shape
both READMEs already document.

Fixes open-policy-agent#73

BREAKING CHANGE: Opa.DecisionResult.getResult() returns the decision
value instead of the {"result": <value>} envelope. Callers reading
getResult().get("result") should read getResult() directly;
getResult().asBoolean() and getResultAs(Class) now behave as documented.

Signed-off-by: Sebastian Spaink <sebastianspaink@gmail.com>
@sspaink
sspaink marked this pull request as ready for review August 6, 2026 19:08
@sspaink
sspaink requested a review from a team as a code owner August 6, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement mask_decision policy

1 participant