# Build KinD and Docker CLI from source with a patched Go toolchain.
# The Alpine packages/binaries have historically lagged on Go patch releases, so
# we compile these tools ourselves to pick up upstream fixes without local vendoring hacks.
ARG GOLANG_IMAGE=golang:1.25.10-alpine@sha256:8d22e29d960bc50cd025d93d5b7c7d220b1ee9aa7a239b3c8f55a57e987e8d45
ARG NODE_IMAGE=node:24-alpine3.23@sha256:7fddd9ddeae8196abf4a3ef2de34e11f7b1a722119f91f28ddf1e99dcafdf114
ARG KIND_VERSION=v0.31.0
ARG KIND_COMMIT=a323333ff9efd8099f95a8a6b5c86c75a210d00f
ARG DOCKER_CLI_VERSION=v29.3.0
ARG DOCKER_CLI_COMMIT=5927d80c76b3ce5cf782be818922966e8a0d87a3

FROM ${GOLANG_IMAGE} AS go-builder
ARG TARGETARCH
ARG KIND_VERSION
ARG KIND_COMMIT
ARG DOCKER_CLI_VERSION
ARG DOCKER_CLI_COMMIT
RUN if [ "$TARGETARCH" != "amd64" ] && [ "$TARGETARCH" != "arm64" ]; then \
        echo "ERROR: Unsupported architecture: $TARGETARCH. KinD is only available for amd64 and arm64."; \
        exit 1; \
    fi
RUN apk add --no-cache git
RUN git clone --depth 1 --branch "${KIND_VERSION}" https://github.com/kubernetes-sigs/kind.git /kind && \
    test "$(git -C /kind rev-parse HEAD)" = "${KIND_COMMIT}" && \
    cd /kind && \
    go mod edit -go=1.25.10 && \
    # golang.org/x/net <0.53.0: multiple HIGH CVEs (Scout-flagged at 0.51.0); fixed in >= 0.53.0
    go get golang.org/x/net@v0.53.0 && \
    CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build -o /kind-binary .
RUN git clone --depth 1 --branch "${DOCKER_CLI_VERSION}" https://github.com/docker/cli.git /docker-cli && \
    test "$(git -C /docker-cli rev-parse HEAD)" = "${DOCKER_CLI_COMMIT}" && \
    cd /docker-cli && \
    cp vendor.mod go.mod && cp vendor.sum go.sum && \
    go mod edit -go=1.25.10 && \
    # CVE-2026-33186: grpc Improper Authorization fixed in >= 1.79.3
    go get google.golang.org/grpc@v1.79.3 && \
    # CVE-2026-39883: OTel SDK untrusted search path fixed in >= 1.43.0
    go get go.opentelemetry.io/otel/sdk@v1.43.0 && \
    # CVE-2026-34986: go-jose uncaught exception fixed in >= 4.1.4
    go get github.com/go-jose/go-jose/v4@v4.1.4 && \
    # x/sys/x/term must be pinned for `go mod vendor` to find windows/registry and plan9 sub-pkgs.
    go get golang.org/x/sys@v0.42.0 && \
    go get golang.org/x/term@v0.42.0 && \
    # golang.org/x/net <0.53.0: multiple HIGH CVEs (Scout-flagged at 0.51.0); fixed in >= 0.53.0.
    # Must be the LAST `go get` before `go mod vendor` — earlier `go get`s for grpc/otel/x/sys
    # transitively pull x/net@v0.52.0 and would otherwise override our explicit requirement.
    go get golang.org/x/net@v0.53.0 && \
    go mod vendor && \
    CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build -mod=vendor \
    -ldflags "-X github.com/docker/cli/cli/version.Version=${DOCKER_CLI_VERSION#v}" \
    -o /docker-binary ./cmd/docker

FROM ${NODE_IMAGE} AS base

# Enable pnpm
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

RUN corepack prepare pnpm@10.33.0 --activate

# CVE-2026-33671: pnpm 10.33.0 bundles picomatch 4.0.3 inside its own node_modules.
# Corepack caches it at /root/.cache/node/corepack/, and it is inherited by every
# downstream stage. Replace it with the 4.0.4 package tree so Scout does not flag
# the cached copy in the final image.
RUN set -eux; \
    cd /tmp; \
    wget -q -O picomatch-4.0.4.tgz https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz; \
    echo "515b5ab666558ed9a117483a310892aede54a68dd78f2d8db6604513e578571c  picomatch-4.0.4.tgz" | sha256sum -c -; \
    target=/root/.cache/node/corepack/v1/pnpm/10.33.0/dist/node_modules/picomatch; \
    rm -rf "$target"/*; \
    tar -xzf picomatch-4.0.4.tgz --strip-components=1 -C "$target"; \
    rm -f picomatch-4.0.4.tgz; \
    grep -q '"version": "4.0.4"' "$target/package.json"

# Dependencies stage
FROM base AS deps
WORKDIR /app

# Copy package files for all workspaces
# .npmrc must be included so minimum-release-age / ignore-scripts are enforced
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json .npmrc ./
COPY backend/package.json backend/
COPY frontend/package.json frontend/
COPY shared/package.json shared/
COPY patches/ patches/

# Install all dependencies
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

# CVE-2026-33671: Next.js bundles picomatch 4.0.3 at dist/compiled/picomatch/.
# pnpm overrides cannot reach this vendored copy; upstream has not re-vendored
# yet (tracked at vercel/next.js#92950). Replace it with the 4.0.4 package tree.
# The path resolves through the symlink frontend/node_modules/next → .pnpm/next@.../node_modules/next,
# so overwriting once updates every reference.
RUN set -eux; \
    cd /tmp; \
    wget -q -O picomatch-4.0.4.tgz https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz; \
    echo "515b5ab666558ed9a117483a310892aede54a68dd78f2d8db6604513e578571c  picomatch-4.0.4.tgz" | sha256sum -c -; \
    target=/app/frontend/node_modules/next/dist/compiled/picomatch; \
    rm -rf "$target"/*; \
    tar -xzf picomatch-4.0.4.tgz --strip-components=1 -C "$target"; \
    rm -f picomatch-4.0.4.tgz; \
    grep -q '"version": "4.0.4"' "$target/package.json"

# <----- Builder stage ----->
FROM base AS builder
WORKDIR /app

# Version arg for Sentry release tracking
ARG VERSION=dev

# Copy dependencies from deps stage
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/backend/node_modules ./backend/node_modules
COPY --from=deps /app/frontend/node_modules ./frontend/node_modules
COPY --from=deps /app/shared/node_modules ./shared/node_modules

# Copy source files
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY backend ./backend
COPY frontend ./frontend
COPY shared ./shared

# Build all workspace
ENV NEXT_TELEMETRY_DISABLED=1

# VERSION is exported as env var for child processes (used by Sentry source map upload)
ENV VERSION=${VERSION}

# Use Docker secrets to securely pass various sensitive environment variables during build
# These environment variables are NOT persisted in the final image
#
# TURBO_TEAM and TURBO_TOKEN are used for Turbo remote caching
# https://turborepo.com/docs/guides/tools/docker#example
#
# SENTRY_AUTH_TOKEN is used by backend/frontend builds to upload source maps
# SENTRY_URL points to the EU region where the archestra org is hosted
#
# https://docs.docker.com/build/building/secrets/#using-build-secrets
# https://docs.docker.com/build/building/secrets/#target
RUN --mount=type=secret,id=turbo_team,env=TURBO_TEAM \
    --mount=type=secret,id=turbo_token,env=TURBO_TOKEN \
    --mount=type=secret,id=sentry_auth_token,env=SENTRY_AUTH_TOKEN \
    SENTRY_URL=https://de.sentry.io/ \
    pnpm build

# <----- Final unified stage ----->
FROM base AS unified
WORKDIR /app

ARG VERSION=dev

ENV NODE_ENV=production
# disable telemetry for next.js
ENV NEXT_TELEMETRY_DISABLED=1

ENV ARCHESTRA_VERSION=${VERSION}
ENV ARCHESTRA_INTERNAL_API_BASE_URL="http://localhost:9000"
ENV ARCHESTRA_API_BASE_URL=""
ENV ARCHESTRA_ANALYTICS="enabled"
ENV ARCHESTRA_ENTERPRISE_LICENSE_ACTIVATED="false"
ENV ARCHESTRA_ENTERPRISE_LICENSE_FULL_WHITE_LABELING="false"
ENV ARCHESTRA_SENTRY_FRONTEND_DSN=""
ENV ARCHESTRA_SENTRY_ENVIRONMENT=""

# Cloud database CA bundle for SSL certificate validation
# This allows sslmode=require to work with AWS RDS and Google Cloud SQL
ENV NODE_EXTRA_CA_CERTS="/etc/ssl/certs/cloud-database-ca-bundle.pem"

# Vendor cloud database CA bundles into the repository so image builds do not
# depend on live network fetches for trust roots.
COPY docker/certs/aws-rds-global-bundle.pem /tmp/aws-rds-ca.pem
COPY docker/certs/gcloud-sql-global.pem /tmp/gcloud-sql-ca.pem

RUN apk --no-cache upgrade && \
    # Install PostgreSQL 17, pgvector, and supervisord
    apk add --no-cache postgresql17 postgresql17-contrib postgresql-pgvector su-exec && \
    # Combine all CA bundles
    cat /tmp/aws-rds-ca.pem /tmp/gcloud-sql-ca.pem > /etc/ssl/certs/cloud-database-ca-bundle.pem && \
    rm -f /tmp/aws-rds-ca.pem /tmp/gcloud-sql-ca.pem && \
    # Remove NPM-related files and directories (as we do not use npm and it just brings extra dependencies/vulnerabilities)
    # See https://github.com/grafana/grafana-image-renderer/pull/625
    rm -rf /usr/local/lib/node_modules/npm && \
    rm -rf /usr/local/bin/npm && \
    rm -rf /usr/local/bin/npx && \
    rm -rf /root/.npm && \
    rm -rf /root/.node-gyp && \
    mkdir -p /var/log/supervisor && \
    # Clean up
    rm -rf /tmp/*

# Install KinD (Kubernetes in Docker) and docker-cli for embedded K8s cluster support
# Both binaries are built from source in go-builder with Go 1.25.10 to fix CVE-2025-68121
# and the Go stdlib HIGH CVEs fixed in 1.25.10 (CVE-2026-42499/39836/39820/33814/33811).
COPY --from=go-builder /docker-binary /usr/local/bin/docker
COPY --from=go-builder /kind-binary /usr/local/bin/kind
RUN chmod +x /usr/local/bin/kind /usr/local/bin/docker
# TODO: Once KinD releases a version compiled with Go >= 1.25.10, remove the kind-builder stage
# at the top of this file and restore the pre-built binary download below for faster builds.
# Track releases at: https://github.com/kubernetes-sigs/kind/releases
# RUN ARCH=$(uname -m) && \
#     if [ "$ARCH" = "x86_64" ]; then \
#         KIND_URL="https://kind.sigs.k8s.io/dl/v0.31.0/kind-linux-amd64"; \
#         KIND_SHA256="eb244cbafcc157dff60cf68693c14c9a75c4e6e6fedaf9cd71c58117cb93e3fa"; \
#     elif [ "$ARCH" = "aarch64" ]; then \
#         KIND_URL="https://kind.sigs.k8s.io/dl/v0.31.0/kind-linux-arm64"; \
#         KIND_SHA256="8e1014e87c34901cc422a1445866835d1e666f2a61301c27e722bdeab5a1f7e4"; \
#     else \
#         echo "ERROR: Unsupported architecture: $ARCH. KinD is only available for x86_64 and aarch64."; \
#         exit 1; \
#     fi && \
#     wget -O /usr/local/bin/kind "${KIND_URL}" && \
#     echo "${KIND_SHA256}  /usr/local/bin/kind" | sha256sum -c - && \
#     chmod +x /usr/local/bin/kind

RUN apk add --no-cache supervisor && \
    # CVE-2026-24049: wheel 0.45.1 path traversal. Vendored inside py3-setuptools
    # (pulled in by supervisor); pip can't upgrade the vendored copy, so delete it.
    rm -rf /usr/lib/python*/site-packages/setuptools/_vendor/wheel \
           /usr/lib/python*/site-packages/setuptools/_vendor/wheel-*.dist-info \
           /usr/lib/python*/ensurepip

# Create postgres directories (user already exists from postgresql package)
RUN mkdir -p /var/lib/postgresql/data /run/postgresql && \
    chown -R postgres:postgres /var/lib/postgresql /run/postgresql

# Mark PostgreSQL data directory as a volume for data persistence
VOLUME /var/lib/postgresql/data /app/data

# Copy package files
# .npmrc must be included so minimum-release-age / ignore-scripts are enforced
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY backend/package.json backend/
COPY frontend/package.json frontend/
COPY patches/ patches/
COPY docker/scripts/docker-banner.sh /app/docker-banner.sh
COPY docker/scripts/docker-entrypoint.sh /docker-entrypoint.sh
COPY docker/supervisord/supervisord.conf /etc/supervisord.conf
COPY docker/supervisord/postgres.conf /etc/supervisord.postgres.conf

# Install production dependencies for both workspaces
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile --prod --filter=@backend --filter=@frontend

# CVE-2026-33671: replace Next's bundled picomatch 4.0.3 with 4.0.4 (same as deps stage).
# Production install refetches next so the patched copy from the builder is not inherited.
RUN set -eux; \
    cd /tmp; \
    wget -q -O picomatch-4.0.4.tgz https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz; \
    echo "515b5ab666558ed9a117483a310892aede54a68dd78f2d8db6604513e578571c  picomatch-4.0.4.tgz" | sha256sum -c -; \
    target=/app/frontend/node_modules/next/dist/compiled/picomatch; \
    rm -rf "$target"/*; \
    tar -xzf picomatch-4.0.4.tgz --strip-components=1 -C "$target"; \
    rm -f picomatch-4.0.4.tgz; \
    grep -q '"version": "4.0.4"' "$target/package.json"

# Copy built backend
COPY --from=builder /app/backend/dist ./backend/dist
COPY --from=builder /app/backend/scripts ./backend/scripts
COPY --from=builder /app/backend/drizzle.config.ts ./backend/
COPY --from=builder /app/backend/src/database/migrations ./backend/src/database/migrations
RUN chmod +x /app/backend/scripts/start-production.sh

# Copy built frontend
COPY --from=builder /app/frontend/public ./frontend/public
COPY --from=builder /app/frontend/.next/standalone ./

# Copy previous version's static assets first (from CI build context)
# Content-hashed filenames ensure no conflicts between versions
COPY prev-static-assets/ ./frontend/.next/static/

# Copy current build's assets on top
COPY --from=builder /app/frontend/.next/static ./frontend/.next/static

# Keep a clean copy of ONLY this build's assets (not accumulated)
# CI will extract from this path for the NEXT deployment
COPY --from=builder /app/frontend/.next/static /static-assets-source/

RUN chmod +x /docker-entrypoint.sh
RUN chmod +x /app/docker-banner.sh

# Expose ports
EXPOSE 5432 9000 9050 3000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1

ENTRYPOINT ["/docker-entrypoint.sh"]
