Skip to content

Commit 936c1df

Browse files
committed
scripts: add runtime refusal receipt v0.2 validator
1 parent 5205707 commit 936c1df

1 file changed

Lines changed: 119 additions & 0 deletions

File tree

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Validate Runtime Refusal Receipt v0.2 examples.
4+
5+
This validator performs two checks:
6+
1. JSON Schema validation.
7+
2. Local semantic checks for the synthetic receipt examples.
8+
9+
Claim boundary:
10+
This validates receipt shape and internal semantic consistency only.
11+
It does not prove downstream non-execution, production enforcement, compliance,
12+
medical safety, financial safety, adoption, or path-universal coverage.
13+
"""
14+
15+
from __future__ import annotations
16+
17+
import copy
18+
import hashlib
19+
import json
20+
from pathlib import Path
21+
22+
try:
23+
import jsonschema
24+
except ImportError as exc: # pragma: no cover
25+
raise SystemExit(
26+
"Missing dependency: jsonschema\n"
27+
"Install it with: python -m pip install jsonschema"
28+
) from exc
29+
30+
31+
ROOT = Path(__file__).resolve().parents[1]
32+
SCHEMA_PATH = ROOT / "docs" / "schemas" / "Runtime_Refusal_Receipt_Schema_v0.2.json"
33+
EXAMPLES_DIR = ROOT / "docs" / "schemas" / "examples"
34+
HASH_PLACEHOLDER = "sha256:SELF_HASH_EXCLUDED"
35+
36+
37+
def load_json(path: Path) -> dict:
38+
with path.open("r", encoding="utf-8") as handle:
39+
return json.load(handle)
40+
41+
42+
def canonical_json(value: dict) -> str:
43+
return json.dumps(value, sort_keys=True, separators=(",", ":"))
44+
45+
46+
def expected_receipt_hash(receipt: dict) -> str:
47+
copied = copy.deepcopy(receipt)
48+
copied["receipt_hash"] = HASH_PLACEHOLDER
49+
return "sha256:" + hashlib.sha256(canonical_json(copied).encode("utf-8")).hexdigest()
50+
51+
52+
def require(condition: bool, message: str) -> None:
53+
if not condition:
54+
raise ValueError(message)
55+
56+
57+
def semantic_checks(receipt: dict) -> None:
58+
verdict = receipt["verdict"]
59+
state = receipt["state"]
60+
scope = receipt["scope"]
61+
replay = receipt["replay"]
62+
downstream_status = receipt["claimed_downstream_effect_status"]
63+
64+
require(verdict != "ALLOW", "ALLOW is not permitted in Runtime Refusal Receipt v0.2.")
65+
66+
if verdict in {"REFUSE", "BLOCKED", "STATE_CONFLICT", "OUT_OF_SCOPE", "REPLAY_BLOCKED"}:
67+
require(state["execution_permitted"] is False, f"{verdict} requires state.execution_permitted=false.")
68+
69+
if verdict == "OUT_OF_SCOPE":
70+
require(scope["scope_match"] is False, "OUT_OF_SCOPE requires scope.scope_match=false.")
71+
72+
if verdict == "REPLAY_BLOCKED":
73+
require(replay["replay_detected"] is True, "REPLAY_BLOCKED requires replay.replay_detected=true.")
74+
75+
if verdict == "STATE_CONFLICT":
76+
require(state["execution_permitted"] is False, "STATE_CONFLICT requires execution_permitted=false.")
77+
78+
if downstream_status == "VERIFIED_NOT_COMMITTED":
79+
evidence_types = {item["type"] for item in receipt["evidence"]}
80+
require(
81+
"EXTERNAL_VERIFICATION" in evidence_types or "CODE_EXECUTION" in evidence_types,
82+
"VERIFIED_NOT_COMMITTED requires EXTERNAL_VERIFICATION or CODE_EXECUTION evidence.",
83+
)
84+
85+
require(
86+
receipt["receipt_hash"] == expected_receipt_hash(receipt),
87+
"receipt_hash does not match canonical hash with receipt_hash excluded.",
88+
)
89+
90+
91+
def main() -> int:
92+
schema = load_json(SCHEMA_PATH)
93+
example_paths = sorted(EXAMPLES_DIR.glob("runtime_refusal_receipt_*_v0.2.json"))
94+
95+
if not example_paths:
96+
raise SystemExit("No Runtime Refusal Receipt v0.2 examples found.")
97+
98+
print("Runtime Refusal Receipt v0.2 Examples: VALID")
99+
print(f"Examples checked: {len(example_paths)}")
100+
print("")
101+
102+
for path in example_paths:
103+
receipt = load_json(path)
104+
jsonschema.validate(instance=receipt, schema=schema)
105+
semantic_checks(receipt)
106+
print(f"- {path.name}")
107+
print(f" Receipt: {receipt['id']}")
108+
print(f" Verdict: {receipt['verdict']}")
109+
print(f" Action class: {receipt['action_class']}")
110+
print(f" Downstream status: {receipt['claimed_downstream_effect_status']}")
111+
print("")
112+
113+
print("Claim boundary: schema-valid and semantically consistent synthetic receipts only.")
114+
print("This does not prove downstream non-execution or production enforcement.")
115+
return 0
116+
117+
118+
if __name__ == "__main__":
119+
raise SystemExit(main())

0 commit comments

Comments
 (0)