#!/usr/bin/env python3 """Register or inspect a revision-pinned T02 synthetic-load driver candidate. Registration reads and hashes committed source. It never executes the driver, reads a bearer, or authorizes the live database-lease exercise. """ from __future__ import annotations import argparse import hashlib import json import os import re import subprocess import sys import urllib.error import urllib.parse import urllib.request from datetime import UTC, datetime from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] DEFAULT_CONTRACT = ROOT / "interfaces" / "RAILIANCE-WP-0024-T02-synthetic-load-driver.json" DEFAULT_AUDIT_REPO = ROOT.parent / "audit-core" DEFAULT_API_BASE = os.environ.get("STATE_HUB_URL", "http://127.0.0.1:8000") PREFIX = "WP0024-T02-DRIVER-CANDIDATE" class CandidateError(RuntimeError): pass def canonical(value: Any) -> str: return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=True) def digest(value: bytes) -> str: return hashlib.sha256(value).hexdigest() def load_contract(path: Path = DEFAULT_CONTRACT) -> dict[str, Any]: try: value = json.loads(path.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError) as exc: raise CandidateError("synthetic-load contract is unavailable or invalid") from exc if ( not isinstance(value, dict) or value.get("interface") != "railiance.synthetic-load-driver" or value.get("version") != 1 or value.get("task_id") != "RAILIANCE-WP-0024-T02" or value.get("owner") != "audit-core" ): raise CandidateError("unsupported synthetic-load contract") phases = value.get("phases") if not isinstance(phases, dict) or set(phases) != { "baseline", "expect-unavailable", "expect-recovered", "cleanup" }: raise CandidateError("synthetic-load contract has the wrong phase set") for phase, record in phases.items(): if not isinstance(record, dict) or not record.get("keys") or not record.get("status"): raise CandidateError(f"synthetic-load phase is incomplete: {phase}") return value def contract_digest(contract: dict[str, Any]) -> str: return digest(canonical(contract).encode("utf-8")) def run_git(repo: Path, args: list[str]) -> str: completed = subprocess.run( ["git", "-C", str(repo), *args], text=True, capture_output=True, check=False ) if completed.returncode != 0: raise CandidateError("cannot resolve committed driver source") return completed.stdout.strip() def inspect_driver(repo: Path, source_path: str) -> dict[str, str]: repo = repo.resolve() target = (repo / source_path).resolve() try: relative = target.relative_to(repo).as_posix() except ValueError as exc: raise CandidateError("driver path escapes the audit-core repository") from exc if not target.is_file() or not os.access(target, os.X_OK): raise CandidateError("driver candidate must be an executable file") if run_git(repo, ["status", "--porcelain", "--", relative]): raise CandidateError("driver candidate must be committed with no path-local changes") tracked = run_git(repo, ["ls-files", "--error-unmatch", "--", relative]) if tracked != relative: raise CandidateError("driver candidate is not tracked at the requested path") revision = run_git(repo, ["log", "-1", "--format=%H", "--", relative]) if not re.fullmatch(r"[0-9a-f]{40}", revision): raise CandidateError("driver source revision is not a full Git commit") return { "source_repo": "audit-core", "source_revision": revision, "source_path": relative, "driver_revision": "sha256:" + digest(target.read_bytes()), } def reviewer(value: str) -> str: if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._:@/+\-]{1,127}", value): raise CandidateError("reviewer must be a stable 2-128 character identifier") return value def build_receipt( contract: dict[str, Any], source: dict[str, str], reviewer_id: str, *, now: datetime | None = None, ) -> dict[str, Any]: return { "interface": "railiance.synthetic-load-driver-candidate", "version": 1, "workplan_id": contract["workplan_id"], "task_id": contract["task_id"], "contract_id": contract["contract_id"], "contract_digest": contract_digest(contract), "owner": "audit-core", "reviewer": reviewer(reviewer_id), **source, "created_at": (now or datetime.now(UTC)).astimezone(UTC).isoformat().replace("+00:00", "Z"), "registration_executed_driver": False, "secret_values_observed": False, } def subject(receipt: dict[str, Any]) -> str: return "/".join((PREFIX, "v1", receipt["contract_digest"], receipt["driver_revision"][7:])) def http_json(method: str, url: str, payload: dict[str, Any] | None = None) -> Any: data = canonical(payload).encode("utf-8") if payload is not None else None request = urllib.request.Request( url, data=data, method=method, headers={"Content-Type": "application/json"} if data else {}, ) try: with urllib.request.urlopen(request, timeout=10) as response: return json.loads(response.read().decode("utf-8")) except (OSError, urllib.error.URLError, json.JSONDecodeError) as exc: raise CandidateError(f"State Hub request failed: {method} {url}") from exc def post(receipt: dict[str, Any], api_base: str) -> dict[str, Any]: value = http_json( "POST", f"{api_base.rstrip('/')}/messages/", { "from_agent": "audit-core", "to_agent": "railiance-platform", "subject": subject(receipt), "body": canonical(receipt), }, ) if not isinstance(value, dict): raise CandidateError("State Hub returned an invalid candidate response") return value def parse_message(message: dict[str, Any], contract: dict[str, Any]) -> dict[str, Any] | None: if message.get("from_agent") != "audit-core": return None try: receipt = json.loads(message["body"]) except (KeyError, TypeError, json.JSONDecodeError): return None if not isinstance(receipt, dict): return None try: valid = ( message.get("subject") == subject(receipt) and receipt.get("interface") == "railiance.synthetic-load-driver-candidate" and receipt.get("version") == 1 and receipt.get("task_id") == contract["task_id"] and receipt.get("contract_id") == contract["contract_id"] and receipt.get("contract_digest") == contract_digest(contract) and receipt.get("owner") == "audit-core" and receipt.get("source_repo") == "audit-core" and re.fullmatch(r"[0-9a-f]{40}", receipt.get("source_revision", "")) and re.fullmatch(r"sha256:[0-9a-f]{64}", receipt.get("driver_revision", "")) and receipt.get("registration_executed_driver") is False and receipt.get("secret_values_observed") is False ) except (KeyError, TypeError): return None return receipt if valid else None def status(contract: dict[str, Any], api_base: str) -> dict[str, Any]: query = urllib.parse.urlencode({"to_agent": "railiance-platform", "limit": 500}) value = http_json("GET", f"{api_base.rstrip('/')}/messages/?{query}") if not isinstance(value, list): raise CandidateError("State Hub messages response is not a list") candidates = [item for message in value if (item := parse_message(message, contract))] latest = max(candidates, key=lambda item: item.get("created_at", ""), default=None) return { "interface": contract["interface"], "version": contract["version"], "task_id": contract["task_id"], "contract_id": contract["contract_id"], "contract_digest": contract_digest(contract), "candidate_registered": latest is not None, "candidate": latest, } def parser() -> argparse.ArgumentParser: result = argparse.ArgumentParser(description=__doc__) result.add_argument("--contract", type=Path, default=DEFAULT_CONTRACT) result.add_argument("--api-base", default=DEFAULT_API_BASE) sub = result.add_subparsers(dest="command", required=True) sub.add_parser("show") register = sub.add_parser("register") register.add_argument("--repo", type=Path, default=DEFAULT_AUDIT_REPO) register.add_argument("--driver", required=True, help="path relative to the audit-core repo") register.add_argument("--reviewer", required=True) sub.add_parser("status") return result def main(argv: list[str] | None = None) -> int: args = parser().parse_args(argv) try: contract = load_contract(args.contract) if args.command == "show": output = {**contract, "contract_digest": contract_digest(contract)} elif args.command == "register": source = inspect_driver(args.repo, args.driver) receipt = build_receipt(contract, source, args.reviewer) response = post(receipt, args.api_base) output = {"submitted": True, "message_id": response.get("id"), "receipt": receipt} else: output = status(contract, args.api_base) except CandidateError as exc: print(canonical({"ok": False, "error": str(exc)}), file=sys.stderr) return 2 print(json.dumps(output, indent=2, sort_keys=True)) return 0 if __name__ == "__main__": raise SystemExit(main())