diff --git a/scripts/policy_checker.py b/scripts/policy_checker.py new file mode 100755 index 0000000..59fe163 --- /dev/null +++ b/scripts/policy_checker.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""policy_checker.py — REQ-07 / D-025 + +Reads a contract.yaml and enforces the single Phase-03 policy rule: +`public-ingress: true` is forbidden. + +Input: argv[1] = path to a contract.yaml file. +Output: stdout "POLICY_PASS" or "POLICY_VIOLATION:PUBLIC_INGRESS" +Exit: 0 on pass, 1 on violation. + +Idempotent, no side effects (no file writes). Treats an absent or falsy +`public-ingress` key as a pass. +""" +import sys +import yaml + + +def main() -> int: + if len(sys.argv) < 2: + print("usage: policy_checker.py ", file=sys.stderr) + return 2 + + contract_path = sys.argv[1] + + try: + with open(contract_path, "r", encoding="utf-8") as fh: + contract = yaml.safe_load(fh) + except FileNotFoundError: + print(f"contract not found: {contract_path}", file=sys.stderr) + return 2 + except yaml.YAMLError as exc: + print(f"invalid yaml: {exc}", file=sys.stderr) + return 2 + + # Treat missing/non-mapping as no policy violation. + if not isinstance(contract, dict): + print("POLICY_PASS") + return 0 + + public_ingress = contract.get("public-ingress", False) + + if public_ingress is True: + print("POLICY_VIOLATION:PUBLIC_INGRESS") + return 1 + + print("POLICY_PASS") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file