Apply GH-DEC-2026-021: name the text in force, converge on the reference detector
VALIDATED_AGAINST now names the accepted security-layer-model v0.7 (net-kingdom@66dc491) as amended by GH-DEC-2026-017, -020, -021 (gate-house@39d9287), not the held v0.8 (021 §2). The A12 detector converges on ops-warden's playbook reference plus the 021 §3 addition (a version in a standard:/companion: value is a pin). A prose citation such as 'the v0.7 scope rule' is no longer failed (021 §1); tests updated. The layer.yaml note rewording stays. 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
This commit is contained in:
parent
8322f0587e
commit
ff0712b260
2 changed files with 43 additions and 30 deletions
|
|
@ -7,8 +7,8 @@ Read-only. Makes two mechanical checks:
|
|||
derived artifact (derived: true, derived_from: INTENT.md) that must agree
|
||||
with it after ASCII case-folding. The layer is one of §3's closed four
|
||||
tokens (Taxonomy, Tooling, Engine, Staff). Neither form carries a
|
||||
version of the standard or its companion in any key or value
|
||||
(GH-DEC-2026-017 §1-§5, GH-DEC-2026-020, amendments A9, A11, A12 r2).
|
||||
version of the standard or its companion as a pin (GH-DEC-2026-017
|
||||
§1-§5, GH-DEC-2026-020, GH-DEC-2026-021 §1, amendments A9, A11, A12 r2).
|
||||
2. No catalogued Tooling client (OpenBao, key-cape) appears in src/
|
||||
unless it maps to a declared §5.1 / §5.2 / §5.3 entry.
|
||||
|
||||
|
|
@ -16,10 +16,13 @@ PostgreSQL / SQLite / httpx-to-flex-auth / httpx-to-audit-core are not
|
|||
Tooling contacts. They are listed in layer.yaml non_tooling_clients so
|
||||
the inventory is total.
|
||||
|
||||
A12 r2 reaches content, not a key name: a `*_version` key (standard_version,
|
||||
companion_version, ...), a versioned `security-layer-model_v0.7.md` or
|
||||
companion path, and a bare `v0.7` token all count. `schema_version` and YAML
|
||||
comments are not reached. Stance, claims and classification maps
|
||||
A12 reaches a pin, not a citation (GH-DEC-2026-021 §1). The detector is
|
||||
ops-warden's estate reference (wiki/playbooks/netkingdom-layer-declaration.md,
|
||||
021 §3): a key naming a standard or companion version, a version in a path or
|
||||
file-name token (`_v0.7`, `-v0.8.md`, `@0.7`), and, the one addition, any
|
||||
version token in the value of a `standard:` or `companion:` key. A revision
|
||||
cited in prose (a space-preceded `v0.7`) is provenance and is not reached.
|
||||
`schema_version` and YAML comments are not reached. Stance, claims and classification maps
|
||||
(pep-stance.yaml, pip-claims.yaml) are not declarations; this check does not
|
||||
read them for A12 and must not (A12 r2, GH-DEC-2026-020 §3).
|
||||
|
||||
|
|
@ -41,34 +44,33 @@ try:
|
|||
import yaml
|
||||
except ImportError: # pragma: no cover - dev extra
|
||||
print("FAIL: PyYAML is required (pip install pyyaml)", file=sys.stderr)
|
||||
raise SystemExit(2)
|
||||
raise SystemExit(2) from None
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SRC = ROOT / "src" / "tenant_engine"
|
||||
DECL = ROOT / "layer.yaml"
|
||||
INTENT = ROOT / "INTENT.md"
|
||||
|
||||
# The standard text this checker was built and validated against
|
||||
# (GH-DEC-2026-020 §4, A12 r2: the version belongs to the run). Bump it when
|
||||
# the checker is re-validated against a newer accepted text.
|
||||
VALIDATED_AGAINST = ("net-kingdom/canon/standards/security-layer-model_v0.8.md "
|
||||
"@ net-kingdom f9e1611, with gate-house "
|
||||
"docs/amendments/v0.8-section-11-declaration-amendments.md "
|
||||
"A9, A11, A12 r2 @ gate-house 104f3fc")
|
||||
# The text in force this checker enforces (GH-DEC-2026-020 §4, GH-DEC-2026-021
|
||||
# §2): the ACCEPTED v0.7 plus the gate-house decisions enforced beyond it. v0.8
|
||||
# is held under GH-DEC-2026-019 and does not govern, so it is not named here.
|
||||
# Re-point after the flip (GH-WP-0004-T11).
|
||||
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, GH-DEC-2026-021 (gate-house@39d9287)")
|
||||
SCOPE = ("declaration = INTENT.md frontmatter + layer.yaml (every key and value); "
|
||||
"tooling scan = src/tenant_engine/**/*.py; "
|
||||
"not reached: pep-stance.yaml, pip-claims.yaml, comments, schema_version")
|
||||
|
||||
# A12 r2: what reads as a version of this standard or its companion.
|
||||
_VERSION_KEY = re.compile(r"(?:^|_)version$", re.IGNORECASE)
|
||||
# A12 pin detector, converged on ops-warden's estate reference (GH-DEC-2026-021
|
||||
# §3). The path pattern deliberately flags a versioned path of any document.
|
||||
_VERSION_KEY = re.compile(r"(standard|companion).*version|version.*(standard|companion)",
|
||||
re.IGNORECASE)
|
||||
_VERSION_IN_VALUE = re.compile(r"[_\-.]v\d+(\.\d+)*(\.md)?\b|@v?\d+\.\d+", re.IGNORECASE)
|
||||
_EXEMPT_KEYS = {"schema_version"} # the declaration file's own schema, not reached
|
||||
_VERSIONED_PATH = re.compile(
|
||||
r"(?:security-layer-model|security[-_]companion|companion)[^\s]*?[_-]v?\d+(?:\.\d+)+",
|
||||
re.IGNORECASE)
|
||||
# A bare version token (v0.7). A declaration names no other versioned text, so
|
||||
# a bare token reads as this standard's. File-name suffixes of other
|
||||
# standards (…_v0.1.md) are preceded by '_' and are not matched here.
|
||||
_BARE_VERSION = re.compile(r"(?<![\w.])v\d+(?:\.\d+)+\b", re.IGNORECASE)
|
||||
# 021 §3 addition: an identity-bearing standard:/companion: value carries no version.
|
||||
_IDENTITY_KEYS = {"standard", "companion"}
|
||||
_ANY_VERSION = re.compile(r"v?\d+\.\d+", re.IGNORECASE)
|
||||
|
||||
# Catalogued Tooling in statute §4 today: key-cape and OpenBao.
|
||||
# Import roots that would constitute a direct client of those.
|
||||
|
|
@ -94,7 +96,7 @@ def _fold(value: object) -> str:
|
|||
|
||||
|
||||
def version_findings(data: object, where: str) -> list[str]:
|
||||
"""Every key or value of a parsed declaration that carries a version (A12 r2)."""
|
||||
"""Every pin in a parsed declaration (A12, GH-DEC-2026-021 §1, §3)."""
|
||||
found: list[str] = []
|
||||
|
||||
def walk(node: object, path: str) -> None:
|
||||
|
|
@ -106,14 +108,16 @@ def version_findings(data: object, where: str) -> list[str]:
|
|||
if _VERSION_KEY.search(str(key)):
|
||||
found.append(f"{where}: key '{sub}' is a version key")
|
||||
continue
|
||||
if isinstance(key, str):
|
||||
walk(key, sub + " (key)")
|
||||
if (_fold(key) in _IDENTITY_KEYS and isinstance(value, str)
|
||||
and _ANY_VERSION.search(value)):
|
||||
found.append(f"{where}: '{sub}' carries a version: {value.strip()[:80]!r}")
|
||||
continue
|
||||
walk(value, sub)
|
||||
elif isinstance(node, list):
|
||||
for i, item in enumerate(node):
|
||||
walk(item, f"{path}[{i}]")
|
||||
elif isinstance(node, str):
|
||||
if _VERSIONED_PATH.search(node) or _BARE_VERSION.search(node):
|
||||
if _VERSION_IN_VALUE.search(node):
|
||||
found.append(f"{where}: '{path}' carries a version: {node.strip()[:80]!r}")
|
||||
|
||||
walk(data, "")
|
||||
|
|
@ -124,7 +128,7 @@ def _reject_versions(data: object, where: str) -> None:
|
|||
findings = version_findings(data, where)
|
||||
if findings:
|
||||
print("FAIL: a layer declaration must not carry a version of the standard "
|
||||
"or its companion, in any key or value (A12 r2, GH-DEC-2026-020)",
|
||||
"or its companion, as a pin (A12, GH-DEC-2026-020, GH-DEC-2026-021 §1)",
|
||||
file=sys.stderr)
|
||||
for line in findings:
|
||||
print(f" {line}", file=sys.stderr)
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ def test_versioned_standard_path_or_companion_version_fails():
|
|||
{**base, "companion_version": "0.2"},
|
||||
{**base, "companion": "net-kingdom/SECURITY-COMPANION.md v0.2"},
|
||||
{**base, "standard_version": "0.8"},
|
||||
{**base, "notes": [{"note": "Outside §5 by the v0.7 scope rule."}]},
|
||||
{**base, "standard": "security-layer-model v0.7"}, # 021 §3 addition
|
||||
{**base, "ref": "net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md"},
|
||||
]
|
||||
for data in bad:
|
||||
assert checker.version_findings(data, "x"), data
|
||||
|
|
@ -97,10 +98,18 @@ def test_schema_version_comments_and_section_numbers_are_not_reached():
|
|||
"# Framework: net-kingdom/canon/standards/security-layer-model_v0.7.md\n"
|
||||
"schema_version: '0.1'\nstandard: netkingdom-security-layer-model\n"
|
||||
"declared_shapes: {'5.1': [], '5.2': []}\ndeclared_at: '2026-08-29'\n"
|
||||
"ref: net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md\n")
|
||||
"notes: [{note: 'Outside §5 by the v0.7 scope rule.'}]\n")
|
||||
assert checker.version_findings(data, "x") == []
|
||||
|
||||
|
||||
def test_prose_citation_is_not_a_pin():
|
||||
"""GH-DEC-2026-021 §1: a revision cited in prose is provenance, not reached."""
|
||||
checker = _checker()
|
||||
for data in ({"notes": [{"note": "Outside §5 by the v0.7 scope rule."}]},
|
||||
{"role_note": "Per Security Layer Model v0.8 §11 and companion v0.2."}):
|
||||
assert checker.version_findings(data, "x") == [], data
|
||||
|
||||
|
||||
def test_checker_does_not_apply_a12_to_stance_or_claims_maps():
|
||||
"""A12 r2 / GH-DEC-2026-020 §3: those files keep their version and are not read for it."""
|
||||
for name in ("pep-stance.yaml", "pip-claims.yaml"):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue