Converge layer checker on GH-DEC-2026-021.
VALIDATED_AGAINST names v0.7 at net-kingdom@66dc491 as amended by GH-DEC-2026-017/020/021 (gate-house@39d9287). The version detector adopts ops-warden's estate reference: identity-bearing standard:/companion: values carrying a version token are pins; keys naming neither are not reached. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 58902@bnt-lap001 Assistant-Session: 7ac7f865-2dc5-4aa7-8eb7-27a342109c2f
This commit is contained in:
parent
a7312baafc
commit
abd4bf1fd8
2 changed files with 33 additions and 10 deletions
|
|
@ -30,10 +30,14 @@ sys.path.insert(0, str(ROOT / "src"))
|
|||
|
||||
from user_engine.layer_yaml import load_mapping, load_mapping_text # noqa: E402
|
||||
|
||||
# The standard text this checker was built and validated against. The version
|
||||
# belongs to the run, not to the declaration (GH-DEC-2026-020 §4, A12 r2); it is
|
||||
# printed on every run. Bump it when the checker is re-validated.
|
||||
VALIDATED_AGAINST = "net-kingdom/canon/standards/security-layer-model_v0.7.md"
|
||||
# What every run checks against, printed on every run (GH-DEC-2026-020 §4,
|
||||
# GH-DEC-2026-021 §2). The accepted text is v0.7 at net-kingdom@66dc491; the
|
||||
# decision records whose rulings this checker enforces beyond v0.7 are named with it.
|
||||
VALIDATED_AGAINST = (
|
||||
"net-kingdom/canon/standards/security-layer-model_v0.7.md (net-kingdom@66dc491) "
|
||||
"as amended by GH-DEC-2026-017, GH-DEC-2026-020 and GH-DEC-2026-021 "
|
||||
"(A9-A13, A12 r3; gate-house@39d9287)"
|
||||
)
|
||||
|
||||
# What every run ranges over. Stance, claims and classification maps
|
||||
# (pep-stance.yaml) are not declarations and are not checked for versions
|
||||
|
|
@ -45,9 +49,15 @@ SCOPE = (
|
|||
|
||||
# A12 r2: no standard or companion version in any key or value of the
|
||||
# declaration. Comments are not parsed; schema_version is not reached.
|
||||
VERSION_KEY = re.compile(r"(?:^|_)version$", re.IGNORECASE)
|
||||
VERSION_VALUE = re.compile(r"(?:^|[_\-/\s])v?\d+\.\d+(?:\.\d+)*(?:\.md)?(?=$|[\s/])|_v\d+", re.IGNORECASE)
|
||||
# Detector converged on the estate reference, ops-warden's (GH-DEC-2026-021 §3):
|
||||
# a version token (`v?N.N`) in an identity-bearing value (`standard:`,
|
||||
# `companion:`) is a pin (A12 r3); keys naming neither, e.g. `intent_version`,
|
||||
# are not reached.
|
||||
VERSION_KEY = re.compile(r"(standard|companion).*version|version.*(standard|companion)", re.I)
|
||||
VERSION_VALUE = re.compile(r"[_\-.]v\d+(\.\d+)*(\.md)?\b|@v?\d+\.\d+", re.I)
|
||||
UNREACHED_KEYS = {"schema_version"}
|
||||
IDENTITY_KEYS = {"standard", "companion"}
|
||||
IDENTITY_VERSION = re.compile(r"\bv?\d+\.\d+", re.I)
|
||||
|
||||
TOOLING_IMPORTS = {
|
||||
"hvac": "OpenBao / Vault client",
|
||||
|
|
@ -81,7 +91,9 @@ def fold(value: object) -> str:
|
|||
)
|
||||
|
||||
|
||||
def find_versions(node: object, where: str, path: str = "") -> list[str]:
|
||||
def find_versions(
|
||||
node: object, where: str, path: str = "", identity: bool = False
|
||||
) -> list[str]:
|
||||
"""Every key or value in a declaration that carries a version (A12 r2)."""
|
||||
found: list[str] = []
|
||||
if isinstance(node, dict):
|
||||
|
|
@ -92,12 +104,14 @@ def find_versions(node: object, where: str, path: str = "") -> list[str]:
|
|||
if VERSION_KEY.search(str(key)):
|
||||
found.append(f"{where}: key '{here}'")
|
||||
continue
|
||||
found.extend(find_versions(value, where, here))
|
||||
found.extend(find_versions(value, where, here, str(key).lower() in IDENTITY_KEYS))
|
||||
elif isinstance(node, list):
|
||||
for index, item in enumerate(node):
|
||||
found.extend(find_versions(item, where, f"{path}[{index}]"))
|
||||
found.extend(find_versions(item, where, f"{path}[{index}]", identity))
|
||||
elif isinstance(node, str) and VERSION_VALUE.search(node):
|
||||
found.append(f"{where}: value of '{path}' = {node!r}")
|
||||
elif isinstance(node, str) and identity and IDENTITY_VERSION.search(node):
|
||||
found.append(f"{where}: identity-bearing value of '{path}' = {node!r}")
|
||||
return found
|
||||
|
||||
|
||||
|
|
@ -106,7 +120,7 @@ def reject_versions(data: dict, where: str) -> None:
|
|||
if found:
|
||||
print(
|
||||
"FAIL: a layer declaration MUST NOT carry a standard or companion "
|
||||
"version in any key or value (GH-DEC-2026-017 §5, GH-DEC-2026-020, A12 r2)",
|
||||
"version in any key or value (GH-DEC-2026-017 §5, GH-DEC-2026-020, GH-DEC-2026-021, A12 r3)",
|
||||
file=sys.stderr,
|
||||
)
|
||||
for item in found:
|
||||
|
|
|
|||
|
|
@ -81,6 +81,15 @@ class LayerDeclarationTests(unittest.TestCase):
|
|||
# pep-stance.yaml keeps its version fields (GH-DEC-2026-020 §3).
|
||||
self.assertTrue(module.find_versions(load_mapping(STANCE_FILE), "stance"))
|
||||
|
||||
def test_version_scan_matches_estate_reference_detector(self):
|
||||
# GH-DEC-2026-021 §3 (A12 r3): a version token in an identity-bearing
|
||||
# value is a pin; a key naming neither standard nor companion is not.
|
||||
module = _checker()
|
||||
self.assertTrue(module.find_versions({"standard": "security-layer-model 0.7"}, "x"))
|
||||
self.assertTrue(module.find_versions({"companion": ["SECURITY-COMPANION v0.2"]}, "x"))
|
||||
self.assertEqual(module.find_versions({"intent_version": "0.3"}, "x"), [])
|
||||
self.assertEqual(module.find_versions({"note": "revised 0.7 wording"}, "x"), [])
|
||||
|
||||
def test_every_run_prints_version_and_scope(self):
|
||||
module = _checker()
|
||||
for argv in ([], ["--report"]):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue