# ARQERA Twin Runner — lightweight GHA self-hosted runner image.
#
# CARDINAL RULE (operator directive 2026-05-27):
#   ARQERA decides which LLM worker to use. This image does NOT ship
#   any Anthropic / OpenAI / Modal / vllm SDK. There is exactly one
#   inference helper: scripts/twin/ask_arqera.py, which POSTs to
#   {ARQERA_BASE_URL}/api/v1/ai/route with the runner's ARQERA_API_KEY.
#
# Substrate basis:
#   - arq://doc/policy/twin-dispatch-mesh-only-v2
#   - arq://doc/principle/every-platform-is-a-peer-v1
#
# Image is published to ghcr.io/Arqera-IO/twin-runner:<tag> by the
# .github/workflows/build-twin-runner-image.yml workflow.

FROM ghcr.io/actions/actions-runner:latest

USER root

# ---- OS deps ---------------------------------------------------------
# python3.12 + pip, jq, gh, kubectl, cloudflared — that's it.
# Deliberately NO anthropic, openai, modal, vllm, transformers, torch
# anywhere in this image. If a workflow needs inference it asks ARQERA.
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
        software-properties-common \
        curl \
        ca-certificates \
        gnupg \
        lsb-release \
        jq \
        git \
        openssh-client \
        libatomic1 \
        libssl3 \
        libcurl4 \
        libxml2 \
        libsqlite3-0 \
        zlib1g \
        unzip \
        xz-utils \
 && add-apt-repository -y ppa:deadsnakes/ppa \
 && apt-get update \
 && apt-get install -y --no-install-recommends \
        python3.12 \
        python3.12-venv \
        python3-pip \
 && rm -rf /var/lib/apt/lists/*

# Symlink python3 → python3.12 for predictability
RUN ln -sf /usr/bin/python3.12 /usr/local/bin/python3 \
 && ln -sf /usr/bin/python3.12 /usr/local/bin/python

# ---- Lightweight Python deps ---------------------------------------
# requests   → HTTPS to ARQERA's /api/v1/ai/route
# pyyaml     → mesh-bridge config parsing
# No LLM SDKs by design.
RUN pip3 install --no-cache-dir --break-system-packages \
        requests==2.32.3 \
        pyyaml==6.0.2

# ---- gh CLI ---------------------------------------------------------
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
        | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
 && chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
 && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
        > /etc/apt/sources.list.d/github-cli.list \
 && apt-get update \
 && apt-get install -y --no-install-recommends gh \
 && rm -rf /var/lib/apt/lists/*

# ---- kubectl --------------------------------------------------------
# Read-only-by-default kubeconfig is mounted by the workflow; image
# does NOT carry credentials.
RUN curl -fsSL "https://dl.k8s.io/release/$(curl -fsSL https://dl.k8s.io/release/stable.txt)/bin/linux/$(dpkg --print-architecture)/kubectl" \
        -o /usr/local/bin/kubectl \
 && chmod +x /usr/local/bin/kubectl

# ---- cloudflared ----------------------------------------------------
RUN ARCH=$(dpkg --print-architecture) \
 && curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${ARCH}" \
        -o /usr/local/bin/cloudflared \
 && chmod +x /usr/local/bin/cloudflared

# ---- arq-* mesh bridges --------------------------------------------
# Substrate-mediated dispatch verbs. These call mesh peers, not vendor
# APIs directly. mesh-enforce.sh in PreToolUse blocks bare gh/kubectl
# to mutating endpoints — workflows must use these wrappers.
COPY scripts/mesh-bridge/ /usr/local/bin/mesh-bridge/
RUN find /usr/local/bin/mesh-bridge -maxdepth 1 -type f -name 'arq-*' \
        -exec chmod +x {} \; \
 && for f in /usr/local/bin/mesh-bridge/arq-*; do \
        name=$(basename "$f"); \
        ln -sf "/usr/local/bin/mesh-bridge/$name" "/usr/local/bin/$name"; \
    done

# ---- ask_arqera.py (the only inference helper) ----------------------
COPY scripts/twin/ask_arqera.py /usr/local/bin/ask_arqera.py
RUN chmod +x /usr/local/bin/ask_arqera.py

# ---- Entrypoint -----------------------------------------------------
COPY infrastructure/docker/twin-runner/entrypoint.sh /usr/local/bin/twin-runner-entrypoint.sh
RUN chmod +x /usr/local/bin/twin-runner-entrypoint.sh

# Substrate label discipline — image carries its own routing assertions.
LABEL io.arqera.image="twin-runner"
LABEL io.arqera.policy="arq://doc/policy/twin-dispatch-mesh-only-v2"
LABEL io.arqera.principle="arq://doc/principle/every-platform-is-a-peer-v1"
LABEL io.arqera.no-hardcoded-llm-providers="true"

USER runner

ENTRYPOINT ["/usr/local/bin/twin-runner-entrypoint.sh"]
