"""Release packaging and provenance guarantees added in v1.2.1. Two defects reached production before these existed, and both were invisible to every gate the project had. Neither was a code bug: the source was correct in both cases and the *artifact* was wrong, which is precisely the class of failure a unit test looking at source cannot see. **The console could not reach its own API.** Vite inlines ``VITE_*`` at build time, but ``release_build.py`` never passed ``VITE_API_BASE_URL``, so every release image compiled the Dockerfile's development default — ``http://localhost:8000`` — into an immutable bundle, and the nginx CSP, derived from the same argument, hardcoded the same wrong origin. The frontend test suite passed because jsdom never performs a cross-origin fetch; the release gate passed because it inspects labels and checksums, not bundle contents. It surfaced only when a human opened the production console. **The Node Agent's identity drifted from its tag.** ``docker-compose.node-agent.yml`` declared a ``build:`` block with no ``args:``, so a Compose-built agent got version ``0.0.0`` and empty revision/created labels while still being tagged from ``MODELFORGE_VERSION``. Production ran an image tagged ``1.1.1`` whose contents were ``1.2.0`` and whose OCI labels were blank. These tests read the actual release inputs — the Dockerfiles, the Compose projections and the release builder — so the same two failures cannot ship again without failing here first. """ from __future__ import annotations import re from pathlib import Path import pytest import yaml from modelforge_api.domain.release import PRODUCT_VERSION ROOT = Path(__file__).resolve().parents[2] RELEASE_BUILD = ROOT / "scripts" / "release_build.py" FRONTEND_DOCKERFILE = ROOT / "frontend" / "Dockerfile" NODE_AGENT_DOCKERFILE = ROOT / "node-agent" / "Dockerfile" #: Every image the release builder publishes. The Runtime Worker is a first-class private runtime #: artifact even though it exposes no public listener. RELEASE_IMAGES = ( "modelforge-api", "modelforge-web", "modelforge-node-agent", "modelforge-runtime-worker", ) #: The OCI fields a release image must carry for an operator to trace it back to a commit. REQUIRED_OCI_LABELS = ( "org.opencontainers.image.title", "org.opencontainers.image.version", "org.opencontainers.image.revision", "org.opencontainers.image.created", "org.opencontainers.image.source", ) def _release_build_source() -> str: return RELEASE_BUILD.read_text(encoding="utf-8") def _compose(name: str) -> dict: return yaml.safe_load((ROOT / name).read_text(encoding="utf-8")) # --------------------------------------------------------------- console API origin (defect A) def test_the_release_builder_requires_an_explicit_public_api_origin() -> None: """No origin, no release. The default that shipped v1.2.0 was a development convenience.""" source = _release_build_source() assert "--public-api-origin" in source assert "MODELFORGE_PUBLIC_API_ORIGIN" in source assert "def normalise_public_api_origin" in source def test_a_release_build_without_an_api_origin_fails_closed() -> None: import importlib.util spec = importlib.util.spec_from_file_location("modelforge_release_build", RELEASE_BUILD) assert spec and spec.loader module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) for empty in ("", " "): with pytest.raises(SystemExit) as raised: module.normalise_public_api_origin(empty) assert "public API origin" in str(raised.value) @pytest.mark.parametrize( "value", [ "localhost:8000", # no scheme: ambiguous, and how the original default looked "ftp://example.com", "https://", "https://example.com/api", # a path would be appended twice "https://example.com?x=1", ], ) def test_a_malformed_api_origin_is_refused(value: str) -> None: import importlib.util spec = importlib.util.spec_from_file_location("modelforge_release_build", RELEASE_BUILD) assert spec and spec.loader module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) with pytest.raises(SystemExit): module.normalise_public_api_origin(value) @pytest.mark.parametrize( ("given", "expected"), [ ("https://modelforge.example.com", "https://modelforge.example.com"), ("http://192.0.2.10:18000/", "http://192.0.2.10:18000"), (" https://example.com ", "https://example.com"), ], ) def test_a_valid_api_origin_is_normalised(given: str, expected: str) -> None: import importlib.util spec = importlib.util.spec_from_file_location("modelforge_release_build", RELEASE_BUILD) assert spec and spec.loader module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) assert module.normalise_public_api_origin(given) == expected def test_the_api_origin_reaches_the_console_image_build() -> None: """The validated origin must actually be passed to the build that inlines it.""" source = _release_build_source() assert "VITE_API_BASE_URL={public_api_origin}" in source assert "ORIGIN_DEPENDENT_IMAGES" in source assert "modelforge-web" in source def test_the_release_manifest_records_the_console_api_origin() -> None: """An operator must be able to see the compiled-in origin without unpacking the image.""" assert '"public_api_origin"' in _release_build_source() def test_the_console_csp_is_derived_from_the_same_origin_argument() -> None: """The bundle and the policy that protects it cannot be allowed to disagree.""" dockerfile = FRONTEND_DOCKERFILE.read_text(encoding="utf-8") assert 'API_ORIGIN=$(printf \'%s\' "${VITE_API_BASE_URL}" | cut -d/ -f1-3)' in dockerfile # The build fails rather than shipping a policy with an unsubstituted placeholder. assert 'grep -q "connect-src \'self\' ${API_ORIGIN};"' in dockerfile def test_the_console_csp_is_never_widened_to_a_wildcard() -> None: template = (ROOT / "frontend" / "security-headers.inc.template").read_text(encoding="utf-8") connect = [line for line in template.splitlines() if "connect-src" in line] assert connect, "the template must define connect-src" for line in connect: assert "connect-src 'self' __API_ORIGIN__" in line assert "*" not in line.split("connect-src", 1)[1].split(";")[0] def test_local_development_keeps_its_convenient_default() -> None: """Fail-closed is a property of the release path, not of `docker compose up` on a laptop.""" dockerfile = FRONTEND_DOCKERFILE.read_text(encoding="utf-8") assert "ARG VITE_API_BASE_URL=http://localhost:8000" in dockerfile development = _compose("docker-compose.yml")["services"]["web"]["build"]["args"] assert development["VITE_API_BASE_URL"] == "${VITE_API_BASE_URL:-http://localhost:8000}" def test_the_production_overlay_still_demands_an_api_base_url() -> None: production = _compose("docker-compose.production.yml")["services"]["web"]["build"]["args"] assert production["VITE_API_BASE_URL"].startswith("${VITE_API_BASE_URL:?") # ------------------------------------------------------------- image provenance (defect B) def test_every_release_dockerfile_declares_the_release_identity_arguments() -> None: for relative in ( "backend/Dockerfile", "frontend/Dockerfile", "node-agent/Dockerfile", "runtime-worker/Dockerfile", ): text = (ROOT / relative).read_text(encoding="utf-8") for argument in ("MODELFORGE_VERSION", "MODELFORGE_COMMIT", "MODELFORGE_BUILT_AT"): assert f"ARG {argument}" in text, f"{relative} does not accept {argument}" def test_every_release_dockerfile_emits_the_required_oci_labels() -> None: for relative in ( "backend/Dockerfile", "frontend/Dockerfile", "node-agent/Dockerfile", "runtime-worker/Dockerfile", ): text = (ROOT / relative).read_text(encoding="utf-8") for label in REQUIRED_OCI_LABELS: assert f'LABEL {label}=' in text, f"{relative} does not set {label}" def test_the_oci_version_and_revision_come_from_the_release_arguments() -> None: """A label typed in by hand is a label that drifts.""" for relative in ( "backend/Dockerfile", "frontend/Dockerfile", "node-agent/Dockerfile", "runtime-worker/Dockerfile", ): text = (ROOT / relative).read_text(encoding="utf-8") assert 'org.opencontainers.image.version="${MODELFORGE_VERSION}"' in text assert 'org.opencontainers.image.revision="${MODELFORGE_COMMIT}"' in text assert 'org.opencontainers.image.created="${MODELFORGE_BUILT_AT}"' in text def test_the_node_agent_compose_build_passes_the_release_identity() -> None: """The exact gap that let production run a 1.1.1 tag containing 1.2.0.""" build = _compose("docker-compose.node-agent.yml")["services"]["node-agent"]["build"] args = build.get("args") assert args, "the node-agent build must pass release identity arguments" assert args["MODELFORGE_VERSION"] == "${MODELFORGE_VERSION:-0.0.0}" assert args["MODELFORGE_COMMIT"] == "${MODELFORGE_COMMIT:-}" assert args["MODELFORGE_BUILT_AT"] == "${MODELFORGE_BUILT_AT:-}" def test_every_composed_release_image_passes_the_release_identity() -> None: """Whatever builds a published image must stamp it; otherwise the tag is the only identity.""" for compose_file, service in ( ("docker-compose.yml", "api"), ("docker-compose.yml", "web"), ("docker-compose.node-agent.yml", "node-agent"), ("docker-compose.runtime-worker.yml", "runtime-worker"), ): build = _compose(compose_file)["services"][service].get("build") assert build, f"{compose_file}:{service} has no build section" args = build.get("args") or {} assert "MODELFORGE_VERSION" in args, f"{compose_file}:{service} omits MODELFORGE_VERSION" assert "MODELFORGE_COMMIT" in args, f"{compose_file}:{service} omits MODELFORGE_COMMIT" def test_the_node_agent_image_reference_is_versioned_and_never_floating() -> None: service = _compose("docker-compose.node-agent.yml")["services"]["node-agent"] reference = service["image"] assert "${MODELFORGE_NODE_AGENT_IMAGE:-" in reference assert "${MODELFORGE_VERSION:-local}" in reference assert ":latest" not in reference def test_the_runtime_worker_image_reference_is_versioned_and_never_floating() -> None: service = _compose("docker-compose.runtime-worker.yml")["services"]["runtime-worker"] reference = service["image"] assert "${MODELFORGE_RUNTIME_WORKER_IMAGE:-" in reference assert "${MODELFORGE_VERSION:-local}" in reference assert ":latest" not in reference def test_the_agent_version_derives_from_the_repository_version_file() -> None: """Single-source versioning: VERSION drives every packaged manifest. Read from the file rather than imported: the Node Agent is a separate distribution and is not installed into the backend's environment, and a version test that silently skips when the import fails would be worthless. """ text = (ROOT / "node-agent" / "src" / "modelforge_node_agent" / "__init__.py").read_text( encoding="utf-8" ) match = re.search(r'__version__\s*=\s*"([^"]+)"', text) assert match, "the Node Agent must declare __version__" assert match.group(1) == PRODUCT_VERSION assert (ROOT / "VERSION").read_text(encoding="utf-8").strip() == PRODUCT_VERSION def test_the_runtime_worker_version_matches_the_release() -> None: text = (ROOT / "runtime-worker" / "src" / "modelforge_runtime_worker" / "__init__.py").read_text( encoding="utf-8" ) match = re.search(r'__version__\s*=\s*"([^"]+)"', text) assert match and match.group(1) == PRODUCT_VERSION def test_the_release_builder_publishes_exactly_the_expected_images() -> None: source = _release_build_source() for image in RELEASE_IMAGES: assert f'"{image}"' in source # ---------------------------------------------------------------- artifact reproducibility def test_release_artifacts_are_written_with_unix_line_endings() -> None: """`sha256sum -c` treats a trailing CR as part of the filename and fails on every entry. Found while verifying v1.2.0 on Windows: all four digests were correct and not one filename could be read. """ source = _release_build_source() assert source.count('newline="\\n"') >= 2 assert 'checksums.write_text("\\n".join(lines) + "\\n", encoding="utf-8", newline="\\n")' in ( source ) def test_the_build_timestamp_feeds_the_reproducible_build_contract() -> None: source = _release_build_source() assert "SOURCE_DATE_EPOCH" in source assert "def source_date_epoch" in source def test_the_release_build_refuses_a_dirty_tree_by_default() -> None: source = _release_build_source() assert "refusing to build a release from a dirty working tree" in source def test_the_release_build_records_no_host_specific_paths() -> None: """A manifest that names the machine that built it is not a portable release record.""" source = _release_build_source() for accidental in ("C:\\\\", "/home/", "/Users/", "os.getcwd()"): assert accidental not in source, f"release build references {accidental!r}"