# Nucleic runner image — the Covalence runner's host-of-record container
# (docs/COVALENCE_RUNNER.md §2, §9).
#
# Layers `nucleicd` (the headless NucleicCore host) onto the sandbox image, so one container is
# simultaneously the host-of-record AND the agent sandbox (`RunSpec.container = nil` — the
# CLOUD_RUNTIME insight): claude/codex/grok, git, gh, and the control-bridge instrumentation all
# come from the base; this image adds only the daemon and its runtime.
#
# ── Building the binary (linux/amd64 — Cloudflare Containers run amd64 ONLY) ─────────────────
# The `nucleicd` Linux build is REAL (the CLOUD_RUNTIME Phase-2 port landed: swift-crypto Noise
# interop proven by the protocol suite on Linux, GRDB-on-Linux green, BSD-socket approval
# server, 0600-file secret store, NIO relay WebSocket). The image binary is a fully-static
# x86_64-musl build via Swift's Static Linux SDK — cross-compiles at native speed from ANY host
# arch (including the arm64 swift container on an Apple-silicon Mac), no Swift runtime libs to
# ship. The proven recipe is scripted:
#
#   docker run --rm -v "$PWD":/src -w /src swift:6.3-bookworm scripts/build-nucleicd-linux.sh
#   cp .build/x86_64-swift-linux-musl/release/nucleicd containers/nucleic-runner/
#   docker build --platform linux/amd64 -t nucleic-runner containers/nucleic-runner
#
# Verified end to end: the static amd64 binary (run under qemu-x86_64) enrolls with the deployed
# relay, listens on it, and mints working pairing codes.
#
# ── Gates before this deploys to Cloudflare ──────────────────────────────────────────────────
#   • The FROM base below (nucleic-sandbox) must ship a linux/amd64 variant — Cloudflare
#     Containers run amd64 only. That landed with sandbox tag **v6**, the first multi-arch index
#     (linux/amd64 + linux/arm64; sandbox-image.yml, CLOUD_RUNTIME §3.2). v5 was arm64-only, so
#     the amd64 `RUN` layers here failed with exit 255 ("exec format" on the wrong-arch base) —
#     keep this pinned at a multi-arch tag.
#   • Push this image to **Cloudflare's managed registry** (`registry.cloudflare.com/<ACCOUNT_ID>/
#     nucleic-runner`) — NOT GHCR, which Wrangler/Cloudflare Containers can't pull without extra
#     `wrangler containers registries configure` + credentials. `wrangler containers push` handles
#     auth (CLOUDFLARE_API_TOKEN) and Cloudflare pulls it at deploy with no further config;
#     .github/workflows/runner-image.yml does this in CI. Then the wrangler `containers` block in
#     cloud/nucleic-runner/wrangler.jsonc references it. The Worker + pool DO deploy and run without
#     it, and a self-hosted box runs `nucleicd` natively with no container at all.
#     (The FROM base below stays on GHCR — it's pulled only at build time, by Docker in CI.)
FROM ghcr.io/abkslm/nucleic-sandbox:v7

COPY nucleicd /usr/local/bin/nucleicd

# Reachability transport, split by who operates the runner (WITH_TAILSCALE build arg):
#   • Nucleic-hosted (default, WITH_TAILSCALE=0): reachable ONLY over Nucleic's own relay infra
#     (nucleicd listens relay-only), so no tailscale is installed — it would be dead weight the
#     cloud runner never uses. This is the image CI builds + pushes to Cloudflare
#     (.github/workflows/runner-image.yml).
#   • Self-hosted (WITH_TAILSCALE=1, built + tagged separately — e.g. `:self-hosted`): an operator
#     may want the container reachable over THEIR tailnet, so we install the OS-level tailscale
#     package here. (nucleicd's own Tailnet transport is TailscaleKit, which is Darwin-only and has
#     no Linux build, so on Linux "tailscale" can only mean the system daemon — the operator brings
#     a TS_AUTHKEY and runs `tailscaled` + `tailscale up` alongside the daemon.) See
#     containers/nucleic-runner/README.md "Self-hosted variant".
ARG WITH_TAILSCALE=0
RUN if [ "$WITH_TAILSCALE" = "1" ]; then \
        apt-get update \
        && apt-get install -y --no-install-recommends curl ca-certificates \
        && curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.noarmor.gpg \
            -o /usr/share/keyrings/tailscale-archive-keyring.gpg \
        && curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.tailscale-keyring.list \
            -o /etc/apt/sources.list.d/tailscale.list \
        && apt-get update \
        && apt-get install -y --no-install-recommends tailscale \
        && rm -rf /var/lib/apt/lists/*; \
    fi

# The runner's store lives on the container's own (ephemeral) disk; durable state rides git
# remotes + checkpoints per CLOUD_RUNTIME §3.5. Fixed path so checkpoint tooling can find it.
ENV NUCLEIC_RUNNER_DATA_DIR=/var/lib/nucleic-runner
RUN mkdir -p /var/lib/nucleic-runner

# The pool injects the rest of the contract at start (container.ts buildContainerEnv):
#   NUCLEIC_RUNNER_POOL_ID, NUCLEIC_RUNNER_INSTANCE_ID, NUCLEIC_RUNNER_EPOCH,
#   NUCLEIC_RUNNER_INSTANCE_TOKEN, NUCLEIC_RUNNER_CONTROL_URL, NUCLEIC_RELAY_URL (optional).
# nucleicd listens relay-only by default and serves the one-shot pairing payload on the
# loopback control port (9200) for the provisioning proxy (`GET /v1/pool/pairing`).
ENTRYPOINT ["/usr/local/bin/nucleicd"]
