Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 308701@bnt-lap001 Assistant-Session: 5548e447-444c-4dcc-bed1-05c16eebfe56
118 lines
3.9 KiB
Python
118 lines
3.9 KiB
Python
"""Synthetic tests for the rotation-lane coverage check (NK-WP-0055-T15)."""
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
SOURCE = Path(__file__).parents[1] / "check.py"
|
|
spec = importlib.util.spec_from_file_location("rotation_lanes_check", SOURCE)
|
|
rl = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(rl)
|
|
|
|
STANDARD = "# CM\n\n## 6. Secret Rotation\n\n| Secret | Blast |\n|---|---|\n| `APP_SECRET` | Low |\n\n## 7. Next\n| `NOT_IN_SIX` | x |\n"
|
|
CRISIS = "| # | Item |\n|---|---|\n| 1 | **key** | a |\n| 2 | ~~retired~~ | b |\n"
|
|
|
|
|
|
def make_root(tmp_path):
|
|
(tmp_path / "tools/service-identity/declarations").mkdir(parents=True)
|
|
(tmp_path / "canon/standards").mkdir(parents=True)
|
|
(tmp_path / "docs").mkdir()
|
|
(tmp_path / "workplans").mkdir()
|
|
decl = {
|
|
"service": "svc",
|
|
"identities": [
|
|
{"name": "bind", "custody": ["delivered-secret"]},
|
|
{"name": "sso", "custody": ["none"]},
|
|
],
|
|
}
|
|
(tmp_path / "tools/service-identity/declarations/svc.yaml").write_text(
|
|
yaml.safe_dump(decl)
|
|
)
|
|
(tmp_path / "canon/standards/credential-management_v0.2.md").write_text(STANDARD)
|
|
(tmp_path / "docs/crisis-custody-list.md").write_text(CRISIS)
|
|
(tmp_path / "workplans/NK-WP-0001-x.md").write_text("id: NK-WP-0001-T01\n")
|
|
return tmp_path
|
|
|
|
|
|
def lane(**over):
|
|
base = {
|
|
"id": "l1",
|
|
"class": "service",
|
|
"state": "designed",
|
|
"path": "swap it",
|
|
"verification": "old refused",
|
|
"owner_lane": ["NK-WP-0001-T01"],
|
|
"blast_radius": {"level": "low", "affects": ["svc"], "effect": "sessions end"},
|
|
"identities": ["svc/bind"],
|
|
"credentials": ["APP_SECRET"],
|
|
"crisis_items": ["1"],
|
|
}
|
|
base.update(over)
|
|
return base
|
|
|
|
|
|
def test_complete_register_passes(tmp_path):
|
|
_, errors = rl.check({"lanes": [lane()]}, make_root(tmp_path))
|
|
assert errors == []
|
|
|
|
|
|
def test_missing_coverage_is_reported(tmp_path):
|
|
_, errors = rl.check(
|
|
{"lanes": [lane(identities=[], credentials=[], crisis_items=[])]},
|
|
make_root(tmp_path),
|
|
)
|
|
assert "no lane for identity svc/bind" in errors
|
|
assert "no lane for credential APP_SECRET" in errors
|
|
assert "no lane for crisis_item 1" in errors
|
|
|
|
|
|
def test_federated_identity_may_be_named_but_is_not_required(tmp_path):
|
|
_, errors = rl.check(
|
|
{"lanes": [lane(identities=["svc/bind", "svc/sso"])]}, make_root(tmp_path)
|
|
)
|
|
assert errors == []
|
|
|
|
|
|
def test_retired_crisis_row_and_other_sections_are_ignored(tmp_path):
|
|
_, errors = rl.check(
|
|
{
|
|
"lanes": [
|
|
lane(crisis_items=["1", "2"], credentials=["APP_SECRET", "NOT_IN_SIX"])
|
|
]
|
|
},
|
|
make_root(tmp_path),
|
|
)
|
|
assert "lane l1 names unknown crisis_items entry 2" in errors
|
|
assert "lane l1 names unknown credentials entry NOT_IN_SIX" in errors
|
|
|
|
|
|
def test_lane_fields_and_owner_refs_are_enforced(tmp_path):
|
|
bad = lane(
|
|
state="maybe",
|
|
verification="",
|
|
owner_lane=["NK-WP-0099-T01", "bogus"],
|
|
blast_radius={"level": "huge"},
|
|
)
|
|
_, errors = rl.check({"lanes": [bad]}, make_root(tmp_path))
|
|
assert any("state must be" in e for e in errors)
|
|
assert "l1: verification is empty" in errors
|
|
assert any("blast_radius needs" in e for e in errors)
|
|
assert "l1: owner_lane NK-WP-0099-T01 not found in workplans/" in errors
|
|
assert any("'bogus' is not a workplan" in e for e in errors)
|
|
|
|
|
|
def test_duplicate_assignment_is_reported(tmp_path):
|
|
_, errors = rl.check(
|
|
{"lanes": [lane(), lane(id="l2", credentials=[], crisis_items=[])]},
|
|
make_root(tmp_path),
|
|
)
|
|
assert "l2: identities svc/bind already in lane l1" in errors
|
|
|
|
|
|
def test_checked_in_register_is_complete():
|
|
root = Path(__file__).parents[3]
|
|
_, errors = rl.check(
|
|
yaml.safe_load((root / "tools/rotation-lanes/lanes.yaml").read_text()), root
|
|
)
|
|
assert errors == []
|