fix(policy): merge partial data_rules overrides onto conservative defaults - #35
Conversation
…aults
_fill_missing_classes backfilled conservative defaults only for data classes
entirely ABSENT from the org file (setdefault, at CLASS granularity). When an
org overrode a class to tighten ONE axis — e.g. `internal: {regions: [eu]}` to
pin residency — pydantic built a fresh DataRule for that class in which every
unspecified field reverted to DataRule's permissive default. Most dangerously
`forbid_training_vendors` flipped from the class default True to False, so an
override meant to TIGHTEN policy silently LOOSENED it: internal / confidential /
restricted data could now reach a vendor that trains on it, with no error and no
visible diff. The bug hit even `restricted`, the fail-closed class.
This contradicts the module's own contract — StrictModel exists so "a typo in a
governance file must be a loud error, not a silently ignored rule", the
validator's comment promises overrides "never silently un-govern", and the
existing test is literally named
`test_partial_data_rules_keep_conservative_defaults`. The defaults were only
kept for OTHER (absent) classes, never for the one being edited.
Add a mode="before" validator that merges each per-class override dict onto that
class's conservative default, so an unspecified field keeps the strict default
(`{**default.model_dump(), **override}`). Un-governing is still possible but must
be written out loud (`forbid_training_vendors: false`), never happen by omission.
Absent classes are still filled whole by _fill_missing_classes. The existing
partial-override test gains an assertion that the overridden class keeps its own
guard, plus new tests for the tightening case and for explicit un-governing.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Adversarial gate: PASS (two independent opus reviewers, both high confidence). Correctness/intent: merge semantics match documented intent (not atomic-replace) — the module insists absence is visible-not-implicit and governance typos must fail loudly, and the validator/tests codify "never silently un-govern by omission." All construction paths verified stable (defaults, Security-completeness — verified end-to-end at runtime:
Full suite 208 passed; demo +
|
Bug (governance downgrade)
A per-class
data_rulesoverride that tightens one axis silently dropped the class's other conservative guards. For example, pinning EU residency on internal data:produced
DataRule(regions=['eu'], forbid_training_vendors=False)— theforbid_training_vendorsguard flipped from its class defaultTruetoFalse. So an override meant to tighten policy loosened it: internal / confidential / restricted data could now be routed to a vendor that trains on it, with no error and no visible diff. The bug hit evenrestricted, the fail-closed class (restricted: { models: [x] }dropped its training-vendor guard too).Root cause
_fill_missing_classesbackfilled conservative defaults only for classes entirely absent from the file (setdefault, class granularity). A class present but partial in YAML was taken as a complete atomicDataRule, so unspecified fields fell back toDataRule's permissive field defaults instead of the conservative per-class defaults.This contradicts the module's own contract:
StrictModelexists so "a typo in a governance file must be a loud error, not a silently ignored rule," the validator's comment promises overrides "never silently un-govern," and the existing test is namedtest_partial_data_rules_keep_conservative_defaults— yet defaults were only kept for other classes, never the one being edited.Fix
Add a
mode="before"validator that merges each per-class override dict onto that class's conservative default ({**default.model_dump(), **override}), so an unspecified field keeps the strict default. Un-governing is still possible but must be explicit (forbid_training_vendors: false) — never by omission. Absent classes are still filled whole by_fill_missing_classes.Tests
forbid_training_vendorsguard.test_partial_override_keeps_the_same_class_training_guard: pinning a region oninternalkeeps the training-vendor guard.test_data_rule_ungoverning_must_be_explicit: an explicitforbid_training_vendors: falseis still honored.Verified the new assertions fail on
main(guard silently dropped) and pass on the branch. Full local gate green: 208 passed, coverage 93.34% (≥85%),ruffclean, offline demo +audit verifyintact.🤖 Found and fixed by an autonomous
bughuntiteration.