"""Contract tests for the Docker image's immutable /opt/hermes install tree.""" from __future__ import annotations import re from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] DOCKERFILE = REPO_ROOT / "Dockerfile" def _dockerfile_text() -> str: return DOCKERFILE.read_text() def test_dockerfile_makes_opt_hermes_readonly_for_hermes_user() -> None: text = _dockerfile_text() # --chmod on the source COPY bakes read-only perms at copy time instead # of a separate chmod -R pass (which walked ~30k files — #49113). assert "COPY --link --chmod=a+rX,go-w . ." in text # The old tree-walking passes must not be present. assert "chown -R root:root /opt/hermes" not in text assert "chmod -R a+rX /opt/hermes" not in text assert "chmod -R a-w /opt/hermes" not in text def test_dockerfile_keeps_mutable_state_under_opt_data() -> None: text = _dockerfile_text() assert "ENV HERMES_HOME=/opt/data" in text assert "ENV HERMES_WRITE_SAFE_ROOT=/opt/data" in text assert 'VOLUME [ "/opt/data" ]' in text def test_dockerfile_disables_runtime_install_mutations() -> None: text = _dockerfile_text() assert "ENV PYTHONDONTWRITEBYTECODE=1" in text assert "ENV HERMES_DISABLE_LAZY_INSTALLS=1" in text assert "HERMES_TUI_DIR=/opt/hermes/ui-tui" in text def test_dockerfile_does_not_chown_install_trees_to_hermes() -> None: text = _dockerfile_text() forbidden_patterns = ( r"chown\s+-R\s+hermes:hermes\s+/opt/hermes/\.venv", r"chown\s+-R\s+hermes:hermes\s+/opt/hermes/ui-tui", r"chown\s+-R\s+hermes:hermes\s+/opt/hermes/gateway", r"chown\s+-R\s+hermes:hermes\s+/opt/hermes/node_modules", ) for pattern in forbidden_patterns: assert not re.search(pattern, text), ( "runtime install trees under /opt/hermes must stay immutable; " f"found forbidden pattern {pattern!r}" ) def test_dockerfile_bakes_code_scoped_install_method_stamp() -> None: """The 'docker' install-method stamp is baked next to the code. detect_install_method() reads the code-scoped stamp (/opt/hermes/.install_method) first; baking it at build time keeps the published image self-identifying as 'docker' WITHOUT writing into the shared $HERMES_HOME data volume (which a host install may also use). The stamp is created by root in the shim-wiring RUN block; the hermes user can't modify it (go-w from the --chmod on the source COPY). """ text = _dockerfile_text() assert "printf 'docker\\n' > /opt/hermes/.install_method" in text # The stamp must be in the RUN block that wires the exec shim. shim_block = re.search( r"RUN mkdir -p /opt/hermes/bin && \\\n" r"(?:.*\\\n)+?" r"\s+printf 'docker\\n' > /opt/hermes/\.install_method", text, ) assert shim_block, "install-method stamp must be in the shim-wiring RUN block"