fix: distinguish absent authority fields from forbidden claims

This commit is contained in:
djpjronline-netizen committed 2026-10-30 12:01:15 -04:00
1 parent d6b84ecef8
commit 37a20ef06f
5 files changed
+63 -12

No files matched your search

@@ -10,7 +10,7 @@
"id": "hand-seeded",
"source": "manual-curation-pending-regeneration"
},
"registryDigest": "ac3209d3e03a4b28d796dd6bf75c81a0452c88aae691c8a4fec95544c07e82c8",
"registryDigest": "b7be40189dfad25f456b15105f6fbea219d3cda7aafbc0bd0f38c5089b76dec8",
"schemaVersion": 1,
"triggers": {
"skill:agent-runtime-gateway-smoke-test": [
@@ -539,22 +539,24 @@ def _validate_authority(observation: dict[str, Any], contradictions: list[dict[s
("claimsPullRequestOpened", "pull_request_claim_forbidden"),
)
for field, code in forbidden_claims:
if observation.get(field) is not False:
if field in observation and observation[field] is not False:
contradictions = add_issue(
contradictions, code, 2,
"The compiler cannot claim repository or external effects.",
)
requested_effects = observation.get("requestedEffects")
if not isinstance(requested_effects, dict) or set(requested_effects) != EFFECT_FIELDS or any(
value is not False for value in requested_effects.values()
if "requestedEffects" in observation and (
not isinstance(requested_effects, dict)
or any(value is not False for value in requested_effects.values())
):
contradictions = add_issue(
contradictions, "external_action_requested", 6,
"Compilation cannot request source, test, catalog, Git, PR, or memory effects.",
)
claimed_authority = observation.get("claimedAuthority")
if not isinstance(claimed_authority, dict) or set(claimed_authority) != AUTHORITY_FIELDS or any(
value is not False for value in claimed_authority.values()
if "claimedAuthority" in observation and (
not isinstance(claimed_authority, dict)
or any(value is not False for value in claimed_authority.values())
):
contradictions = add_issue(
contradictions, "unsafe_generated_authority", 6,
@@ -610,6 +612,10 @@ def _valid_envelope(observation: Any, faults: list[dict[str, Any]]) -> tuple[boo
faults = add_issue(faults, "observation_shape_invalid", 1,
"Declared maps and arrays must retain their documented shapes.")
return False, faults
for field, expected in (("requestedEffects", EFFECT_FIELDS), ("claimedAuthority", AUTHORITY_FIELDS)):
if set(observation[field]) != expected:
faults = add_issue(faults, "observation_shape_invalid", 1,
"Authority and effect maps must contain all documented fields.")
return True, faults
@@ -1,6 +1,6 @@
{
"errors": [],
"generated_at": "2026-10-30T15:27:34Z",
"generated_at": "2026-10-30T16:00:48Z",
"metrics": {
"_totals": {
"CONFIDENCE.HIGH": 0,
@@ -11,7 +11,7 @@
"SEVERITY.LOW": 0,
"SEVERITY.MEDIUM": 0,
"SEVERITY.UNDEFINED": 0,
"loc": 909,
"loc": 915,
"nosec": 0,
"skipped_tests": 0
},
@@ -37,7 +37,7 @@
"SEVERITY.LOW": 0,
"SEVERITY.MEDIUM": 0,
"SEVERITY.UNDEFINED": 0,
"loc": 585,
"loc": 591,
"nosec": 0,
"skipped_tests": 0
}
@@ -47,7 +47,7 @@
"scanner": "bandit",
"sha256": {
"skills/ecc-contribution-review/scripts/compile_contribution_review.py": "51be6d82e222eb7dcf35f6c2db55dd06dd04a480d6c5734d2e671bac1bbb820c",
"skills/ecc-contribution-review/scripts/contribution_review_validation.py": "f56d3a9a01a3393a41b3a546cbfe6b64cb7a28745b5e78939832d8bb40c7b932"
"skills/ecc-contribution-review/scripts/contribution_review_validation.py": "34420b91f55c5e2f1619e7f82d0d0ef920ffe119cbf2013e5ea7f7d62d382f35"
},
"version": "1.9.4"
}
@@ -1,12 +1,12 @@
{
"skills/ecc-contribution-review/agents/openai.yaml": "43a1fec439fa8ef2b1bb57f938a61df11ef78ef3c2e901038b8836868cb8e3b1",
"skills/ecc-contribution-review/scripts/compile_contribution_review.py": "51be6d82e222eb7dcf35f6c2db55dd06dd04a480d6c5734d2e671bac1bbb820c",
"skills/ecc-contribution-review/scripts/contribution_review_validation.py": "f56d3a9a01a3393a41b3a546cbfe6b64cb7a28745b5e78939832d8bb40c7b932",
"skills/ecc-contribution-review/scripts/contribution_review_validation.py": "34420b91f55c5e2f1619e7f82d0d0ef920ffe119cbf2013e5ea7f7d62d382f35",
"skills/ecc-contribution-review/tests/record_security_evidence.py": "527d5a4bb922fee759768e6f46f40404344075f314dfe045ed6e293aff0ff6c7",
"skills/ecc-contribution-review/tests/test_compile_contribution_review.py": "609e562330237f1cbd92ee500a4c2773b749c196085e6c8bef39dbc4d4c05cba",
"skills/ecc-contribution-review/tests/test_packet_review_fixes.py": "391f763657e48accfba29814100d284aee986200d9d10d6aa578d051fdb1d160",
"skills/ecc-contribution-review/tests/test_review_regressions.py": "956f8e7fb026a73a59226053bac167581bbf1644666824f81510396eb025f202",
"skills/ecc-contribution-review/tests/test_security_evidence.py": "e3d1d2f82612efa45343ab696aca84951b965ecbe6057051ea17633a7729ac76",
"skills/ecc-contribution-review/tests/test_security_regression.py": "6ff109c9d052bd6d8bf9a2e2dcd37f238e0d53c833c57caf051f54c6eff4b4d8",
"skills/ecc-contribution-review/tests/test_validation_findings.py": "7f1b93cfcb73b688a4e4ed09e95801ed385c67978e3e423f4b7adc060b0086e5"
"skills/ecc-contribution-review/tests/test_validation_findings.py": "ac3719be89b018e4d0f233d1d29ce333a246e7d1207934ba8b93b922e3ede4f3"
}
@@ -65,6 +65,51 @@ class ValidationFindingsTests(unittest.TestCase):
self.assertIn("observation_shape_invalid", [item["code"] for item in faults])
self.assertIn("unsafe_generated_authority", [item["code"] for item in contradictions])
def test_missing_claims_require_review_without_false_contradictions(self):
fields = [key for key in observation() if key.startswith("claims")]
for field in [*fields, "requestedEffects", "claimedAuthority"]:
with self.subTest(field=field):
data = observation()
del data[field]
packet = compile_contract(data, Path("observation.json"))
self.assertEqual("require_review", packet["controllerDecision"]["decision"])
faults, contradictions = validate(data)
self.assertIn("observation_envelope_incomplete", [item["code"] for item in faults])
self.assertEqual([], contradictions)
def test_missing_nested_members_require_review_but_preserve_present_claims(self):
for section in ("claimedAuthority", "requestedEffects"):
for field in observation()[section]:
with self.subTest(section=section, field=field):
data = observation()
del data[section][field]
faults, contradictions = validate(data)
self.assertIn("observation_shape_invalid", [item["code"] for item in faults])
self.assertEqual([], contradictions)
packet = compile_contract(data, Path("observation.json"))
self.assertEqual("require_review", packet["controllerDecision"]["decision"])
remaining = next(iter(data[section]))
data[section][remaining] = True
packet = compile_contract(data, Path("observation.json"))
self.assertEqual("reject", packet["controllerDecision"]["decision"])
def test_missing_field_preserves_explicit_claims_and_authority(self):
changes = (
("claimsPushPerformed", True, "push_claim_forbidden"),
("claimedAuthority", {"mayCommit": True}, "unsafe_generated_authority"),
("requestedEffects", {"pushRequested": True}, "external_action_requested"),
)
for field, value, code in changes:
with self.subTest(field=field):
data = observation()
del data["claimsCommitCreated"]
data[field] = value
data["validationMatrix"][0]["gateId"] = []
packet = compile_contract(data, Path("observation.json"))
self.assertEqual("reject", packet["controllerDecision"]["decision"])
self.assertIn(code, packet["controllerDecision"]["reasonCodes"])
self.assertNotIn("commit_claim_forbidden", packet["controllerDecision"]["reasonCodes"])
def test_invalid_top_level_section_does_not_hide_authority(self):
data = observation()
data["validationMatrix"] = None