secrets-engine/scripts/check_layer_conformance.py
tegwick 906c6f1599
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Print the validated standard version and scope on every layer-conformance run
GH-DEC-2026-020 / A12 r2: the checker now walks every key and value of
the INTENT.md frontmatter and layer.yaml, so a versioned standard: or
companion: path and a companion_version are rejected, not only a key named
standard_version. schema_version and comments are not reached, and
pep-stance.yaml / evidence-classification.yaml keep their versions.
Every run prints VALIDATED_AGAINST and its scope, the PASS line included.
Declarations unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
2026-09-21 09:38:13 +02:00

315 lines
12 KiB
Python

#!/usr/bin/env python3
"""Check secrets-engine against the NetKingdom security layer model (§3.3, §6, §11).
Read-only. This is the Engine/Lifecycle adaptation of the ops-warden reference
checker. §5 Staff shapes do not apply to the owned OpenBao contact.
Two declaration forms are read. Per GH-DEC-2026-017 §1 (amendment A11)
INTENT.md's frontmatter `layer:` key governs; layer.yaml is a derived artifact
that must be marked derived, must name INTENT.md, and must agree with it. The
sidecar is still read, because a disagreement between the two is a finding in
its own right, reported rather than resolved away by precedence.
Layer values are compared against §3's closed four-token vocabulary after an
ASCII case-fold (GH-DEC-2026-017 §2-§3, amendment A9). Nothing is re-spelled:
`Engine` and `engine` are one token. Neither form carries a standard version
(GH-DEC-2026-017 §5, amendment A12 r2 / GH-DEC-2026-020), and its return is
rejected. The rule reaches content, not a key name: every key and value of the
INTENT.md frontmatter and of layer.yaml is walked, so a versioned `standard:` or
`companion:` path and a `companion_version` are caught as well as a
`standard_version`. Comments and `schema_version` are not reached. Stance maps
and evidence classifications (pep-stance.yaml, evidence-classification.yaml)
are not declarations and A12 is never applied to them (GH-DEC-2026-020 §3).
The version belongs to the run (GH-DEC-2026-020 §4): every run prints
VALIDATED_AGAINST and the scope it ranged over, including the PASS line.
Mechanical checks:
- INTENT.md frontmatter carries the governing `layer:` (Engine) and role
- layer.yaml is marked derived from INTENT.md and agrees with it after folding
- no authorization decision surface is exposed
- the PEP stance map is published at the path named in the declaration
- every OpenBao subprocess adapter lives in a module listed as owned tooling
Exit 0 clean, 1 finding, 2 declaration malformed.
"""
from __future__ import annotations
import argparse
import re
import sys
from pathlib import Path
import yaml
ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "src" / "secrets_engine"
DECL = ROOT / "layer.yaml"
INTENT = ROOT / "INTENT.md"
BAO_ARGV = re.compile(
r"""\[\s*(?:["']bao["']|bao_bin\b|bao_binary\b|self\.bao_bin)\s*,"""
)
DECISION_SURFACE = re.compile(
r"""\b(evaluate_policy|check_permission|render_decision|pdp_decide)\b"""
)
# §3's vocabulary: closed, four tokens, compared case-insensitively
# (GH-DEC-2026-017 §3, amendment A9). Taxonomy is in it.
LAYER_VOCABULARY = {"taxonomy", "tooling", "engine", "staff"}
EXPECTED_LAYER = "engine"
# The standard text this checker was built and validated against, printed on
# every run (GH-DEC-2026-020 §4, A12 r2). v0.7 is the accepted text in force;
# the v0.8 §11 amendments it already applies are named alongside. Bump this
# when the checker is re-validated against a newer accepted text.
VALIDATED_AGAINST = "net-kingdom/canon/standards/security-layer-model_v0.7.md"
AMENDMENTS_APPLIED = "v0.8 A9, A11, A12 r2 (GH-DEC-2026-017, GH-DEC-2026-020)"
SCOPE = (
"declaration = INTENT.md frontmatter + layer.yaml (every key and value); "
"source = src/secrets_engine/**/*.py; "
"not reached by A12: pep-stance.yaml, evidence-classification.yaml"
)
# A12 r2: a version of the standard or its companion, anywhere in the
# declaration. `schema_version` is the declaration file's own schema and is
# not reached.
VERSION_KEY = re.compile(r"version", re.IGNORECASE)
UNREACHED_KEYS = {"schema_version"}
VERSIONED_REF = re.compile(
r"(?i)(security-layer-model|security-companion|layer-model|companion)"
r"[^\s]*?(?:[_@-]v?\d+(?:\.\d+)*|\bv\d+(?:\.\d+)*)"
)
STANDARD_KEYS = {"standard", "companion", "framework"}
BARE_VERSION = re.compile(r"(?i)(?:^|[_@\s-])v?\d+\.\d+(?:\.\d+)*\b")
def _fold(value: object) -> str:
"""ASCII case-fold, per §3 as amended: two spellings of a token are one token."""
return str(value).strip().encode("ascii", "ignore").decode().lower()
def _version_hits(data: object, path: str = "") -> list[str]:
"""Every place a standard or companion version appears in a declaration."""
hits: list[str] = []
if isinstance(data, dict):
for key, value in data.items():
here = f"{path}.{key}" if path else str(key)
if str(key) in UNREACHED_KEYS:
continue
if VERSION_KEY.search(str(key)):
hits.append(f"key {here!r}")
continue
if isinstance(value, str) and str(key).lower() in STANDARD_KEYS:
if BARE_VERSION.search(value):
hits.append(f"{here}: {value!r}")
continue
hits.extend(_version_hits(value, here))
elif isinstance(data, list):
for n, item in enumerate(data):
hits.extend(_version_hits(item, f"{path}[{n}]"))
elif isinstance(data, str) and VERSIONED_REF.search(data):
hits.append(f"{path}: {data!r}")
return hits
def _no_standard_version(where: str, data: dict) -> None:
hits = _version_hits(data)
if hits:
print(
f"MALFORMED: {where} carries a standard or companion version at "
f"{'; '.join(hits)} — a layer declaration MUST NOT carry one in any "
"key or value (§11 as amended by A12 r2, GH-DEC-2026-020 §1-§2)"
)
raise SystemExit(2)
def _in_vocabulary(where: str, layer: object) -> None:
if _fold(layer) not in LAYER_VOCABULARY:
print(
f"MALFORMED: {where} declares layer {layer!r}, outside §3's closed "
f"vocabulary {sorted(LAYER_VOCABULARY)} (case-insensitive)"
)
raise SystemExit(2)
def load_declaration() -> dict:
if not DECL.exists():
print(f"MISSING: {DECL} — secrets-engine must declare in its own voice (§11)")
raise SystemExit(2)
decl = yaml.safe_load(DECL.read_text())
for key in (
"layer",
"role",
"repository",
"derived",
"derived_from",
"owned_tooling",
"decision_surfaces_exposed",
"pep_shaped",
"pep_stance",
):
if key not in decl:
print(f"MALFORMED: layer.yaml has no {key!r}")
raise SystemExit(2)
# §11 derived-artifact rule (GH-DEC-2026-017 §1): marked, naming its source.
if decl["derived"] is not True:
print("MALFORMED: layer.yaml must be marked 'derived: true' (§11, GH-DEC-2026-017 §1)")
raise SystemExit(2)
if decl["derived_from"] != "INTENT.md":
print(
f"MALFORMED: layer.yaml derives from {decl['derived_from']!r}; §11 names "
"INTENT.md as the governing declaration"
)
raise SystemExit(2)
_no_standard_version("layer.yaml", decl)
_in_vocabulary("layer.yaml", decl["layer"])
if decl["role"] != "lifecycle":
print(f"MALFORMED: declared role is {decl['role']!r}, expected 'lifecycle'")
raise SystemExit(2)
if decl["repository"] != "secrets-engine":
print(f"MALFORMED: repository is {decl['repository']!r}")
raise SystemExit(2)
return decl
def intent_frontmatter() -> dict:
text = INTENT.read_text(encoding="utf-8")
if not text.startswith("---"):
print("MALFORMED: INTENT.md has no YAML frontmatter (§11 / companion §2)")
raise SystemExit(2)
end = text.find("\n---", 3)
if end < 0:
print("MALFORMED: INTENT.md frontmatter is unclosed")
raise SystemExit(2)
front = yaml.safe_load(text[3:end]) or {}
if "layer" not in front:
print("MALFORMED: INTENT.md frontmatter has no 'layer' key — §11's declaration")
raise SystemExit(2)
_no_standard_version("INTENT.md frontmatter", front)
_in_vocabulary("INTENT.md frontmatter", front["layer"])
return front
def owned_modules(decl: dict) -> set[str]:
names: set[str] = set()
for entry in decl.get("owned_tooling", []):
for module in entry.get("modules", []):
names.add(Path(module).name)
return names
def scan_bao_modules() -> dict[str, list[int]]:
found: dict[str, list[int]] = {}
for path in sorted(SRC.rglob("*.py")):
hits: list[int] = []
for n, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
stripped = line.strip()
if stripped.startswith("#"):
continue
if BAO_ARGV.search(line):
hits.append(n)
if hits:
found[path.name] = hits
return found
def scan_decision_surfaces() -> dict[str, list[int]]:
found: dict[str, list[int]] = {}
for path in sorted(SRC.rglob("*.py")):
hits: list[int] = []
for n, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1):
if DECISION_SURFACE.search(line):
hits.append(n)
if hits:
found[path.name] = hits
return found
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--report", action="store_true")
args = ap.parse_args()
print(f"validated against: {VALIDATED_AGAINST} [{AMENDMENTS_APPLIED}]")
print(f"scope: {SCOPE}")
front = intent_frontmatter()
decl = load_declaration()
ok = True
governing = front["layer"]
if _fold(governing) != EXPECTED_LAYER:
ok = False
print(f"FINDING: INTENT.md frontmatter layer is {governing!r}, not Engine")
# §11 as amended (A11): a post-fold disagreement between the two forms is a
# finding in its own right, reported rather than resolved by precedence.
if _fold(decl["layer"]) != _fold(governing):
ok = False
print(
"FINDING: DECLARATION DISAGREEMENT (§11) — "
f"INTENT.md (governs) layer: {governing!r}; "
f"layer.yaml (derived) layer: {decl['layer']!r}. "
"Case is already folded; this is a disagreement about a layer."
)
if str(front.get("role", "")).lower() != "lifecycle":
ok = False
print("FINDING: INTENT.md frontmatter role is not Lifecycle")
if decl["decision_surfaces_exposed"] not in {None, "none"}:
ok = False
print("FINDING: decision_surfaces_exposed is not none — §6 forbids a second PDP")
surfaces = scan_decision_surfaces()
if surfaces:
ok = False
print("FINDING: possible authorization decision surface in source:")
for name, lines in sorted(surfaces.items()):
print(f" src/secrets_engine/{name}: line(s) {', '.join(map(str, lines[:6]))}")
stance = ROOT / str(decl["pep_stance"])
if decl.get("pep_shaped") and not stance.is_file():
ok = False
print(f"FINDING: pep_shaped but {decl['pep_stance']} is missing (§6.4 / §13.1)")
classification = decl.get("evidence_bound", {}).get("classification")
if classification and not (ROOT / str(classification)).is_file():
ok = False
print(f"FINDING: evidence classification {classification} is missing (§9.6)")
found = scan_bao_modules()
owned = owned_modules(decl)
undeclared = {name: lines for name, lines in found.items() if name not in owned}
if undeclared:
ok = False
print("FINDING: OpenBao adapter outside owned_tooling modules:")
for name, lines in sorted(undeclared.items()):
print(f" src/secrets_engine/{name}: line(s) {', '.join(map(str, lines[:6]))}")
if args.report:
print(
f"{decl['repository']} — layer: {governing} role: {front.get('role')} "
"(declared in INTENT.md; §11 governing form)"
)
print(f"layer.yaml: derived from {decl['derived_from']}, layer: {decl['layer']}")
print(f"declared by {decl['declared_by']}")
print(f"pep stance: {decl['pep_stance']}")
print(f"owned OpenBao modules: {sorted(owned)}")
print(f"OpenBao argv adapters found: {sorted(found)}")
if ok and not args.report:
print(
"PASS — Engine/Lifecycle declaration present, no decision surface, "
f"{len(found)} OpenBao adapter module(s) owned; "
f"validated against {VALIDATED_AGAINST}."
)
elif ok:
print(
"\nPASS — declaration, owned tooling, and PEP stance path hold; "
f"validated against {VALIDATED_AGAINST}."
)
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())