mirror of
https://github.com/affaan-m/ECC.git
synced 2026-11-07 08:35:54 +00:00
fix: distinguish absent authority fields from forbidden claims
This commit is contained in:
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
|
||||
|
||||
Reference in new issue
Block a user