atlas-iac/testing/tests/test_hermes_webui_brand.py
2026-08-23 04:42:08 +00:00

321 lines
12 KiB
Python

"""Canonical icon, PWA, and fail-closed Hermes WebUI identity contracts."""
from __future__ import annotations
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import shutil
import struct
import subprocess
import sys
from urllib.parse import urlsplit
import pytest
ROOT = Path(__file__).resolve().parents[2]
DOCKERFILES = ROOT / "dockerfiles"
FIXTURE = ROOT / "testing/fixtures/hermes-webui-0.52.181"
AGENT_FIXTURE = ROOT / "testing/fixtures/hermes-agent"
ATLAS_PATCHER = DOCKERFILES / "hermes-webui-atlas-patch.py"
BRAND_PATCHER = DOCKERFILES / "hermes-webui-brand-patch.py"
MANIFEST_PATCHER = DOCKERFILES / "hermes-webui-manifest-patch.py"
SMOKE = DOCKERFILES / "hermes-webui-smoke.py"
ASSETS = DOCKERFILES / "hermes-webui-assets"
MANIFEST = DOCKERFILES / "hermes-webui-manifest.json"
BRAND_CSS = DOCKERFILES / "hermes-webui-brand.css"
EXPECTED_HASHES = {
"hermes-agent.ico": "aefe65e6574e6f46d3382588f46c508e1b3f3b3c9ce3dec6d335403a5374add9",
"hermes-agent-192.png": "0e4102cc715372058dd6ab55e9cde2567e46fee5ab6557b564cdd212ccd2616f",
"hermes-agent-512.png": "6661e5ca0ecc690af213b9f85f961541e6d3d0e36946ede9d3c2c97dfbd3c23d",
}
def _load(path: Path, name: str):
spec = importlib.util.spec_from_file_location(name, path)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def _patched_fixture(tmp_path: Path) -> Path:
target = tmp_path / "hermes-webui"
agent_target = tmp_path / "hermes-agent"
shutil.copytree(FIXTURE, target)
shutil.copytree(AGENT_FIXTURE, agent_target)
env = os.environ.copy()
env["HERMES_WEBUI_PATCH_ROOT"] = str(target)
env["HERMES_AGENT_PATCH_ROOT"] = str(agent_target)
env["HERMES_WEBUI_MANIFEST_SOURCE"] = str(MANIFEST)
for patcher in (ATLAS_PATCHER, BRAND_PATCHER, MANIFEST_PATCHER):
subprocess.run(
[sys.executable, str(patcher)],
cwd=ROOT,
env=env,
check=True,
capture_output=True,
text=True,
)
return target
def _png_size(path: Path) -> tuple[int, int]:
payload = path.read_bytes()
assert payload.startswith(b"\x89PNG\r\n\x1a\n")
assert payload[12:16] == b"IHDR"
return struct.unpack(">II", payload[16:24])
def test_canonical_icon_provenance_format_and_pwa_derivatives() -> None:
"""The supplied persona is tracked exactly and only resized for PWA use."""
for name, expected in EXPECTED_HASHES.items():
payload = (ASSETS / name).read_bytes()
assert hashlib.sha256(payload).hexdigest() == expected
ico = (ASSETS / "hermes-agent.ico").read_bytes()
reserved, image_type, count = struct.unpack_from("<HHH", ico)
assert (reserved, image_type, count) == (0, 1, 3)
sizes = set()
for index in range(count):
offset = 6 + index * 16
width, height, _colors, _reserved, planes, depth, length, start = (
struct.unpack_from("<BBBBHHII", ico, offset)
)
sizes.add((width or 256, height or 256))
assert (planes, depth) == (1, 32)
assert ico[start : start + 8] == b"\x89PNG\r\n\x1a\n"
assert start + length <= len(ico)
assert sizes == {(16, 16), (32, 32), (48, 48)}
assert _png_size(ASSETS / "hermes-agent-192.png") == (192, 192)
assert _png_size(ASSETS / "hermes-agent-512.png") == (512, 512)
provenance = (ASSETS / "SOURCE.md").read_text(encoding="utf-8")
assert "/opt/hermes/web/public/favicon.ico" in provenance
assert EXPECTED_HASHES["hermes-agent.ico"] in provenance
assert "LANCZOS" in provenance
def test_manifest_is_installable_scoped_and_uses_only_canonical_persona() -> None:
"""The app has both mandatory icon sizes and no remote or secret-bearing data."""
manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
assert manifest["id"] == "./"
assert manifest["name"] == "Hermes Chat"
assert manifest["short_name"] == "Hermes"
assert manifest["start_url"].startswith("./")
assert manifest["scope"] == "./"
assert manifest["display"] == "standalone"
assert manifest["background_color"] == "#070A12"
assert manifest["theme_color"] == "#0D1420"
icons = manifest["icons"]
assert {(icon["sizes"], icon["type"]) for icon in icons} == {
("192x192", "image/png"),
("512x512", "image/png"),
}
assert {icon["src"] for icon in icons} == {
"static/hermes-agent-192.png",
"static/hermes-agent-512.png",
}
assert all(icon["purpose"] == "any" for icon in icons)
serialized = json.dumps(manifest).lower()
assert "http:" not in serialized and "https:" not in serialized
assert "secret" not in serialized and "token" not in serialized
def test_production_patchers_apply_title_icons_theme_and_cache_contract(
tmp_path: Path,
) -> None:
"""Exercise the shipped patchers against pinned upstream source fragments."""
target = _patched_fixture(tmp_path)
index = (target / "static/index.html").read_text(encoding="utf-8")
worker = (target / "static/sw.js").read_text(encoding="utf-8")
assert index.count("<title>Hermes Chat</title>") == 1
assert index.count('id="hermesBrandStyles"') == 1
assert 'href="static/hermes-agent.ico"' in index
assert 'sizes="192x192" href="static/hermes-agent-192.png"' in index
assert 'sizes="512x512" href="static/hermes-agent-512.png"' in index
assert '<meta name="apple-mobile-web-app-title" content="Hermes Chat">' in index
assert '<meta name="theme-color" content="#0D1420"' in index
assert 'id="appTitlebarTitle">Hermes Chat</span>' in index
assert '<img src="static/hermes-agent-192.png" alt="">' in index
assert "favicon.svg" not in index
assert "favicon-32.png" not in index
assert worker.count("'./static/hermes-brand.css' + VQ") == 1
for name in EXPECTED_HASHES:
assert worker.count(f"'./static/{name}'") == 1
assert "favicon.svg" not in worker
assert "favicon-32.png" not in worker
def test_brand_patch_rejects_upstream_drift_before_partial_success(
tmp_path: Path,
) -> None:
"""A changed pinned title/favicon context cannot silently ship partial branding."""
target = _patched_fixture(tmp_path)
index = target / "static/index.html"
index.write_text(
index.read_text(encoding="utf-8").replace(
"<title>Hermes Chat</title>", "<title>Upstream changed</title>", 1
),
encoding="utf-8",
)
env = os.environ.copy()
env["HERMES_WEBUI_PATCH_ROOT"] = str(target)
result = subprocess.run(
[sys.executable, str(BRAND_PATCHER)],
cwd=ROOT,
env=env,
check=False,
capture_output=True,
text=True,
)
assert result.returncode != 0
assert "brand patch context changed" in result.stderr
def test_manifest_patch_rejects_drift_before_wholesale_replacement(
tmp_path: Path,
) -> None:
"""The branded file cannot hide a changed manifest in the pinned image."""
target = tmp_path / "hermes-webui"
shutil.copytree(FIXTURE, target)
installed = target / "static/manifest.json"
installed.write_text(
installed.read_text(encoding="utf-8").replace(
'"name": "Hermes"', '"name": "Upstream drift"', 1
),
encoding="utf-8",
)
before = installed.read_bytes()
env = os.environ.copy()
env["HERMES_WEBUI_PATCH_ROOT"] = str(target)
env["HERMES_WEBUI_MANIFEST_SOURCE"] = str(MANIFEST)
result = subprocess.run(
[sys.executable, str(MANIFEST_PATCHER)],
cwd=ROOT,
env=env,
check=False,
capture_output=True,
text=True,
)
assert result.returncode != 0
assert "pinned upstream SHA-256 mismatch" in result.stderr
assert installed.read_bytes() == before
class _SmokeResponse:
status = 200
def __init__(self, body: bytes, url: str) -> None:
self.body = body
self.url = url
def __enter__(self):
return self
def __exit__(self, *_args):
return None
def read(self) -> bytes:
return self.body
def geturl(self) -> str:
return self.url
def test_server_smoke_resolves_served_manifest_icons_and_checks_root() -> None:
"""The image gate validates HTTP responses, not its own source files."""
module = _load(SMOKE, "hermes_webui_smoke_contract")
manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
root = (
b'<link href="static/hermes-agent.ico">'
b'<link href="static/hermes-agent-192.png">'
b'<link href="static/hermes-agent-512.png">'
b'<link href="static/hermes-brand.css?v=reviewed">'
)
calls = []
def open_fixture(request, *, timeout):
assert timeout == 5
url = request.full_url
calls.append(url)
path = urlsplit(url).path
if path == "/manifest.json":
return _SmokeResponse(
json.dumps(manifest).encode(),
"http://assets.hermes.test/pwa/manifest.json",
)
if path == "/":
return _SmokeResponse(root, url)
if path in (
"/pwa/static/hermes-agent-192.png",
"/pwa/static/hermes-agent-512.png",
"/static/hermes-agent-192.png",
):
return _SmokeResponse(module.PNG_MAGIC + b"fixture", url)
raise AssertionError(f"unexpected smoke URL: {url}")
result = module.smoke("http://hermes.test/", opener=open_fixture)
assert result["manifest"] == "http://assets.hermes.test/pwa/manifest.json"
assert result["icon_requests"] == 3
assert calls.count("http://assets.hermes.test/pwa/static/hermes-agent-192.png") == 2
assert "http://assets.hermes.test/pwa/static/hermes-agent-512.png" in calls
assert calls.count("http://hermes.test/static/hermes-agent-192.png") == 1
def test_server_smoke_rejects_unbranded_served_manifest() -> None:
"""A successful health check cannot mask the upstream PWA identity."""
module = _load(SMOKE, "hermes_webui_smoke_unbranded")
def open_upstream(request, *, timeout):
assert timeout == 5
payload = (FIXTURE / "static/manifest.json").read_bytes()
return _SmokeResponse(payload, request.full_url)
with pytest.raises(RuntimeError, match="not branded"):
module.smoke("http://hermes.test/", opener=open_upstream)
def test_brand_css_is_accessible_dark_and_reduced_motion_aware() -> None:
"""Identity colors retain system controls and disable cosmetic motion."""
css = BRAND_CSS.read_text(encoding="utf-8")
dark = css.split(":root.dark {", 1)[1]
assert "color-scheme: dark" in dark
assert "--bg: #070a12" in dark
assert "--text: #e8f1f4" in dark
assert "--accent: #48cfcc" in dark
assert "--voice-accent: 72, 207, 204" in css
assert "--voice-accent-secondary: 76, 164, 205" in css
assert "@media (prefers-reduced-motion: reduce)" in css
reduced = css.split("@media (prefers-reduced-motion: reduce)", 1)[1]
assert "transition: none !important" in reduced
assert "animation:" not in css
def test_dockerfile_copies_and_verifies_every_tracked_brand_asset() -> None:
"""The immutable image, not a runtime coordinator path, owns PWA assets."""
dockerfile = (DOCKERFILES / "Dockerfile.hermes-webui").read_text(encoding="utf-8")
assert "/opt/hermes/web/public/favicon.ico" not in dockerfile
assert "COPY dockerfiles/hermes-webui-brand-patch.py" in dockerfile
assert "python /tmp/hermes-webui-brand-patch.py" in dockerfile
assert "COPY dockerfiles/hermes-webui-manifest-patch.py" in dockerfile
assert "python /tmp/hermes-webui-manifest-patch.py" in dockerfile
assert (
"COPY dockerfiles/hermes-webui-manifest.json /tmp/hermes-webui-manifest.json"
in dockerfile
)
assert (
"COPY dockerfiles/hermes-webui-manifest.json /opt/hermes-webui/static/manifest.json"
not in dockerfile
)
assert "python /tmp/hermes-webui-smoke.py http://127.0.0.1:18787/" in dockerfile
assert "COPY dockerfiles/hermes-webui-brand.css" in dockerfile
for name, digest in EXPECTED_HASHES.items():
assert f"COPY dockerfiles/hermes-webui-assets/{name}" in dockerfile
assert digest in dockerfile