ci(hermes): make HUX topology gates all-or-nothing adaptive

The delivery and image-automation gates now enforce whichever state the
chat StatefulSet is actually in: with no hux sidecar they require zero
partial HUX wiring (no containers, volumes, PVC, or HUX_* env); with the
sidecar staged they enforce the full strict boundary. This lets the
reviewed source chain merge and build before the activation topology
lands, without ever waiving an activated assertion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvMSXH8VH2tMWXanb8SJdf
This commit is contained in:
jenkins 2026-08-24 04:17:02 -03:00
parent 659f70ee03
commit 13359769dc
2 changed files with 73 additions and 20 deletions

View File

@ -1,7 +1,13 @@
"""Flux delivery gates for the per-tenant HUX service boundary."""
"""Flux delivery gates for the per-tenant HUX service boundary.
The gates are topology-adaptive: before the activation commit lands, the
manifests must contain no partial HUX wiring at all; once the ``hux``
sidecar exists, every boundary assertion below is enforced strictly.
"""
from pathlib import Path
import pytest
import yaml
@ -31,6 +37,38 @@ def _statefulset() -> dict:
return yaml.safe_load(CHAT.read_text(encoding="utf-8"))
def _hux_active() -> bool:
pod = _statefulset()["spec"]["template"]["spec"]
return any(item["name"] == "hux" for item in pod["containers"])
def _require_activation() -> None:
if not _hux_active():
pytest.skip("HUX activation topology is not staged in this tree")
def test_hux_topology_is_all_or_nothing() -> None:
"""A partial HUX rollout (some wiring without the sidecar) never ships."""
stateful = _statefulset()
pod = stateful["spec"]["template"]["spec"]
if _hux_active():
return
assert not any(item["name"].startswith("hux") for item in pod["containers"])
assert not any(
item["name"] == "init-hux-runtime" for item in pod.get("initContainers", [])
)
assert not any(item["name"].startswith("hux-") for item in pod["volumes"])
claims = {
item["metadata"]["name"]
for item in yaml.safe_load_all(CHAT_PVCS.read_text(encoding="utf-8"))
}
assert "hermes-chat-hux-data" not in claims
for container in pod["containers"]:
assert not any(
entry["name"].startswith("HUX_") for entry in container.get("env", [])
)
def _named(items: list[dict], name: str) -> dict:
return next(item for item in items if item["name"] == name)
@ -45,6 +83,7 @@ def _mounts(container: dict) -> dict[str, dict]:
def test_hux_sidecar_is_loopback_only_and_uses_the_reviewed_webui_image() -> None:
"""The browser BFF and HUX backend ship as one immutable reviewed artifact."""
_require_activation()
pod = _statefulset()["spec"]["template"]["spec"]
webui = _named(pod["containers"], "webui")
hux = _named(pod["containers"], "hux")
@ -82,6 +121,7 @@ def test_hux_sidecar_is_loopback_only_and_uses_the_reviewed_webui_image() -> Non
def test_hux_storage_and_keys_are_mounted_by_least_privilege() -> None:
"""Hermes receives only its key/context views, never the HUX ledger root."""
_require_activation()
stateful = _statefulset()
pod = stateful["spec"]["template"]["spec"]
hermes = _named(pod["containers"], "hermes")
@ -125,6 +165,7 @@ def test_hux_storage_and_keys_are_mounted_by_least_privilege() -> None:
def test_hux_init_preserves_context_identity_and_rotates_transport_keys() -> None:
"""Context identity is durable while relay/worker credentials are pod-local."""
_require_activation()
pod = _statefulset()["spec"]["template"]["spec"]
init = _named(pod["initContainers"], "init-hux-runtime")
script = init["args"][0]
@ -151,6 +192,7 @@ def test_hux_init_preserves_context_identity_and_rotates_transport_keys() -> Non
def test_hux_identity_and_authentication_inputs_are_file_backed() -> None:
"""No HUX shared key or subject is placed directly in an environment value."""
_require_activation()
pod = _statefulset()["spec"]["template"]["spec"]
hermes = _env(_named(pod["containers"], "hermes"))
webui = _env(_named(pod["containers"], "webui"))
@ -173,6 +215,7 @@ def test_hux_identity_and_authentication_inputs_are_file_backed() -> None:
def test_hux_runtime_plugin_renders_its_vendored_hook_package() -> None:
"""The mounted plugin must contain its Kustomize-local Python package tree."""
_require_activation()
stateful = _statefulset()
pod = stateful["spec"]["template"]["spec"]
plugin = _named(pod["volumes"], "hux-runtime-plugin")["configMap"]

View File

@ -72,30 +72,40 @@ def test_flux_updates_only_the_reviewed_hermes_image_digests() -> None:
}
assert agent.count('"$imagepolicy": "hermes:hermes-agent-release:digest"') == 1
webui_marker = '"$imagepolicy": "hermes:hermes-webui-release"'
assert chat.count(webui_marker) == 2
chat_object = yaml.safe_load(chat)
hux = next(
(
item
for item in chat_object["spec"]["template"]["spec"]["containers"]
if item["name"] == "hux"
),
None,
)
# Before activation the chat StatefulSet carries exactly one WebUI
# consumer and no HUX setters; after activation the HUX sidecar is the
# second consumer of the very same reviewed image line, with tag and
# digest setters binding its build metadata.
assert chat.count(webui_marker) == (2 if hux else 1)
assert dashboard.count(webui_marker) == 1
assert chat.count(
'"$imagepolicy": "hermes:hermes-webui-release:tag"'
) == 1
) == (1 if hux else 0)
assert chat.count(
'"$imagepolicy": "hermes:hermes-webui-release:digest"'
) == 1
chat_object = yaml.safe_load(chat)
hux = next(
item
for item in chat_object["spec"]["template"]["spec"]["containers"]
if item["name"] == "hux"
)
hux_env = {item["name"]: item["value"] for item in hux["env"] if "value" in item}
release = re.fullmatch(
r"git-([0-9a-f]{40})-build-[1-9][0-9]*-release",
hux_env["HUX_IMAGE_TAG"],
)
assert release is not None
assert hux["image"].split(":git-", 1)[1].split("@", 1)[0] == hux_env[
"HUX_IMAGE_TAG"
].removeprefix("git-")
assert hux["image"].endswith("@" + hux_env["HUX_IMAGE_DIGEST"])
) == (1 if hux else 0)
if hux:
hux_env = {
item["name"]: item["value"] for item in hux["env"] if "value" in item
}
release = re.fullmatch(
r"git-([0-9a-f]{40})-build-[1-9][0-9]*-release",
hux_env["HUX_IMAGE_TAG"],
)
assert release is not None
assert hux["image"].split(":git-", 1)[1].split("@", 1)[0] == hux_env[
"HUX_IMAGE_TAG"
].removeprefix("git-")
assert hux["image"].endswith("@" + hux_env["HUX_IMAGE_DIGEST"])
# A digest-only setter replaces the complete YAML scalar with ``sha256:...``.
# Whole-image setters must retain the registry and repository in pod specs.
for workload in (chat, dashboard):