FROM rust:1-bookworm

RUN apt-get update && apt-get install -y --no-install-recommends \
    bash \
    passwd \
    fish \
    git \
    curl \
    build-essential \
    clang \
    pkg-config \
    sudo \
    python3 \
    libclamav-dev \
    clamav \
    clamav-freshclam \
    libclang-dev \
    hyperfine \
    dbus \
    policykit-1 \
    nftables \
    libnftables-dev \
    iproute2 \
    util-linux \
    qemu-system-x86 \
    qemu-utils \
    cloud-image-utils \
    openssh-client \
    xauth \
    qdbus-qt5 \
    d-feet \
    libwebkit2gtk-4.1-dev \
    wget \
    file \
    openssl \
    libayatana-appindicator3-dev \
    librsvg2-common \
    fonts-dejavu \
    perl \
    libglib2.0-dev \
    libgdk-pixbuf-2.0-dev \
    libatk1.0-dev \
    libatkmm-1.6-dev \
    libsoup-3.0-dev \
    libbz2-dev \
    liblzma-dev \
    zlib1g-dev \
    && rm -rf /var/lib/apt/lists/*

# Bookworm's Binaryen 108 breaks the current multi-table WASM externref export.
RUN set -eu; \
    version=133; \
    case "$(dpkg --print-architecture)" in \
        amd64) \
            architecture=x86_64; \
            checksum=2dc9c7813f5375db93d96ead4b78222fcc3e2677bbb832297af4797782a37489 \
            ;; \
        arm64) \
            architecture=aarch64; \
            checksum=89c07ea56faf38d0fbecf36ca8ec0721756716185f265b568e133d427f299bf8 \
            ;; \
        *) printf 'unsupported Binaryen architecture\n' >&2; exit 1 ;; \
    esac; \
    temporary_root=$(mktemp -d); \
    trap 'rm -rf -- "$temporary_root"' EXIT; \
    archive="binaryen-version_${version}-${architecture}-linux.tar.gz"; \
    curl --fail --show-error --location --proto '=https' --proto-redir '=https' \
        --retry 3 --connect-timeout 15 --max-time 180 \
        "https://github.com/WebAssembly/binaryen/releases/download/version_${version}/${archive}" \
        --output "$temporary_root/$archive"; \
    printf '%s  %s\n' "$checksum" "$temporary_root/$archive" | sha256sum --check --strict -; \
    tar -xzf "$temporary_root/$archive" -C "$temporary_root" --strip-components=2 \
        "binaryen-version_${version}/bin/wasm-opt"; \
    test "$("$temporary_root/wasm-opt" --version)" = "wasm-opt version $version (version_$version)"; \
    install -m 0755 "$temporary_root/wasm-opt" /usr/local/bin/wasm-opt; \
    test "$(command -v wasm-opt)" = /usr/local/bin/wasm-opt; \
    wasm-opt --version

RUN rustup component add rustfmt clippy \
    && rustup target add wasm32-unknown-unknown \
    && rustup toolchain install nightly-2026-07-19 --profile minimal --component rust-src \
    && cargo install bpf-linker --version 0.10.4 --locked \
    && cargo install create-tauri-app --locked \
    && cargo install tauri-cli --version "^2.0.0" --locked \
    && cargo install cargo-leptos --locked \
    && cargo install trunk --version "0.21.13" --locked -j 64

RUN freshclam || true

# Install the stable server CLI in a shared path, independent of the legacy
# /root volume. Pin both architectures rather than running an installer at boot.
RUN set -eu; \
    version=1.19.5; \
    case "$(dpkg --print-architecture)" in \
        amd64) architecture=x64-baseline; checksum=17c200fd4b2289954cc01552559f9b6d03ec157b2ddfb5eb54144f491656333d ;; \
        arm64) architecture=arm64; checksum=fae5be262d693b7c5e562856cc473e59e741772936db0c0600ac0d5ed5bd088b ;; \
        *) printf 'unsupported OpenCode architecture\n' >&2; exit 1 ;; \
    esac; \
    temporary_root=$(mktemp -d); \
    trap 'rm -rf -- "$temporary_root"' EXIT; \
    curl --fail --show-error --location --proto '=https' --proto-redir '=https' \
        --retry 3 --connect-timeout 15 --max-time 180 \
        "https://github.com/anomalyco/opencode/releases/download/v${version}/opencode-linux-${architecture}.tar.gz" \
        --output "$temporary_root/opencode.tar.gz"; \
    printf '%s  %s\n' "$checksum" "$temporary_root/opencode.tar.gz" | sha256sum --check --strict -; \
    tar -xzf "$temporary_root/opencode.tar.gz" -C "$temporary_root"; \
    install -m 0755 "$temporary_root/opencode" /usr/local/bin/opencode; \
    test "$(opencode --version)" = "$version"

ENV DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/dbus-session.sock

# Install the Codex CLI with OpenAI's standalone installer. Keep the package
# tree image-owned under /opt so rebuilds replace it; authentication state still
# lives in ~/.codex on the dev-home volume.
RUN set -eu; \
    temporary_root=$(mktemp -d); \
    trap 'rm -rf -- "$temporary_root"' EXIT; \
    curl --fail --show-error --location --proto '=https' --proto-redir '=https' \
        --retry 3 --connect-timeout 15 \
        https://chatgpt.com/codex/install.sh \
        --output "$temporary_root/install.sh"; \
    CODEX_NON_INTERACTIVE=1 \
    CODEX_INSTALL_DIR=/usr/local/bin \
    CODEX_HOME=/opt/codex \
        sh "$temporary_root/install.sh"; \
    test "$(command -v codex)" = /usr/local/bin/codex; \
    CODEX_HOME=/opt/codex codex --version

# Install Claude Code with Anthropic's native installer. Use an image-owned
# prefix so the dev-home volume cannot mask it, then expose the launcher on PATH.
RUN set -eu; \
    install_root=/opt/claude; \
    temporary_root=$(mktemp -d); \
    trap 'rm -rf -- "$temporary_root"' EXIT; \
    rm -rf "$install_root"; \
    mkdir -p "$install_root"; \
    curl --fail --show-error --location --proto '=https' --proto-redir '=https' \
        --retry 3 --connect-timeout 15 \
        https://claude.ai/install.sh \
        --output "$temporary_root/install.sh"; \
    HOME="$install_root" CLAUDE_INSTALL_ALLOW_SUDO=1 \
        bash "$temporary_root/install.sh"; \
    ln -sfn "$install_root/.local/bin/claude" /usr/local/bin/claude; \
    test "$(command -v claude)" = /usr/local/bin/claude; \
    HOME="$install_root" claude --version

ARG USER_UID=1000
ARG USER_GID=1000
RUN groupadd --system openuss \
    && groupadd --gid "$USER_GID" vscode \
    && useradd --uid "$USER_UID" --gid "$USER_GID" --groups openuss \
        --create-home --shell /usr/bin/fish vscode \
    && printf 'vscode ALL=(ALL:ALL) NOPASSWD:ALL\n' > /etc/sudoers.d/vscode \
    && chmod 0440 /etc/sudoers.d/vscode \
    && visudo --check --file /etc/sudoers.d/vscode \
    && chown -R vscode:vscode /usr/local/cargo /usr/local/rustup

# Install the pinned T3 Code CLI and its self-contained runtime. The runtime is
# image-owned under /opt/t3 so a rebuild replaces it; state lives under
# /home/vscode/.t3 in the dev-home volume.
RUN set -eu; \
    version=0.1.6; \
    case "$(dpkg --print-architecture)" in \
        amd64) architecture=x64; checksum=7cf31da90dee41f524dd5b679ebb6d404637ca5d9dc6fd8bc019511d57bb77e6 ;; \
        arm64) architecture=arm64; checksum=b708f059200776f50623a766854841e40eda0bb67614211cf8b6909295ce20da ;; \
        *) printf 'unsupported T3 Code architecture\n' >&2; exit 1 ;; \
    esac; \
    target_dir=/opt/t3; \
    temporary_root=$(mktemp -d); \
    trap 'rm -rf -- "$temporary_root"' EXIT; \
    archive="t3-${version}-linux-${architecture}.tar.gz"; \
    rm -rf "$target_dir"; \
    mkdir -p "$target_dir" /home/vscode/.local/bin; \
    curl --fail --show-error --location --proto '=https' --proto-redir '=https' \
        --retry 3 --connect-timeout 15 --max-time 300 \
        "https://github.com/pingdotgg/t3code/releases/download/v${version}/${archive}" \
        --output "$temporary_root/$archive"; \
    printf '%s  %s\n' "$checksum" "$temporary_root/$archive" | sha256sum --check --strict -; \
    tar -xzf "$temporary_root/$archive" -C "$target_dir" --strip-components=1; \
    printf '%s\n' "$version" > "$target_dir/.install-complete"; \
    chown -R root:root "$target_dir"; \
    chmod -R a+rX "$target_dir"; \
    ln -sfn "$target_dir/t3" /usr/local/bin/t3; \
    ln -sfn "$target_dir/t3" /home/vscode/.local/bin/t3; \
    test "$(HOME=/home/vscode /usr/local/bin/t3 --version)" = "t3 v${version}"; \
    chown -h vscode:vscode /home/vscode/.local/bin/t3; \
    chown vscode:vscode /home/vscode/.local /home/vscode/.local/bin

COPY daemon/packaging/org.openussd.conf /usr/share/dbus-1/system.d/org.openussd.conf
COPY daemon/packaging/org.openussd.policy /usr/share/polkit-1/actions/org.openussd.policy
COPY daemon/packaging/org.openussd.rules /usr/share/polkit-1/rules.d/org.openussd.rules

COPY .devcontainer/start-dbus.sh /usr/local/bin/start-dbus.sh
RUN chmod +x /usr/local/bin/start-dbus.sh

COPY .devcontainer/dbus-ui.sh /usr/local/bin/dbus-ui
RUN chmod +x /usr/local/bin/dbus-ui

COPY .devcontainer/start-devcontainer.sh /usr/local/bin/start-devcontainer.sh
RUN chmod 0755 /usr/local/bin/start-devcontainer.sh

ENV HOME=/home/vscode
ENV PATH=/home/vscode/.local/bin:/home/vscode/.opencode/bin:${PATH}
USER vscode
WORKDIR /workspaces/OpenUSS

ENTRYPOINT ["/usr/local/bin/start-devcontainer.sh"]
