"""Offline guard for the net-kingdom agent status identity (net-kingdom NK-WP-0058-T05, decision 4af1ec01). Parses the GitOps manifests and asserts the founder's 2026-11-06 boundary (option A): read-only verbs on the curated namespaced resources, named objects outside sso, no forbidden resources, no wildcards, no cluster scope, a ServiceAccount without token automount, and a manual, pinned Application. """ from pathlib import Path import re import pytest import yaml ROOT = Path(__file__).resolve().parents[1] ADDON = ROOT / "argocd/platform-addons/nk-agent-status" APP = ROOT / "argocd/railiance01/applications/nk-agent-status.application.yaml" READ_VERBS = {"get", "list", "watch"} FORBIDDEN_RESOURCES = { "secrets", "pods/log", "pods/exec", "pods/attach", "pods/portforward", "serviceaccounts/token", "nodes/proxy", "services/proxy", "pods/proxy", "roles", "rolebindings", "clusterroles", "clusterrolebindings", } EXPECTED = { ("sso", "batch", "jobs"): None, ("sso", "", "pods"): None, ("sso", "apps", "deployments"): None, ("sso", "external-secrets.io", "externalsecrets"): None, ("informed-decision", "", "configmaps"): ["informed-decision-workload-registry"], ("argocd", "argoproj.io", "applications"): ["informed-decision"], } SUBJECT = [{"kind": "ServiceAccount", "name": "nk-agent-status", "namespace": "sso"}] def _docs(): kust = yaml.safe_load((ADDON / "kustomization.yaml").read_text()) docs = [] for res in kust["resources"]: docs.extend(d for d in yaml.safe_load_all((ADDON / res).read_text()) if d) return docs def test_only_namespaced_kinds_no_secret(): kinds = sorted(d["kind"] for d in _docs()) assert kinds == ["Role"] * 3 + ["RoleBinding"] * 3 + ["ServiceAccount"] for path in ADDON.iterdir(): if path.is_file(): assert "kind: Secret" not in path.read_text(), path def test_service_account_without_automount(): (sa,) = [d for d in _docs() if d["kind"] == "ServiceAccount"] assert (sa["metadata"]["name"], sa["metadata"]["namespace"]) == ("nk-agent-status", "sso") assert sa["automountServiceAccountToken"] is False def test_roles_read_only_curated_named_outside_sso(): granted = {} for role in (d for d in _docs() if d["kind"] == "Role"): ns = role["metadata"]["namespace"] for rule in role["rules"]: values = [*rule["verbs"], *rule["apiGroups"], *rule["resources"]] assert not any("*" in v for v in values), rule assert set(rule["verbs"]) <= READ_VERBS, rule for group in rule["apiGroups"]: for resource in rule["resources"]: assert resource not in FORBIDDEN_RESOURCES, resource granted[(ns, group, resource)] = rule.get("resourceNames") assert granted == EXPECTED def test_bindings_target_only_the_agent(): for binding in (d for d in _docs() if d["kind"] == "RoleBinding"): assert binding["subjects"] == SUBJECT assert binding["roleRef"] == {"apiGroup": "rbac.authorization.k8s.io", "kind": "Role", "name": "nk-agent-status"} def test_application_manual_and_pinned(): if not APP.exists(): pytest.skip("Application not yet placed") app = yaml.safe_load(APP.read_text()) spec = app["spec"] assert spec["project"] == "railiance-platform-addons" assert spec["source"]["path"] == "argocd/platform-addons/nk-agent-status" assert re.fullmatch(r"[0-9a-f]{40}", spec["source"]["targetRevision"]) assert "automated" not in spec.get("syncPolicy", {}) assert "finalizers" not in app["metadata"]