from __future__ import annotations import copy import importlib.util import json import pathlib import sys import yaml TOOL_PATH = pathlib.Path(__file__).resolve().parents[1] / "posture_feedback.py" SPEC = importlib.util.spec_from_file_location("posture_feedback", TOOL_PATH) feedback = importlib.util.module_from_spec(SPEC) assert SPEC and SPEC.loader sys.modules[SPEC.name] = feedback SPEC.loader.exec_module(feedback) def declaration(service="example") -> dict: return { "schema_version": "0.1", "framework": "netkingdom-tenancy-posture", "service": service, "role": "test-service", "responsible_repo": "example-owner", "tenancy": { "current": {"I": 1, "A": 1, "E": 0, "P": 0, "R": 1, "V": 0}, "target": {"I": 1, "A": 1, "E": 0, "P": 0, "R": 1, "V": 0}, "reviewed": "2026-08-01", "review_due": "2026-12-31", "service_class": "interactive", "reason": { "I": "floor explained", "A": "floor explained", "E": "floor explained", "P": "floor explained", "R": "floor explained", "V": "floor explained", }, }, } def write_declaration(tmp_path: pathlib.Path, document: dict, name="tenancy.yaml") -> pathlib.Path: path = tmp_path / name path.write_text(yaml.safe_dump(document, sort_keys=False), encoding="utf-8") return path def build(path: pathlib.Path, *, as_of="2026-08-23T12:00:00Z", horizon=14, fail_on="none"): return feedback.build_report( [path], as_of=feedback.parse_timestamp(as_of), horizon_days=horizon, fail_on=fail_on, ) def classes(report: dict) -> list[str]: return [item["class"] for item in report["findings"]] def test_checked_in_reference_emits_five_proposals_and_no_authority(): repo_root = pathlib.Path(__file__).resolve().parents[3] path = repo_root / "examples/posture-feedback/expired-e2.yaml" report = build(path) assert report["summary"] == { "total": 5, "high": 1, "medium": 3, "low": 1, "unknown_owner": 0, } assert report["automation"] == { "mode": "proposal-only", "external_write_permitted": False, "policy_mutation_permitted": False, "declaration_mutation_permitted": False, } def test_missing_adversarial_freshness_is_unknown_without_owner_inference(tmp_path): document = declaration() document["tenancy"]["current"]["E"] = 2 document["tenancy"]["target"]["E"] = 2 document["tenancy"]["reason"].pop("E") document["evidence"] = {"E2": "docs/evidence/e2.md"} path = write_declaration(tmp_path, document) report = build(path) finding = next(item for item in report["findings"] if item["class"] == "evidence-freshness-unknown") assert finding["owner"] == "unknown" assert finding["evidence_state"] == "unknown" def test_exact_evidence_expiry_is_still_valid_but_due(tmp_path): document = declaration() document["tenancy"]["current"]["E"] = 2 document["tenancy"]["target"]["E"] = 2 document["tenancy"]["reason"].pop("E") document["evidence"] = {"E2": "docs/evidence/e2.md"} document["evidence_freshness"] = { "E2": { "kind": "adversarial", "observed_at": "2026-08-22T12:00:00Z", "valid_until": "2026-08-23T12:00:00Z", "responsible_repo": "evidence-owner", "scope": "bounded", "remediation": "repeat", } } path = write_declaration(tmp_path, document) report = build(path, horizon=0) assert "evidence-expired" not in classes(report) assert "evidence-due-soon" in classes(report) def test_review_due_date_expires_after_utc_calendar_day(tmp_path): document = declaration() document["tenancy"]["review_due"] = "2026-08-23" path = write_declaration(tmp_path, document) due_today = build(path, as_of="2026-08-23T23:59:59Z", horizon=0) overdue = build(path, as_of="2026-08-24T00:00:00Z", horizon=0) assert "posture-review-due-soon" in classes(due_today) assert "posture-review-overdue" not in classes(due_today) assert "posture-review-overdue" in classes(overdue) def test_posture_owner_is_unknown_when_not_declared(tmp_path): document = declaration() del document["responsible_repo"] document["tenancy"]["review_due"] = "2026-08-01" path = write_declaration(tmp_path, document) report = build(path) finding = next(item for item in report["findings"] if item["class"] == "posture-review-overdue") assert finding["owner"] == "unknown" assert report["summary"]["unknown_owner"] == 1 def test_multi_service_declaration_is_evaluated_per_service(tmp_path): first = declaration("first") second = declaration("second") for entry in (first, second): entry.pop("schema_version") entry.pop("framework") first["tenancy"]["gap"] = {"A": "first gap"} second["tenancy"]["gap"] = {"V": "second gap"} document = { "schema_version": "0.1", "framework": "netkingdom-tenancy-posture", "services": [first, second], } path = write_declaration(tmp_path, document) report = build(path) assert {(item["service"], item["control"]) for item in report["findings"]} == { ("first", "A"), ("second", "V"), } def test_mechanical_evidence_without_expiry_creates_no_freshness_finding(tmp_path): document = declaration() document["tenancy"]["current"]["A"] = 2 document["tenancy"]["target"]["A"] = 2 document["tenancy"]["reason"].pop("A") document["evidence"] = {"A2": "tests/authorization.py"} document["evidence_freshness"] = { "A2": { "kind": "mechanical", "observed_at": "2026-08-22T12:00:00Z", "responsible_repo": "example-owner", "scope": "continuous test", "remediation": "repair the test", } } path = write_declaration(tmp_path, document) report = build(path) assert not any(item["class"].startswith("evidence-") for item in report["findings"]) def test_report_digest_is_stable_for_identical_inputs(tmp_path): path = write_declaration(tmp_path, declaration()) first = build(path) second = build(path) assert first == second assert first["report_digest"].startswith("sha256:") def test_workspace_source_identifier_is_portable_and_not_an_owner_inference(): repo_root = pathlib.Path(__file__).resolve().parents[3] path = repo_root / "examples/posture-feedback/expired-e2.yaml" report = build(path) assert {item["source"] for item in report["findings"]} == { "net-kingdom/examples/posture-feedback/expired-e2.yaml" } gap = next(item for item in report["findings"] if item["class"] == "declared-gap") zone = next(item for item in report["findings"] if item["class"].startswith("zone-")) assert gap["owner"] == "net-kingdom" assert zone["owner"] == "team:platform-security" assert all(item["owner"] != item["source"] for item in report["findings"]) def test_fail_on_threshold_changes_ok_not_findings(tmp_path): document = declaration() document["tenancy"]["gap"] = {"R": "declared gap"} path = write_declaration(tmp_path, document) report_only = build(path, fail_on="none") failing = build(path, fail_on="low") assert report_only["ok"] is True assert failing["ok"] is False assert report_only["findings"] == failing["findings"] def test_invalid_declaration_is_reported_and_cli_exits_two(tmp_path, capsys): document = declaration() del document["role"] path = write_declaration(tmp_path, document) exit_code = feedback.main( [ "--as-of", "2026-08-23T12:00:00Z", "--fail-on", "none", str(path), ] ) payload = json.loads(capsys.readouterr().out) assert exit_code == 2 assert payload["ok"] is False assert payload["validation_errors"] def test_timestamp_without_offset_is_rejected(): try: feedback.parse_timestamp("2026-08-23T12:00:00") except ValueError as exc: assert "explicit UTC offset" in str(exc) else: raise AssertionError("timezone-naive timestamp was accepted")