maturity-engine/scripts/check_layer_conformance.py

143 lines
4.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Check maturity-engine against the NetKingdom security layer model (§5, §11).
This is an Engine (PIP). The checkable claims:
- layer.yaml declares layer=engine, role=pip
- INTENT.md frontmatter agrees (case-insensitive)
- no pep_stance path
- no catalogued Tooling client (OpenBao, key-cape, cluster)
- sqlite3 is this PIP's own store and is allowed
Exit 0 clean, 1 undeclared Tooling contact, 2 declaration malformed.
"""
from __future__ import annotations
import argparse
import ast
import re
import sys
from pathlib import Path
import yaml
ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "src" / "maturity_engine"
DECL = ROOT / "layer.yaml"
INTENT = ROOT / "INTENT.md"
TOOLING_IMPORTS = {
"hvac": "OpenBao / Vault client",
"bao": "OpenBao client",
"kubernetes": "cluster client",
"kubernetes_asyncio": "cluster client",
"ldap3": "direct LDAP client (key-cape tooling)",
"python_ldap": "direct LDAP client (key-cape tooling)",
}
def load_declaration() -> dict:
if not DECL.exists():
print(f"FAIL: no declaration at {DECL.relative_to(ROOT)} (§11)", file=sys.stderr)
raise SystemExit(2)
try:
data = yaml.safe_load(DECL.read_text())
except yaml.YAMLError as exc:
print(f"FAIL: {DECL.name} is not parseable: {exc}", file=sys.stderr)
raise SystemExit(2) from exc
for key in ("layer", "role", "repository", "tooling_contacts", "standard_version"):
if key not in data:
print(f"FAIL: {DECL.name} missing required key '{key}' (§11)", file=sys.stderr)
raise SystemExit(2)
if str(data["layer"]).lower() != "engine":
print(f"FAIL: declared layer is {data['layer']!r}, expected 'engine'", file=sys.stderr)
raise SystemExit(2)
if str(data["role"]).lower() != "pip":
print(f"FAIL: declared role is {data['role']!r}, expected 'pip'", file=sys.stderr)
raise SystemExit(2)
if data.get("pep_stance"):
print("FAIL: pep_stance is set; this engine is not PEP-shaped", file=sys.stderr)
raise SystemExit(2)
return data
def intent_frontmatter() -> dict:
text = INTENT.read_text()
match = re.match(r"^---\n(.*?)\n---\n", text, re.DOTALL)
if not match:
print("FAIL: INTENT.md has no YAML frontmatter (§11)", file=sys.stderr)
raise SystemExit(2)
meta = yaml.safe_load(match.group(1))
if not isinstance(meta, dict):
print("FAIL: INTENT.md frontmatter is not a mapping", file=sys.stderr)
raise SystemExit(2)
return meta
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 scan() -> list[tuple[Path, str, str]]:
hits: list[tuple[Path, str, str]] = []
for path in sorted(SRC.rglob("*.py")):
for module in sorted(imported_modules(path)):
if module in TOOLING_IMPORTS:
hits.append((path, module, TOOLING_IMPORTS[module]))
return hits
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--report", action="store_true")
args = parser.parse_args()
decl = load_declaration()
intent = intent_frontmatter()
if str(intent.get("layer", "")).lower() != str(decl["layer"]).lower():
print(
f"FAIL: INTENT.md layer {intent.get('layer')!r} != layer.yaml {decl['layer']!r}",
file=sys.stderr,
)
return 2
if str(intent.get("role", "")).lower() != str(decl["role"]).lower():
print(
f"FAIL: INTENT.md role {intent.get('role')!r} != layer.yaml {decl['role']!r}",
file=sys.stderr,
)
return 2
hits = scan()
if hits:
print("FAIL: catalogued Tooling-layer client in an Engine that does not own it", file=sys.stderr)
for path, module, what in hits:
print(f" {path.relative_to(ROOT)}: imports {module!r}{what}", file=sys.stderr)
return 1
if args.report:
print(
f"maturity-engine — layer {decl['layer']}, role {decl['role']}, "
f"standard v{decl['standard_version']}"
)
print(f" tooling contacts: {len(decl.get('tooling_contacts') or [])}")
print(f" non-tooling clients: {len(decl.get('non_tooling_clients') or [])}")
print(" pep_stance: none")
else:
print(f"OK: Engine/PIP declaration holds; no catalogued Tooling client in {SRC.relative_to(ROOT)}")
return 0
if __name__ == "__main__":
raise SystemExit(main())