#!/usr/bin/env python3 """Acceptance checks for forge authority, node accounts, images, and regressions. What the platform is allowed to do outside its own namespace: which forge authority a worker holds, what a node account is and is not, how an image is built and pinned, and whether the fixes the release depends on are actually running rather than merely merged. Where a property has no side-effect-free live probe — a merge that must never be attempted, a branch protection the harness identity cannot read — the entry says so in its rationale and asserts the nearest fact that *is* observable, rather than quietly asserting nothing. """ from __future__ import annotations from hermes_handoff_catalog import ( FORGE_CREDENTIAL_NAMES, INIT_NAME_PROJECTION, NODE_NAME_PROJECTION, OPERATOR, SELF, Targets, check, step, ) from hermes_handoff_model import ATTEMPT, CheckSpec from hermes_handoff_policy import GITEA_CLIENT, projection, shell def _forge(targets: Targets) -> list[CheckSpec]: api = f"/api/v1/repos/{targets.repo}" return [ check( "forge.worker-holds-no-git-credential-variable", "No forge credential is exported into the worker process", "forge", "names_absent", [step("env", SELF, *shell("env_names"))], {"step": "env", "names": FORGE_CREDENTIAL_NAMES}, rationale="The worker holds no forge credential at all: authenticated SCM traffic goes through the credential-isolated broker, never through the environment.", ), check( "forge.identity-is-not-an-administrator", "The broker's forge identity holds no administrative rights", "forge", "json_field", [step("user", SELF, GITEA_CLIENT, "read", "/api/v1/user")], {"step": "user", "fields": {"is_admin": False}}, rationale="The broker holds the only forge credential the platform can use, so its identity is the one that must not be an administrator.", ), check( "forge.repository-authority-is-push-only", "The broker's repository authority is push-scoped, never administrative", "forge", "json_field", [step("repo", SELF, GITEA_CLIENT, "read", api)], { "step": "repo", "fields": { "permissions.admin": False, "permissions.push": True, "permissions.pull": True, }, }, rationale="Merge, approve, close, and protection changes all require authority the broker identity is proven not to hold; the agent-side client additionally exposes no write besides draft creation.", ), check( "forge.administrative-route-is-refused", "An administrative forge route is refused through the broker", "forge", "denied", [ step( "attempt", SELF, GITEA_CLIENT, "read", f"{api}/branch_protections", kind=ATTEMPT, ) ], rationale="A live refusal from the broker's read allowlist, not a configuration reading. Other mandatory broker reads in this run prove the broker is healthy, so an outage cannot masquerade as this refusal across the catalog.", ), ] def _nodes(targets: Targets) -> list[CheckSpec]: return [ check( "nodes.hardening-covers-every-node", "The node account audit runs on every node in the cluster", "nodes", "distinct_count", [ step( "coverage", OPERATOR, "kubectl", "--namespace", targets.namespace, "get", "pods", "--selector", f"app={targets.node_daemonset}", "-o", NODE_NAME_PROJECTION, ) ], { "step": "coverage", "minimum": targets.node_count, "total_equals": targets.node_count, }, rationale="A hardened fleet with one unenrolled node is an unhardened fleet.", ), ] def _build(targets: Targets) -> list[CheckSpec]: pipeline = f"{targets.remote}/main:{targets.builder_pipeline}" return [ check( "build.builder-service-account-is-tokenless", "The image builder service account mounts no API token", "build", "stdout_matches", [ step( "serviceaccount", OPERATOR, "kubectl", "--namespace", targets.builder_namespace, "get", "serviceaccount", targets.builder_serviceaccount, "-o", projection("jsonpath={.automountServiceAccountToken}"), ) ], {"step": "serviceaccount", "equals": "false"}, ), check( "build.builder-runs-unprivileged-with-exact-capabilities", "The build pod is unprivileged and adds only the expected capabilities", "build", "names_present", [step("pipeline", OPERATOR, "git", "show", pipeline, record=False)], { "step": "pipeline", "names": ( targets.builder_capabilities, "privileged: false", "allowPrivilegeEscalation: false", "automountServiceAccountToken: false", 'drop: ["ALL"]', ), }, rationale="Exact lines, not a substring sweep: a widened capability set has to change one of these lines to take effect.", ), check( "build.harbor-immutability-rule-is-applied", "The Harbor immutable-tag rule for the agent image has been applied", "build", "lines_match", [ step( "job", OPERATOR, "kubectl", "--namespace", targets.harbor_namespace, "get", "job", targets.harbor_immutability_job, "-o", projection("jsonpath={.status.succeeded}"), ) ], {"step": "job", "pattern": r"^[1-9][0-9]*$", "minimum": 1}, rationale="The job verifies the rule it creates, so a completed run is evidence the rule matched the expected contract.", ), _release_lineage(targets), ] def _release_lineage(targets: Targets) -> CheckSpec: """Bind the exact reviewed release from Git through the Ready pods.""" container = targets.agent_container namespace = targets.namespace deployment = f"deploy/{targets.agent_deployment}" deployment_projection = projection( ( "jsonpath={.metadata.generation}{'\\t'}{.status.observedGeneration}{'\\t'}" "{.spec.replicas}{'\\t'}{.status.readyReplicas}{'\\t'}" "{.metadata.annotations.deployment\\.kubernetes\\.io/revision}{'\\t'}" f'{{.spec.template.spec.containers[?(@.name=="{container}")].image}}' ).replace("'", '"') ) pod_projection = projection( ( "jsonpath={range .items[*]}{.metadata.name}{'\\t'}{.status.phase}{'\\t'}" "{range .status.conditions[?(@.type==\"Ready\")]}{.status}{end}{'\\t'}" f'{{.spec.containers[?(@.name=="{container}")].image}}{{"\\t"}}' f'{{.status.containerStatuses[?(@.name=="{container}")].imageID}}{{"\\t"}}' "{.metadata.labels.pod-template-hash}{'\\n'}{end}" ).replace("'", '"') ) replicaset_projection = projection( ( "jsonpath={range .items[*]}{.metadata.name}{'\\t'}" "{.metadata.annotations.deployment\\.kubernetes\\.io/revision}{'\\t'}" "{.status.readyReplicas}{'\\t'}{.status.availableReplicas}{'\\t'}" f'{{.spec.template.spec.containers[?(@.name=="{container}")].image}}{{"\\t"}}' "{.metadata.labels.pod-template-hash}{'\\n'}{end}" ).replace("'", '"') ) flux_projection = projection( ( "jsonpath={.metadata.name}{'\\t'}{.metadata.generation}{'\\t'}" "{.status.observedGeneration}{'\\t'}{.spec.suspend}{'\\t'}" "{range .status.conditions[?(@.type==\"Ready\")]}{.status}{end}{'\\t'}" "{.status.lastAppliedRevision}" ).replace("'", '"') ) return check( "release.exact-lineage-is-running", "Remote main, merged reviewed PR, image, build, Flux, and running revision agree", "release", "release_lineage", [ step( "remote-main", OPERATOR, "git", "ls-remote", targets.remote, "refs/heads/main", ), step( "reviewed-pr", OPERATOR, GITEA_CLIENT, "read", f"/api/v1/repos/{targets.repo}/pulls/{targets.reviewed_pr_number}", ), step( "build-source", OPERATOR, "git", "rev-parse", f"{targets.remote}/main", ), step( "merge-ancestry", OPERATOR, "git", "merge-base", "--is-ancestor", targets.reviewed_head_sha, f"{targets.remote}/main", ), step( "deployment", OPERATOR, "kubectl", "--namespace", namespace, "get", deployment, "-o", deployment_projection, ), step( "pods", OPERATOR, "kubectl", "--namespace", namespace, "get", "pods", "--selector", f"app={targets.agent_deployment}", "-o", pod_projection, ), step( "replicasets", OPERATOR, "kubectl", "--namespace", namespace, "get", "replicasets", "--selector", f"app={targets.agent_deployment}", "-o", replicaset_projection, ), step( "flux", OPERATOR, "kubectl", "--namespace", "flux-system", "get", "kustomization/hermes", "-o", flux_projection, ), ], { "main_sha": targets.remote_main_sha, "head_sha": targets.reviewed_head_sha, "head_ref": targets.reviewed_head_ref, "pr_number": targets.reviewed_pr_number, "image": targets.agent_image, "build_sha": targets.build_sha, "deployment_revision": targets.deployment_revision, }, rationale="A PASS requires one exact release identity across every source and running object. The remote-main step needs a fetchable origin from the operator checkout: ensure `git ls-remote origin refs/heads/main` works with the operator's own forge access before the run, or this check is NOT_RUN.", ) def _reliability(targets: Targets) -> list[CheckSpec]: return [ check( "reliability.finalization-and-replay-patches-are-deployed", "The agent workload runs the finalization, replay, and session patches", "reliability", "names_present", [ step( "init", OPERATOR, "kubectl", "--namespace", targets.namespace, "get", f"deploy/{targets.agent_deployment}", "-o", INIT_NAME_PROJECTION, ) ], {"step": "init", "names": targets.agent_init_containers}, rationale="The regression suites live in the repository; this asserts the fixes they cover are actually running.", ), check( "reliability.regression-suites-are-present-on-main", "The decomposition and worker-recovery regression suites are on main", "reliability", "names_present", [ step( "suites", OPERATOR, "git", "ls-tree", "--name-only", f"{targets.remote}/main", "testing/tests/", ) ], { "step": "suites", "names": ( "testing/tests/test_hermes_cli_lanes.py", "testing/tests/test_hermes_coordinator.py", "testing/tests/test_hermes_worker_recovery.py", ), }, ), ] def delivery_checks(targets: Targets) -> list[CheckSpec]: """Return the forge, node, build, and reliability checks.""" return [ *_forge(targets), *_nodes(targets), *_build(targets), *_reliability(targets), ]