# Slim CPU image for the `quber table --review` cloud job. The set-of-mark path
# is CPU-only (poppler + Camelot + Anthropic API), so no GPU base is needed --
# unlike `runpod/Dockerfile`, which installs the `gpu` extra for the docling
# parse path. Build context is the repo root:
#   docker build -f deploy/Dockerfile -t quber .
FROM python:3.13-slim AS base

# uv for dependency resolution (copied from the official distroless uv image).
COPY --from=ghcr.io/astral-sh/uv:0.5.11 /uv /uvx /bin/

ENV UV_LINK_MODE=copy \
    UV_COMPILE_BYTECODE=1 \
    PYTHONUNBUFFERED=1 \
    PATH="/app/.venv/bin:$PATH"

# Runtime system deps for the set-of-mark path:
#   ghostscript  -> Camelot lattice/stream parsing
#   poppler-utils -> pdf2image page rasterization
#   libgl1, libglib2.0-0 -> OpenCV (opencv-python-headless) runtime
RUN apt-get update && apt-get install -y --no-install-recommends \
    ghostscript \
    poppler-utils \
    libgl1 \
    libglib2.0-0 \
    && rm -rf /var/lib/apt/lists/*

# Fonts for consistent glyph rendering. Ghostscript (Camelot's grid) and
# poppler (the page image the vetting LLM reads) both substitute fonts when a
# PDF's fonts are not embedded. Without fonts the slim base renders differently
# from the developer host, which shifts the Camelot grid and the rasterized
# table image, making the grounding guard accept or reject the same table
# differently. This mirrors the developer host's font set exhaustively so
# substitution resolves to the same glyphs everywhere.
#
# The first install holds the rendering essentials and fails the build if any
# is missing: fontconfig plus the URW base-35 (the standard PDF/PostScript
# faces Ghostscript falls back to), Liberation (Arial/Times/Courier metric
# matches) and the Noto/DejaVu Latin cores. The loop then adds the rest of the
# host set; a name that does not exist on the Debian base is logged and skipped
# rather than breaking the build (the host is Ubuntu, the base is Debian).
RUN apt-get update && apt-get install -y --no-install-recommends \
    fontconfig \
    fonts-urw-base35 \
    fonts-liberation \
    fonts-liberation2 \
    fonts-dejavu-core \
    fonts-noto-core \
 && for pkg in \
    fonts-beng fonts-beng-extra fonts-cabin fonts-cantarell fonts-dejavu-extra \
    fonts-deva fonts-deva-extra fonts-droid-fallback fonts-font-awesome \
    fonts-freefont-ttf fonts-gargi fonts-gubbi fonts-gujr fonts-gujr-extra \
    fonts-guru fonts-guru-extra fonts-indic fonts-kacst fonts-kacst-one \
    fonts-kalapi fonts-khmeros-core fonts-knda fonts-lao fonts-lato \
    fonts-lklug-sinhala fonts-lohit-beng-assamese fonts-lohit-beng-bengali \
    fonts-lohit-deva fonts-lohit-gujr fonts-lohit-guru fonts-lohit-knda \
    fonts-lohit-mlym fonts-lohit-orya fonts-lohit-taml fonts-lohit-taml-classical \
    fonts-lohit-telu fonts-mathjax fonts-mlym fonts-nakula fonts-navilu \
    fonts-noto-cjk fonts-noto-color-emoji fonts-noto-mono fonts-opendyslexic \
    fonts-open-sans fonts-opensymbol fonts-orya fonts-orya-extra fonts-pagul \
    fonts-quicksand fonts-sahadeva fonts-samyak-deva fonts-samyak-gujr \
    fonts-samyak-mlym fonts-samyak-taml fonts-sarai fonts-sil-abyssinica \
    fonts-sil-padauk fonts-smc fonts-smc-anjalioldlipi fonts-smc-chilanka \
    fonts-smc-dyuthi fonts-smc-gayathri fonts-smc-karumbi fonts-smc-keraleeyam \
    fonts-smc-manjari fonts-smc-meera fonts-smc-rachana fonts-smc-raghumalayalamsans \
    fonts-smc-suruma fonts-smc-uroob fonts-symbola fonts-taml fonts-telu \
    fonts-telu-extra fonts-teluguvijayam fonts-thai-tlwg fonts-tibetan-machine \
    fonts-tiresias fonts-tlwg-garuda fonts-tlwg-garuda-ttf fonts-tlwg-kinnari \
    fonts-tlwg-kinnari-ttf fonts-tlwg-laksaman fonts-tlwg-laksaman-ttf \
    fonts-tlwg-loma fonts-tlwg-loma-ttf fonts-tlwg-mono fonts-tlwg-mono-ttf \
    fonts-tlwg-norasi fonts-tlwg-norasi-ttf fonts-tlwg-purisa fonts-tlwg-purisa-ttf \
    fonts-tlwg-sawasdee fonts-tlwg-sawasdee-ttf fonts-tlwg-typewriter \
    fonts-tlwg-typewriter-ttf fonts-tlwg-typist fonts-tlwg-typist-ttf \
    fonts-tlwg-typo fonts-tlwg-typo-ttf fonts-tlwg-umpush fonts-tlwg-umpush-ttf \
    fonts-tlwg-waree fonts-tlwg-waree-ttf fonts-ubuntu fonts-yrsa-rasa \
    ; do \
      apt-get install -y --no-install-recommends "$pkg" \
        || echo "font package unavailable on Debian base, skipped: $pkg"; \
    done \
 && fc-cache -f \
 && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install the CORE dependency set only (no `--extra gpu`): the set-of-mark
# table path is CPU-only, so docling/onnxruntime-gpu/nvidia-*/easyocr/
# sentence-transformers are excluded. A single `uv sync` avoids duplicating the
# venv across layers.
COPY pyproject.toml uv.lock README.md ./
COPY src/ ./src/
RUN uv sync --frozen --no-dev

# Drop privileges.
RUN useradd --create-home --uid 10001 quber && chown -R quber:quber /app
USER quber

# The Lambda trigger overrides the command per document, e.g.
#   table s3://qubera-docs/inbound/<co>/<sub>/f.pdf -o s3://qubera-extracts/<co>/<sub>/f/ --review --llm-backend api
ENTRYPOINT ["quber"]
CMD ["--help"]
