fix(VIOL-0100): wire passthrough_on_error through guard config; reject on UDF guards#768
Merged
Merged
Conversation
…t on UDF guards The guard key allowlist rejected passthrough_on_error at load, and the expander never forwarded it, so the value users wrote in an SQL-style guard block never reached the evaluator, which fell back to its True default. Admit the key to the allowlist, parse and bool-check it onto GuardConfig, and forward it in the SQL branch of the runtime guard dict so the evaluator and skip manager receive the user's value. UDF-style guards have no consumer for the flag (the UDF path always passes records through on error), so a non-default value on a UDF guard now raises rather than being silently dropped. passthrough_on_empty stays rejected: it has no runtime consumer on any path, so admitting it would deposit a dead key that changes no behavior.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
passthrough_on_errorguard flag was documented and already consumed by the guard evaluator and skip manager, but users could not actually set it: the guard-key allowlist rejected it at config load, and even before that the expander never forwarded it into the runtime guard dict — so the evaluator always fell back to itsTruedefault.This wires the key end to end for SQL-style guards, on the same rails as
condition/on_false:consolidated_guard.py): admitpassthrough_on_error(only).GuardConfig): store it as an optional attribute (= True);from_dictextracts it with a bool check;from_stringuses the default.process_guard_config): forwardpassthrough_on_errorin the SQL branch's runtime guard dict.ConfigurationError(fail loud) instead of being silently dropped.passthrough_on_emptyis intentionally left rejected — it has no runtime consumer on any path, so admitting it would deposit a dead key that changes no behavior. A test pins that it stays rejected.Defaults are unchanged (
passthrough_on_error=True); thecondition/on_falseflow and the semantic-error-always-bypasses rule are untouched.Verification
passthrough_on_emptyrejection test passed as a baseline.tests/core/utils/test_consolidated_guard.py+tests/unit/output/response/test_guard_passthrough_wire_through.py— 31 passed. New tests cover: parser round-trip, default-when-omitted, non-bool rejection,passthrough_on_emptystays rejected, UDF-guard fail-loud, expander SQL forward + default, and evaluator behavior (applies guard behavior whenFalse, passes record whenTrue) via the publicevaluate()entry point.tests/unit/output/response/(137),tests/unit/workflow/managers/(133),tests/preprocessing/excluding a pre-existing circular-import collection quirk (234), plus the guard/evaluator/skip/parity suites — all pass.ruff checkclean;ruff format --checkclean.Out of scope (observed, not fixed)
tests/preprocessing/staging/test_source_data_protection.pyfails to collect on a circular import (InitialStageContext) — reproduces on cleanmain, unrelated to this change.passthrough_on_errorexample lives in a separatedocs.agent-actions/tree not in this checkout.