From b5edcab3263876bc4976b250f9ffc8fc11093bb8 Mon Sep 17 00:00:00 2001 From: HumbleTurtle Date: Thu, 30 Jul 2026 00:22:31 -0300 Subject: [PATCH] Build gateway image from pinned repository source --- Dockerfile | 42 +++++++++++----------------- MANIFEST.json | 10 +++++-- README.md | 8 ++++-- scripts/test_gateway_image_source.py | 18 ++++++++++++ 4 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 scripts/test_gateway_image_source.py diff --git a/Dockerfile b/Dockerfile index abd7400..986749f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,35 +1,27 @@ -FROM registry.fedoraproject.org/fedora:42 +FROM registry.fedoraproject.org/fedora:42@sha256:63773f454664cd77e239f8e0b13ae7f18effe9e3d6612a325b5646eb3bda11f1 WORKDIR /workspace -RUN dnf -y install ca-certificates curl git openssh-clients python3 tmux util-linux \ +ARG GATEWAY_SOURCE_REVISION=unresolved +LABEL org.opencontainers.image.source="https://github.com/napseer/gateway" \ + org.opencontainers.image.revision="${GATEWAY_SOURCE_REVISION}" + +RUN dnf -y install ca-certificates git openssh-clients python3 tmux util-linux \ && dnf clean all -RUN python3 - <<'PY' -import json -import os -import pathlib -import subprocess -import sys -import urllib.request +COPY resources/scripts/napseer_mcp_server.py /opt/napseer/napseer_mcp_server.py +COPY resources/scripts/napseer_spake2.py /opt/napseer/napseer_spake2.py +COPY resources/scripts/terminal/ /opt/napseer/terminal/ -base_url = "https://api.napseer.com" -request = urllib.request.Request( - f"{base_url}/v1/scripts/nap_install.py", - headers={"User-Agent": "napseer-gateway-docker/0.1"}, -) -payload = json.loads(urllib.request.urlopen(request, timeout=30).read().decode("utf-8")) -installer = pathlib.Path("/tmp/nap_install.py") -installer.write_text(payload["content"], encoding="utf-8") -subprocess.check_call( - [sys.executable, str(installer), "install"], - env={**os.environ, "NAPSEER_HOME": "/opt/napseer", "NAPSEER_BIN_DIR": "/usr/local/bin", "NAPSEER_BASE_URL": base_url}, -) -PY +RUN python3 -m py_compile \ + /opt/napseer/napseer_mcp_server.py \ + /opt/napseer/napseer_spake2.py \ + /opt/napseer/terminal/__init__.py \ + /opt/napseer/terminal/protocol.py \ + /opt/napseer/terminal/pty_manager.py \ + && chmod 0755 /opt/napseer/napseer_mcp_server.py ENV PYTHONPATH=/opt/napseer -ENV NAPSEER_HOME=/opt/napseer -ENV NAPSEER_BIN_DIR=/usr/local/bin ENV NAPSEER_BASE_URL=https://api.napseer.com ENV NAPSEER_GATEWAY_PORT=0 ENV NAPSEER_GATEWAY_PTY_TERMINAL=1 @@ -37,4 +29,4 @@ ENV NAPSEER_SERVICE_ACTIVATION_TIMEOUT_SECONDS=900 VOLUME ["/workspace/.napseer"] -CMD ["sh", "-c", "nap gateway configure && python3 /opt/napseer/napseer_mcp_server.py gateway service run"] +CMD ["python3", "/opt/napseer/napseer_mcp_server.py", "gateway", "service", "run"] diff --git a/MANIFEST.json b/MANIFEST.json index b4f7dc4..f1d1da2 100644 --- a/MANIFEST.json +++ b/MANIFEST.json @@ -1,6 +1,6 @@ { "name": "gateway", - "source": "backend-split-import", + "source": "napseer-gateway", "contract_version": "2026-05-02", "owned_surface": [ "gateway service runtime", @@ -9,5 +9,11 @@ "gateway vault", "gateway Docker image" ], - "migration_status": "initial source refresh from backend resources/scripts" + "build_policy": { + "runtime_source": "repository-owned", + "network_downloads_during_image_build": false, + "base_image_pinned_by_digest": true, + "source_revision_label": "org.opencontainers.image.revision" + }, + "migration_status": "gateway image builds only repository-owned runtime source" } diff --git a/README.md b/README.md index 2dfa243..0b8bef9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Gateway runtime source for Napseer. -This repository is intended to become the canonical source for: +This repository is the canonical source for: - Gateway service runtime. - Local terminal/chat execution managers. @@ -12,9 +12,11 @@ This repository is intended to become the canonical source for: Current state: -- `resources/scripts/napseer_mcp_server.py` is still the pre-split runtime script copied from the backend. +- `resources/scripts/napseer_mcp_server.py` contains the gateway service runtime + while compatibility decomposition continues. - `resources/scripts/terminal/` contains the terminal runtime helpers. - `scripts/` contains gateway-focused smoke and runtime tests. -- `Dockerfile` installs the published `nap` command and runs gateway service mode. +- `Dockerfile` copies repository-owned runtime files into a digest-pinned base + image. It performs no live Napseer API download during the build. The backend remains the protocol and compatibility source of truth through `/v1/gateway-protocol`. diff --git a/scripts/test_gateway_image_source.py b/scripts/test_gateway_image_source.py new file mode 100644 index 0000000..5c9b8a5 --- /dev/null +++ b/scripts/test_gateway_image_source.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +"""Verify that the gateway image is built from pinned repository source.""" + +import pathlib + + +ROOT = pathlib.Path(__file__).resolve().parents[1] +dockerfile = (ROOT / "Dockerfile").read_text(encoding="utf-8") + +assert "FROM registry.fedoraproject.org/fedora:42@sha256:" in dockerfile +assert "COPY resources/scripts/napseer_mcp_server.py" in dockerfile +assert "COPY resources/scripts/terminal/" in dockerfile +assert "/v1/scripts" not in dockerfile +assert "nap_install.py" not in dockerfile +assert "urllib.request" not in dockerfile +assert 'CMD ["python3", "/opt/napseer/napseer_mcp_server.py"' in dockerfile + +print("ok: gateway image uses pinned repository-owned source")