#!/usr/bin/env python3 """Check zone-engine against the NetKingdom security layer model (§5, §6, §11). Read-only. This repository's position is: Engine / PIP for zone identity and membership, offline reference conformance, no Tooling-layer client, no HTTP authorization decision surface, no PEP. §11 requires a machine-readable declaration that agrees with INTENT.md frontmatter. This script is what makes that claim checkable: it fails if layer.yaml is missing, disagrees with INTENT.md, or if a Tooling client or decision surface appears under tools/. The failure it exists to catch is a *convenience* — a live lookup, an OpenBao client, or an /authorize helper "just for this consumer". That is this repository's original §7 falsifier, now statute §6. Review dates are reported, never enforced: a date-triggered failure breaks the build on a calendar day with no code change. Exit 0 clean, 1 undeclared contact or decision surface, 2 declaration malformed or in disagreement with INTENT.md. """ from __future__ import annotations import argparse import ast import sys from datetime import date from pathlib import Path from typing import Any, Iterable, Mapping import yaml ROOT = Path(__file__).resolve().parents[1] TOOLS = ROOT / "tools" DECL = ROOT / "layer.yaml" INTENT = ROOT / "INTENT.md" TOOLING_IMPORTS = { "hvac": "OpenBao / Vault client", "bao": "OpenBao client", "kubernetes": "cluster client", "kubernetes_asyncio": "cluster client", "psycopg": "direct database connection", "psycopg2": "direct database connection", "asyncpg": "direct database connection", "sqlalchemy": "direct database connection", "pymysql": "direct database connection", "redis": "direct datastore connection", "ldap3": "direct LDAP client (key-cape tooling)", "python_ldap": "direct LDAP client (key-cape tooling)", "docker": "container runtime client", } HTTP_SURFACE_IMPORTS = { "flask": "HTTP framework", "fastapi": "HTTP framework", "starlette": "HTTP framework", "aiohttp": "HTTP framework", "tornado": "HTTP framework", "bottle": "HTTP framework", "quart": "HTTP framework", "sanic": "HTTP framework", "django": "HTTP framework", "gunicorn": "HTTP server", "uvicorn": "HTTP server", "hypercorn": "HTTP server", "waitress": "HTTP server", } DECISION_PATHS = ("/authorize", "/v1/check", "/v1/authorize") class ConformanceError(ValueError): """Declaration is missing, unparseable, or disagrees with INTENT.md.""" def _frontmatter(path: Path) -> dict[str, Any]: text = path.read_text() if not text.startswith("---\n") or "\n---\n" not in text[4:]: raise ConformanceError(f"{path.name} requires YAML frontmatter") raw = text.split("\n---\n", 1)[0][4:] value = yaml.safe_load(raw) or {} if not isinstance(value, Mapping): raise ConformanceError(f"{path.name} frontmatter must be a mapping") return dict(value) def load_declaration(path: Path = DECL) -> dict[str, Any]: if not path.exists(): raise ConformanceError(f"no declaration at {path.name} (§11)") try: data = yaml.safe_load(path.read_text()) except yaml.YAMLError as exc: raise ConformanceError(f"{path.name} is not parseable: {exc}") from exc if not isinstance(data, Mapping): raise ConformanceError(f"{path.name} must be a mapping") for key in ("layer", "role", "repository", "tooling_contacts", "standard_version"): if key not in data: raise ConformanceError(f"{path.name} missing required key '{key}' (§11)") return dict(data) def load_intent(path: Path = INTENT) -> dict[str, Any]: if not path.exists(): raise ConformanceError(f"no INTENT.md at {path}") return _frontmatter(path) def _norm(value: Any) -> str: return str(value or "").strip().lower() def check_declaration_agrees( decl: Mapping[str, Any], intent: Mapping[str, Any] ) -> list[str]: errors: list[str] = [] if _norm(decl.get("layer")) != "engine": errors.append(f"declared layer is '{decl.get('layer')}', expected 'engine'") if _norm(decl.get("role")) != "pip": errors.append(f"declared role is '{decl.get('role')}', expected 'pip'") if _norm(intent.get("layer")) != _norm(decl.get("layer")): errors.append( f"INTENT.md layer '{intent.get('layer')}' disagrees with " f"layer.yaml '{decl.get('layer')}'" ) if _norm(intent.get("role")) != _norm(decl.get("role")): errors.append( f"INTENT.md role '{intent.get('role')}' disagrees with " f"layer.yaml '{decl.get('role')}'" ) if decl.get("repository") != "zone-engine": errors.append(f"declared repository is '{decl.get('repository')}'") if decl.get("pep_stance"): errors.append("pep_stance is set; this repository is not PEP-shaped") contacts = decl.get("tooling_contacts") if contacts not in ([], None): errors.append( "tooling_contacts is not empty; a new contact needs a §10 cut, " "not a quiet row" ) return errors def imported_modules(path: Path) -> set[str]: try: tree = ast.parse(path.read_text()) except SyntaxError: return set() found: set[str] = set() for node in ast.walk(tree): if isinstance(node, ast.Import): found.update(alias.name.split(".")[0] for alias in node.names) elif isinstance(node, ast.ImportFrom): if node.level == 0 and node.module: found.add(node.module.split(".")[0]) return found def string_literals(path: Path) -> list[str]: try: tree = ast.parse(path.read_text()) except SyntaxError: return [] found: list[str] = [] for node in ast.walk(tree): if isinstance(node, ast.Constant) and isinstance(node.value, str): found.append(node.value) return found def scan_tooling(directory: Path) -> list[tuple[Path, str, str]]: hits: list[tuple[Path, str, str]] = [] for path in sorted(directory.rglob("*.py")): for module in sorted(imported_modules(path)): if module in TOOLING_IMPORTS: hits.append((path, module, TOOLING_IMPORTS[module])) return hits def scan_decision_surfaces(directory: Path) -> list[tuple[Path, str, str]]: hits: list[tuple[Path, str, str]] = [] for path in sorted(directory.rglob("*.py")): if path.resolve() == Path(__file__).resolve(): continue for module in sorted(imported_modules(path)): if module in HTTP_SURFACE_IMPORTS: hits.append((path, module, HTTP_SURFACE_IMPORTS[module])) if module == "http": # http.server is the stdlib decision-adjacent live surface. text = path.read_text() if "http.server" in text: hits.append((path, "http.server", "stdlib HTTP server")) for literal in string_literals(path): for needle in DECISION_PATHS: if needle in literal: hits.append((path, literal, f"authorization path {needle}")) return hits def overdue_reviews(decl: Mapping[str, Any], today: date | None = None) -> list[str]: today = today or date.today() notes: list[str] = [] for cap in decl.get("unowned_capabilities") or []: review = cap.get("review") if not review: continue try: due = date.fromisoformat(str(review)) except ValueError: notes.append(f"{cap.get('id')}: unparseable review date {review!r}") continue if due < today: notes.append(f"{cap.get('id')}: review overdue ({review})") return notes def evaluate( *, root: Path | None = None, tools: Path | None = None, decl_path: Path | None = None, intent_path: Path | None = None, ) -> tuple[int, list[str], list[str]]: """Return (exit_code, errors, reports). Exit 2 for declaration, 1 for tree.""" root = root or ROOT tools = tools or (root / "tools") decl_path = decl_path or (root / "layer.yaml") intent_path = intent_path or (root / "INTENT.md") try: decl = load_declaration(decl_path) intent = load_intent(intent_path) except ConformanceError as exc: return 2, [str(exc)], [] errors = check_declaration_agrees(decl, intent) if errors: return 2, errors, [] reports = overdue_reviews(decl) tree_errors: list[str] = [] for path, module, what in scan_tooling(tools): rel = path.relative_to(root) if path.is_relative_to(root) else path tree_errors.append(f"{rel}: imports '{module}' — {what}") for path, token, what in scan_decision_surfaces(tools): rel = path.relative_to(root) if path.is_relative_to(root) else path tree_errors.append(f"{rel}: {what} ({token})") if tree_errors: return 1, tree_errors, reports return 0, [], reports def main(argv: Iterable[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--report", action="store_true", help="print the declaration summary") args = parser.parse_args(list(argv) if argv is not None else None) code, errors, reports = evaluate() if args.report: try: decl = load_declaration() except ConformanceError as exc: print(f"FAIL: {exc}", file=sys.stderr) return 2 print( f"zone-engine — layer {decl['layer']}, role {decl['role']}, " f"standard v{decl['standard_version']}" ) print(f" tooling contacts declared: {len(decl.get('tooling_contacts') or [])}") print(f" pep_stance: {decl.get('pep_stance')!r}") for note in reports: print(f" review: {note}") if code == 2: print("FAIL: layer declaration malformed or disagrees with INTENT.md (§11)", file=sys.stderr) for item in errors: print(f" {item}", file=sys.stderr) return 2 if code == 1: print("FAIL: undeclared Tooling client or HTTP decision surface (§6, §11)", file=sys.stderr) for item in errors: print(f" {item}", file=sys.stderr) print("", file=sys.stderr) print(" A live API, Tooling client, or /authorize helper is a layer change.", file=sys.stderr) print(" Do not declare it to make the check pass.", file=sys.stderr) return 1 if not args.report: print(f"OK: Engine/PIP declaration agrees with INTENT.md; no Tooling client or decision surface in {TOOLS.relative_to(ROOT)}") return 0 if __name__ == "__main__": raise SystemExit(main())