# ── Stage 1: Builder ─────────────────────────────────────────────
FROM apache/airflow:3.0.6 AS builder

USER root

# Install build-only dependencies (dropped in final image)
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Install uv
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/root/.local/bin:$PATH"

# Copy project manifests for dependency resolution
COPY --chown=airflow:root pyproject.toml uv.lock /opt/airflow/
COPY --chown=airflow:root textiq_hmac-*.whl /opt/airflow/

# Install project dependencies using uv sync with increased timeout
WORKDIR /opt/airflow
ENV UV_HTTP_TIMEOUT=300
RUN sed -i '/\[tool\.uv\.sources\]/,/^$/d' pyproject.toml && \
    uv pip install --python /home/airflow/.local/bin/python /opt/airflow/textiq_hmac-*.whl && \
    uv sync --frozen --no-install-project && \
    chown -R airflow:root /opt/airflow/.venv

# ── Stage 2: Runtime ─────────────────────────────────────────────
FROM apache/airflow:3.0.6

USER root

# Runtime-only system dependencies (no build-essential)
# libgl1 is required by OpenCV (cv2) for PDF table extraction
# libreoffice is required for .xlsx conversion
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libgl1 \
        libglib2.0-0 \
        libreoffice \
    && apt-get upgrade -y --no-install-recommends \
    && apt-get remove --purge -y \
        python3.11 \
        python3.11-minimal \
        libpython3.11 \
        libpython3.11-minimal \
        libpython3.11-stdlib \
        ldap-utils \
    && apt-get autoremove -y \
    && rm -rf /var/lib/apt/lists/*

# Security: upgrade docker-ce-cli to fix 15 gobinary CVEs (HIGH/CRITICAL) in
# the version pinned by the base image. Re-adds Docker's official apt repo so
# apt-get can pull the latest release rather than the base-image-era pin.
RUN apt-get update \
    && apt-get install -y --no-install-recommends gnupg curl \
    && install -m 0755 -d /etc/apt/keyrings \
    && curl -fsSL https://download.docker.com/linux/debian/gpg \
       | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
    && chmod a+r /etc/apt/keyrings/docker.gpg \
    && . /etc/os-release \
    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
       https://download.docker.com/linux/debian $VERSION_CODENAME stable" \
       > /etc/apt/sources.list.d/docker.list \
    && apt-get update \
    && apt-get install -y --only-upgrade docker-ce-cli \
    && rm -rf /var/lib/apt/lists/*

# Copy pre-built .venv from builder (single layer, correct ownership)
COPY --from=builder --chown=airflow:root /opt/airflow/.venv /opt/airflow/.venv


# Install textiq_hmac into Airflow's own Python so plugins can import it
COPY --chown=airflow:root textiq_hmac-*.whl /tmp/
USER airflow
RUN pip install --no-deps /tmp/textiq_hmac-*.whl && rm -f /tmp/textiq_hmac-*.whl
# pymilvus is needed by the tags/domain_terms plugin endpoints (api-server context)
# The api-server runs outside .venv, so install into Airflow's own Python too
RUN pip install pymilvus==2.6.11
# prometheus-client is needed by the plugin metrics endpoint (api-server context)
RUN pip install prometheus-client
# pybreaker is needed by airflow/plugins/api/{s3,milvus,upload}.py for the
# circuit-breaker layer (TEXTIQ-394). The api-server runs outside .venv, so it
# needs pybreaker in Airflow's own Python too.
RUN pip install pybreaker==1.4.1
# Security: upgrade pip packages with CRITICAL/HIGH CVEs from base image
# CVE-2026-27962, CVE-2025-59420 (Authlib <1.6.9)
# CVE-2026-35030, CVE-2026-35029 (litellm <1.83.0)
RUN pip install "authlib>=1.6.9" "litellm>=1.83.0"

# Security: remove unused Airflow providers bundled in the base image.
# This project only imports `airflow.providers.standard`. Removing the unused
# providers eliminates their vulnerable transitive deps entirely, including the
# two CVEs with no upstream fix:
#   - ray CVE-2023-48022 (CRITICAL) + google-cloud-aiplatform  <- providers-google
#   - lxml CVE-2026-41066 (via redshift-connector)             <- providers-amazon
#   - GitPython GHSA-mv93-w799-cj2w + CVE-2026-4421x           <- providers-git
#   - aiomysql CVE-2025-62611                                  <- providers-mysql
#   - azure-core / microsoft-kiota-http                        <- providers-microsoft-azure
#   - apache-airflow-providers-http CVE-2025-69219             <- providers-http (unused)
#   - pyOpenSSL CVE-2026-27459                                 <- providers-google/snowflake
RUN pip uninstall -y \
        apache-airflow-providers-git \
        apache-airflow-providers-google \
        apache-airflow-providers-amazon \
        apache-airflow-providers-mysql \
        apache-airflow-providers-microsoft-azure \
        apache-airflow-providers-snowflake \
        apache-airflow-providers-http

# Security: remove the orphaned transitive dependencies left behind by the
# provider uninstall above. `pip uninstall <provider>` does NOT cascade-remove
# transitive deps, so the vulnerable libraries (ray CRITICAL, lxml, GitPython,
# aiomysql, redshift-connector, azure-*, microsoft-kiota-*, google-cloud-*,
# snowflake-*, pyOpenSSL) stay installed with no parent. Nothing in this project
# imports them (only `airflow.providers.standard` is used), so removing them is
# pure attack-surface reduction. Verified: api-server (create_app), celery
# executor, standard provider, and all plugin deps still import and boot.
RUN pip uninstall -y \
        ray GitPython aiomysql google-cloud-aiplatform redshift-connector \
        azure-core azure-cosmos azure-identity azure-keyvault-secrets \
        azure-kusto-data azure-kusto-ingest azure-mgmt-core azure-servicebus \
        azure-storage-blob azure-storage-file-datalake azure-storage-file-share \
        azure-synapse-spark azure-synapse-artifacts msrest adlfs \
        microsoft-kiota-abstractions microsoft-kiota-authentication-azure \
        microsoft-kiota-http microsoft-kiota-serialization-json \
        microsoft-kiota-serialization-text msgraph-core msgraph-sdk \
        snowflake-connector-python snowflake-sqlalchemy pyOpenSSL \
        azure-mgmt-containerinstance azure-mgmt-containerregistry \
        azure-mgmt-cosmosdb azure-mgmt-datafactory azure-mgmt-resource \
        azure-mgmt-storage azure-mgmt-datalake-store azure-mgmt-datalake-nspkg \
        azure-mgmt-nspkg azure-nspkg azure-batch azure-datalake-store \
        gcloud-aio-auth gcloud-aio-storage gcloud-aio-bigquery \
        google-ads google-analytics-admin google-cloud-alloydb \
        google-cloud-appengine-logging google-cloud-audit-log google-cloud-automl \
        google-cloud-batch google-cloud-bigquery-datatransfer \
        google-cloud-bigquery-storage google-cloud-bigtable google-cloud-build \
        google-cloud-compute google-cloud-container google-cloud-datacatalog \
        google-cloud-dataflow-client google-cloud-dataform google-cloud-dataplex \
        google-cloud-dataproc google-cloud-dataproc-metastore google-cloud-dlp \
        google-cloud-kms google-cloud-language google-cloud-logging \
        google-cloud-managedkafka google-cloud-memcache google-cloud-monitoring \
        google-cloud-orchestration-airflow google-cloud-os-login \
        google-cloud-pubsub google-cloud-redis google-cloud-resource-manager \
        google-cloud-run google-cloud-secret-manager google-cloud-spanner \
        google-cloud-speech google-cloud-storage-transfer google-cloud-tasks \
        google-cloud-texttospeech google-cloud-translate \
        google-cloud-videointelligence google-cloud-vision google-cloud-workflows \
        msal msal-extensions msrestazure sqlalchemy-spanner

# Security: upgrade Airflow-core / orphan transitive deps with CRITICAL/HIGH CVEs.
# These live in Airflow's own Python and are safe to bump (verified the api-server
# health endpoint + scheduler still work). Not upgraded:
#   - PyJWT: 2.12+ enforces RFC-7519 `iss` must be a string, which Airflow 3.0.6's
#     internal auth tokens violate -> api-server 500s on every request.
#     CVE-2026-32597 (HIGH, unknown `crit` header) accepted.
#   - starlette: fastapi pins <0.48; bumping to the CVE fix (0.49.1) breaks the
#     API server. CVE-2025-62727 (HIGH, Range-header DoS) accepted.
#   - Werkzeug: Flask-AppBuilder pins <3; CVE-2024-34069 (HIGH) accepted.
RUN pip install --upgrade \
        "Mako>=1.3.12" \
        "urllib3>=2.7.0" \
        "pyasn1>=0.6.3" \
        "aiohttp>=3.13.3" \
        "jaraco.context>=6.1.0" \
        "python-multipart>=0.0.27" \
        "wheel>=0.46.2" \
        "tornado>=6.5.5"
USER root

# Copy project files
COPY --chown=airflow:root pyproject.toml /opt/airflow/

# Copy Alembic configuration and migrations for database schema
COPY --chown=airflow:root alembic.ini /opt/airflow/
COPY --chown=airflow:root src/db/migrations /opt/airflow/src/db/migrations

# Copy source code modules used by Airflow tasks
COPY --chown=airflow:root src /opt/airflow/src

# Copy config files (taxonomy tags, namespaces, etc.)
COPY --chown=airflow:root config /opt/airflow/config

# Copy Airflow DAGs, plugins, and config
COPY --chown=airflow:root airflow/dags /opt/airflow/dags
COPY --chown=airflow:root airflow/plugins /opt/airflow/plugins
COPY --chown=airflow:root airflow/config /opt/airflow/config

# Copy entrypoint script
COPY --chown=airflow:root docker/airflow-entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Ensure logs directory exists with correct ownership for all Airflow components
RUN mkdir -p /opt/airflow/logs && chown -R airflow:root /opt/airflow/logs

# Set PATH to use the virtual environment Python first
ENV PATH="/opt/airflow/.venv/bin:$PATH"
ENV VIRTUAL_ENV="/opt/airflow/.venv"
ENV PYTHONPATH="/opt/airflow/plugins:/opt/airflow/src:/opt/airflow"

USER airflow
WORKDIR /opt/airflow

ENTRYPOINT ["/entrypoint.sh"]
