diff --git a/scripts/pre1_harness_binding.py b/scripts/pre1_harness_binding.py index a00cde1..e7a0653 100644 --- a/scripts/pre1_harness_binding.py +++ b/scripts/pre1_harness_binding.py @@ -24,6 +24,14 @@ }) +# Quality workflows remain bound by the full harness commit/tree digest. +# This classification grants no merge, release or required-check authority. +CI_ONLY_PATHS = frozenset({ + ".github/workflows/quality.yml", + ".github/workflows/ci.yml", +}) + + def git(root: Path, *argv: str) -> bytes: return subprocess.check_output( ["git", *argv], cwd=root, stderr=subprocess.PIPE, timeout=30 @@ -67,5 +75,5 @@ def validate_harness_source( root, "diff", "--no-renames", "--name-only", "-z", product_source_commit, binding["harness_source_commit"], "--" ).decode().split("\0") - if set(filter(None, changes)) - TOOL_ONLY_PATHS: + if set(filter(None, changes)) - (TOOL_ONLY_PATHS | CI_ONLY_PATHS): raise ValueError("qualification tooling revision changes frozen product source") diff --git a/scripts/test_pre1_qualification_case.py b/scripts/test_pre1_qualification_case.py index f25c134..84a1f6f 100755 --- a/scripts/test_pre1_qualification_case.py +++ b/scripts/test_pre1_qualification_case.py @@ -235,5 +235,22 @@ def test_rehashed_invalid_dependency_hash_is_not_accepted(self): self.check(value, runtime) +class QualityWorkflowBoundaryTests(unittest.TestCase): + def check_changes(self, paths): + from unittest.mock import patch + import pre1_harness_binding as binding + identity = {"harness_source_commit": "1" * 40, "harness_sha256": "sha256:" + "2" * 64} + with patch.object(binding, "harness_identity", return_value=identity), patch.object(binding, "git", side_effect=[b"", ("\0".join(paths) + "\0").encode()]): + binding.validate_harness_source(ROOT, "3" * 40, identity) + + def test_reviewed_quality_workflows_are_digest_bound_tooling(self): + self.check_changes([".github/workflows/quality.yml", ".github/workflows/ci.yml"]) + + def test_release_dependencies_and_runtime_remain_frozen(self): + for path in [".github/workflows/release.yml", ".github/workflows/other.yml", "Cargo.lock", "Cargo.toml", "src/lib.rs"]: + with self.subTest(path=path), self.assertRaisesRegex(ValueError, "frozen product source"): + self.check_changes([path]) + + if __name__ == "__main__": unittest.main()