Validate accepted security layer v0.8 owner declaration
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
parent
b8ee47806d
commit
1dabbcf47d
4 changed files with 144 additions and 48 deletions
|
|
@ -15,10 +15,10 @@ companion: net-kingdom/SECURITY-COMPANION.md
|
|||
> current implementation. See `SCOPE.md` for what is implemented today.
|
||||
|
||||
> **Layer: Engine. Role: PIP.** This is the declaration required by
|
||||
> NetKingdom Security Layer Model v0.7 §11 and the working companion v0.2.
|
||||
> NetKingdom Security Layer Model v0.8 §11 and the working companion v0.3.
|
||||
> It is this repository's own voice, not a catalog row or a review note
|
||||
> written about us. The statute is
|
||||
> `net-kingdom/canon/standards/security-layer-model_v0.7.md`; the companion
|
||||
> `net-kingdom/canon/standards/security-layer-model_v0.8.md`; the companion
|
||||
> is `net-kingdom/SECURITY-COMPANION.md`. On disagreement the statute
|
||||
> governs, and a disagreement is a finding for `gate-house`.
|
||||
>
|
||||
|
|
@ -251,7 +251,7 @@ the three drift: the statute wins, then the contract, then this file.
|
|||
- `docs/tenant-guardrail-policy.md` — ceiling contract
|
||||
- `docs/tenant-lifecycle-api.md` — update, retire, reactivate
|
||||
- `net-kingdom/SECURITY-COMPANION.md` — start here for the layer rules
|
||||
- `net-kingdom/canon/standards/security-layer-model_v0.7.md` — the statute
|
||||
- `net-kingdom/canon/standards/security-layer-model_v0.8.md` — the statute
|
||||
- `net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md`
|
||||
- `net-kingdom/canon/standards/iam-profile_v0.3.md` — the `tenant_roles`
|
||||
claim and carrying mechanism this service implements
|
||||
|
|
|
|||
62
docs/evidence/2026-10-11-security-layer-v08-migration.json
Normal file
62
docs/evidence/2026-10-11-security-layer-v08-migration.json
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"owner": "tenant-engine",
|
||||
"accepted_standard_sha256": "3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b",
|
||||
"accepted_source": "net-kingdom/canon/standards/security-layer-model_v0.8.md",
|
||||
"acceptance_receipt": "net-kingdom/docs/security-layer-v0.8-acceptance.md",
|
||||
"tests": {
|
||||
"layer_conformance_passed": 16,
|
||||
"source": "staged modified scripts/tests + read-only current source support",
|
||||
"limitations": "mechanical declared scope only, not complete estate/runtime conformance"
|
||||
},
|
||||
"checker_runs": [
|
||||
{
|
||||
"argv": [],
|
||||
"returncode": 0,
|
||||
"stdout": "checking against: net-kingdom/canon/standards/security-layer-model_v0.8.md (accepted; sha256:3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b)\nscope: single repository tenant-engine (catalogued in \u00a74); 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\nOK: Engine/PIP declaration matches INTENT.md; no Tooling client in src/tenant_engine; no version in the declaration; validated against net-kingdom/canon/standards/security-layer-model_v0.8.md (accepted; sha256:3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b)\n",
|
||||
"stderr": ""
|
||||
},
|
||||
{
|
||||
"argv": [
|
||||
"--report"
|
||||
],
|
||||
"returncode": 0,
|
||||
"stdout": "checking against: net-kingdom/canon/standards/security-layer-model_v0.8.md (accepted; sha256:3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b)\nscope: single repository tenant-engine (catalogued in \u00a74); 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\ntenant-engine \u2014 layer Engine, role PIP (INTENT.md governs; layer.yaml derived from INTENT.md)\n tooling contacts declared: 0\n non-tooling clients: 5\n",
|
||||
"stderr": ""
|
||||
}
|
||||
],
|
||||
"meaningful_regressions": {
|
||||
"unicode_token_original_fold": "st\u03b1aff",
|
||||
"original_accepted_non_ascii_token": false,
|
||||
"original_nested_standard_sequence_findings": []
|
||||
},
|
||||
"source_changes": [
|
||||
{
|
||||
"repo": "tenant-engine",
|
||||
"path": "scripts/check_layer_conformance.py",
|
||||
"staged_path": "/tmp/layer-migration-stage/tenant-engine/scripts/check_layer_conformance.py",
|
||||
"original_sha256": "fe9d5f6d47cebb789eee554192873de0ca3b7036ef5b5e6706a62757e15c6822",
|
||||
"staged_sha256": "be73ae48b44fcf09115d6a3897bbd69f71bcebc54f2dce14afb307e3c1e67b5f"
|
||||
},
|
||||
{
|
||||
"repo": "tenant-engine",
|
||||
"path": "tests/test_layer_conformance.py",
|
||||
"staged_path": "/tmp/layer-migration-stage/tenant-engine/tests/test_layer_conformance.py",
|
||||
"original_sha256": "f7b25dd57d933b652e9e741baeb14a0823766ae9b32932ac0b388ef859ae5394",
|
||||
"staged_sha256": "19a6fd4895a4efaebd1825c189fdb1274a3b5c0d75d056e6a0f24d9e4d715ab2"
|
||||
},
|
||||
{
|
||||
"repo": "tenant-engine",
|
||||
"path": "INTENT.md",
|
||||
"staged_path": "/tmp/layer-migration-stage/tenant-engine/INTENT.md",
|
||||
"original_sha256": "97075d9a53b568d5bbeab3c7bed1efe1dfb9833eb93df87c60e18335105b9ce2",
|
||||
"staged_sha256": "c2deaef01f7492ca1b39f52e36bf703f6a55b04158b2888b7befae73452ce285"
|
||||
}
|
||||
],
|
||||
"knowledge_orientation": {
|
||||
"package_version": "0.2.6",
|
||||
"package_digest": "8d1d6a9d4d07fec7b619618de7dfe2be2254c1790f85f4198c7fe19db9751c02",
|
||||
"start_status": "withheld due changed sources; source reviewed directly"
|
||||
},
|
||||
"native_runtime_changed": false,
|
||||
"pushed": false
|
||||
}
|
||||
|
|
@ -51,26 +51,52 @@ SRC = ROOT / "src" / "tenant_engine"
|
|||
DECL = ROOT / "layer.yaml"
|
||||
INTENT = ROOT / "INTENT.md"
|
||||
|
||||
# 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); "
|
||||
# Accepted v0.8 publication; version provenance belongs to this run, never
|
||||
# the standing layer declaration (§11). Exact publisher artifact is retained
|
||||
# in net-kingdom/docs/security-layer-v0.8-acceptance.md.
|
||||
VALIDATED_AGAINST = (
|
||||
"net-kingdom/canon/standards/security-layer-model_v0.8.md "
|
||||
"(accepted; sha256:3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b)"
|
||||
)
|
||||
|
||||
SCOPE = ("single repository tenant-engine (catalogued in §4); "
|
||||
"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 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
|
||||
# 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)
|
||||
# Declaration pin/provenance semantics are the ops-warden estate reference.
|
||||
VERSION_KEY = re.compile(r"(standard|companion).*version|version.*(standard|companion)", re.I)
|
||||
VERSION_IN_VALUE = re.compile(r"[_\-.]v\d+(\.\d+)*(\.md)?\b|@v?\d+\.\d+", re.I)
|
||||
NOT_REACHED_KEYS = {"schema_version"}
|
||||
IDENTITY_KEYS = {"standard", "companion"}
|
||||
IDENTITY_VERSION = re.compile(r"\bv?\d+\.\d+", re.I)
|
||||
|
||||
|
||||
def find_version_pins(node, where: str = "", identity: bool = False) -> list[str]:
|
||||
"""Every place in a parsed declaration that carries a standard/companion version.
|
||||
|
||||
Walks every key and value (comments are gone after parsing, which is the
|
||||
A12 r2 exclusion). Returns human-readable locations; empty means clean.
|
||||
"""
|
||||
pins: list[str] = []
|
||||
if isinstance(node, dict):
|
||||
for k, v in node.items():
|
||||
here = f"{where}.{k}" if where else str(k)
|
||||
if str(k) in NOT_REACHED_KEYS:
|
||||
continue
|
||||
if VERSION_KEY.search(str(k)):
|
||||
pins.append(f"{here} (key names a standard/companion version)")
|
||||
continue
|
||||
pins.extend(find_version_pins(v, here, str(k).lower() in IDENTITY_KEYS))
|
||||
elif isinstance(node, list):
|
||||
for i, v in enumerate(node):
|
||||
pins.extend(find_version_pins(v, f"{where}[{i}]", identity))
|
||||
elif isinstance(node, str) and VERSION_IN_VALUE.search(node):
|
||||
pins.append(f"{where} = {node!r} (value carries a version)")
|
||||
elif isinstance(node, str) and identity and IDENTITY_VERSION.search(node):
|
||||
pins.append(f"{where} = {node!r} (identity-bearing value carries a version)")
|
||||
return pins
|
||||
|
||||
|
||||
# Catalogued Tooling in statute §4 today: key-cape and OpenBao.
|
||||
# Import roots that would constitute a direct client of those.
|
||||
|
|
@ -91,37 +117,13 @@ LAYER_VOCABULARY = {"taxonomy", "tooling", "engine", "staff"}
|
|||
|
||||
def _fold(value: object) -> str:
|
||||
"""ASCII case-fold only; two spellings of a token are one token."""
|
||||
return str(value).translate(str.maketrans("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
return str(value).strip().translate(str.maketrans("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
"abcdefghijklmnopqrstuvwxyz"))
|
||||
|
||||
|
||||
def version_findings(data: object, where: str) -> list[str]:
|
||||
"""Every pin in a parsed declaration (A12, GH-DEC-2026-021 §1, §3)."""
|
||||
found: list[str] = []
|
||||
|
||||
def walk(node: object, path: str) -> None:
|
||||
if isinstance(node, dict):
|
||||
for key, value in node.items():
|
||||
sub = f"{path}.{key}" if path else str(key)
|
||||
if str(key) in _EXEMPT_KEYS:
|
||||
continue
|
||||
if _VERSION_KEY.search(str(key)):
|
||||
found.append(f"{where}: key '{sub}' is a version key")
|
||||
continue
|
||||
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 _VERSION_IN_VALUE.search(node):
|
||||
found.append(f"{where}: '{path}' carries a version: {node.strip()[:80]!r}")
|
||||
|
||||
walk(data, "")
|
||||
return found
|
||||
"""Owner-compatible diagnostics over the estate reference declaration walk."""
|
||||
return [f"{where}: {finding}" for finding in find_version_pins(data)]
|
||||
|
||||
|
||||
def _reject_versions(data: object, where: str) -> None:
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ def test_a_failing_run_still_states_version_and_scope(tmp_path, monkeypatch, cap
|
|||
raise AssertionError("a versioned standard: path must fail")
|
||||
out = capsys.readouterr()
|
||||
assert checker.VALIDATED_AGAINST in out.out and "scope:" in out.out
|
||||
assert "carries a version" in out.err
|
||||
assert "value carries a version" in out.err
|
||||
|
||||
|
||||
def test_checker_rejects_a_divergence_that_survives_the_fold(tmp_path, monkeypatch):
|
||||
|
|
@ -185,3 +185,35 @@ def test_published_stance_equals_shipped_behaviour():
|
|||
assert published_stance() == shipped_stance()
|
||||
assert set(shipped_stance()) == {"unset", "unreachable", "non_allow", "unknown"}
|
||||
assert set(shipped_stance().values()) == {"fail_closed"}
|
||||
|
||||
|
||||
def test_accepted_v08_run_provenance_and_catalog_scope():
|
||||
checker = _checker()
|
||||
assert "security-layer-model_v0.8.md" in checker.VALIDATED_AGAINST
|
||||
assert "sha256:3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b" in checker.VALIDATED_AGAINST
|
||||
assert "single repository tenant-engine (catalogued in §4)" in checker.SCOPE
|
||||
|
||||
|
||||
def test_reference_semantics_propagate_identity_through_nested_sequences():
|
||||
checker = _checker()
|
||||
for data in (
|
||||
{"nested": {"standard": ["Security Layer Model v0.8"]}},
|
||||
{"companion": [["Security Companion 0.3"]]},
|
||||
{"standard": {"alternate": ["Security Layer Model v0.7"]}},
|
||||
):
|
||||
# A dictionary begins a fresh identity key; only sequence descendants
|
||||
# inherit the immediate standard:/companion: identity in the reference.
|
||||
if isinstance(data.get("standard"), dict):
|
||||
assert checker.find_version_pins(data) == []
|
||||
else:
|
||||
assert checker.find_version_pins(data), data
|
||||
assert checker.find_version_pins({"rationale": "Assented at v0.7; migrated at v0.8."}) == []
|
||||
assert checker.find_version_pins({"intent_version": "0.2.0", "schema_version": "0.1"}) == []
|
||||
|
||||
|
||||
def test_ascii_folding_never_discards_non_ascii_letters():
|
||||
checker = _checker()
|
||||
assert checker._fold("Staff") == "staff"
|
||||
assert checker._fold("Engine") == "engine"
|
||||
# Deleting non-ASCII bytes would turn this fifth token into Staff.
|
||||
assert checker._fold("Stαaff") not in checker.LAYER_VOCABULARY
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue