#!/usr/bin/env python3 """CLI boundary for shell/native runtimes to consume Assurance Kernel policy.""" from __future__ import annotations import argparse import json import os import sys from pathlib import Path HARNESS_ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(HARNESS_ROOT)) from kernel.adapters import NativeHarnessAdapter # noqa: E402 from kernel.contracts import validate_bundle # noqa: E402 from kernel.policy import ( # noqa: E402 H2GateContext, evaluate_h2_gate, evaluate_registry_configuration, evaluate_risk, evaluate_trust_capabilities, ) def _print(payload: object) -> None: print(json.dumps(payload, sort_keys=True, separators=(",", ":"))) def _read_content(path: str | None) -> str: if not path: return "" with open(path, encoding="utf-8") as handle: return handle.read() def _append_jsonl(path: str, payload: object) -> None: target = Path(path) target.parent.mkdir(parents=True, exist_ok=True) data = (json.dumps(payload, sort_keys=True, separators=(",", ":")) + "\n").encode("utf-8") fd = os.open(str(target), os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600) try: try: import fcntl fcntl.flock(fd, fcntl.LOCK_EX) except (ImportError, OSError): pass os.write(fd, data) os.fsync(fd) finally: os.close(fd) def cmd_risk(args: argparse.Namespace) -> int: payload = evaluate_risk( action=args.action, tool=args.tool, resource=args.resource, command=args.command, content=_read_content(args.content_file), actor=args.actor, environment=args.environment, ) _print(payload) return 0 def cmd_registry(args: argparse.Namespace) -> int: payload = evaluate_registry_configuration(args.mode, args.profile, args.explicit) if args.evidence_log: _append_jsonl(args.evidence_log, payload) _print(payload) return 0 if payload["valid"] else 2 def cmd_h2(args: argparse.Namespace) -> int: context = H2GateContext( mode=args.mode, actor=args.actor, action=args.action, tool=args.tool, execution_id=args.execution_id, enforcement_path=args.enforcement_path, idempotency_key=args.idempotency_key, timeout_seconds=args.timeout, ) payload = evaluate_h2_gate(args.gate, context, bash_path=args.bash) if args.evidence_log: _append_jsonl(args.evidence_log, payload) _print(payload) return 0 if payload["execution_allowed"] else 2 def cmd_trust(_args: argparse.Namespace) -> int: payload = evaluate_trust_capabilities() _print(payload) return 0 if payload["ready"] else 2 def cmd_native(args: argparse.Namespace) -> int: event = json.load(sys.stdin) if args.event_file == "-" else json.load(open(args.event_file, encoding="utf-8")) payload = NativeHarnessAdapter().map_execution(event) errors = validate_bundle(payload) if errors: _print({"valid": False, "errors": errors, "bundle": payload}) return 2 _print(payload) return 0 def parser() -> argparse.ArgumentParser: root = argparse.ArgumentParser() sub = root.add_subparsers(dest="command", required=True) risk = sub.add_parser("risk") for name in ("action", "tool", "resource", "command", "actor", "environment"): risk.add_argument(f"--{name}", default="") risk.add_argument("--content-file") risk.set_defaults(func=cmd_risk) registry = sub.add_parser("registry-config") registry.add_argument("--mode", default="observe") registry.add_argument("--profile", default="development") registry.add_argument("--explicit") registry.add_argument("--evidence-log") registry.set_defaults(func=cmd_registry) h2 = sub.add_parser("h2-gate") h2.add_argument("--gate", required=True) h2.add_argument("--mode", choices=("observe", "enforce"), required=True) h2.add_argument("--actor", default="") h2.add_argument("--action", required=True) h2.add_argument("--tool", required=True) h2.add_argument("--execution-id", required=True) h2.add_argument("--enforcement-path", required=True) h2.add_argument("--idempotency-key", required=True) h2.add_argument("--timeout", type=float, default=8.0) h2.add_argument("--bash", default="bash") h2.add_argument("--evidence-log") h2.set_defaults(func=cmd_h2) trust = sub.add_parser("trust-capabilities") trust.set_defaults(func=cmd_trust) native = sub.add_parser("adapt-native") native.add_argument("event_file") native.set_defaults(func=cmd_native) return root def main() -> int: args = parser().parse_args() return int(args.func(args)) if __name__ == "__main__": raise SystemExit(main())