vole-document 0.1.0-alpha.9

Byte-exact procedural document storage: deterministic reconstruction state, typed residuals, and entropy-coded channels that materialize the exact original document bytes.
Documentation
# syntax=docker/dockerfile:1
#
# Pinned, reproducible toolchains for VOLE-Document. Every cargo/rustc/rustfmt/
# clippy/test/bench/fuzz and every PDF oracle runs inside one of these stages.
# Base images are pinned by digest. Source code is NOT baked into these images;
# it is bind-mounted by compose.yaml so a single image serves every check and
# the toolchain identity stays stable across evidence receipts.
#
# Digest provenance (recorded for receipts):
#   rust:1.99.0-slim-bookworm  -> rustc 1.99.0 (b940084d7 2026-09-28), cargo 1.99.0
#   rust:1.89-slim-bookworm    -> rustc 1.89.0 (29483883e 2025-08-04)
#   debian:bookworm-slim       -> oracle tooling base (Phase 3+) and, from
#                                 Phase 7.0b, the generator-family `producers` base
#                                 (same digest as `tools`)
#   rustlang/rust:nightly-bookworm-slim-2026-10-04
#                              -> rustc 1.101.0-nightly (db8f076d2 2026-10-03),
#                                 cargo 1.101.0-nightly (f3865b2a4 2026-09-29),
#                                 toolchain nightly-2026-10-04 (Phase 7 fuzz).

ARG BASE_STABLE=rust:1.99.0-slim-bookworm@sha256:452176c0cefca88c0b3184ce85a4eb03e3d4fa05d2afb5366abcba853221019e
ARG BASE_MSRV=rust:1.89-slim-bookworm@sha256:d7fc7de78bb8c1469933aeecbf801314d30d7d6e9f0578bba4cfa285bfa37fe6
ARG BASE_TOOLS=debian:bookworm-slim@sha256:3783cc01769c7b2b1b83a5c5ad96c815348e28ed7da68e2e3687004faa906251
ARG BASE_FUZZ=rustlang/rust:nightly-bookworm-slim-2026-10-04@sha256:58f725c9459a637c19ddf24542d2aee7d93704684c9780b168e81504327ad297

# ---------------------------------------------------------------------------
# Primary sealed toolchain (Rust 1.99.0). The reference development gate.
# ---------------------------------------------------------------------------
FROM ${BASE_STABLE} AS dev
ENV CARGO_TERM_COLOR=never \
    CARGO_INCREMENTAL=0 \
    RUST_BACKTRACE=1
RUN apt-get update \
 && apt-get install -y --no-install-recommends git ca-certificates \
 && rm -rf /var/lib/apt/lists/* \
 && git config --system --add safe.directory /work \
 && rustup component add rustfmt clippy
WORKDIR /work

# ---------------------------------------------------------------------------
# MSRV gate (Rust 1.89.0, the floor dictated by preflate-rs 0.7.6).
# RUSTUP_TOOLCHAIN overrides rust-toolchain.toml so the 1.99 request is ignored.
# ---------------------------------------------------------------------------
FROM ${BASE_MSRV} AS msrv
ENV CARGO_TERM_COLOR=never \
    CARGO_INCREMENTAL=0 \
    RUST_BACKTRACE=1 \
    RUSTUP_TOOLCHAIN=1.89.0
RUN apt-get update \
 && apt-get install -y --no-install-recommends git ca-certificates \
 && rm -rf /var/lib/apt/lists/* \
 && git config --system --add safe.directory /work \
 && rustup component add rustfmt clippy
WORKDIR /work

# ---------------------------------------------------------------------------
# Dependency-policy gate: cargo-audit + cargo-deny, built inside the pinned
# toolchain so they match the compiler and run in Docker (never on the host).
# ---------------------------------------------------------------------------
FROM ${BASE_STABLE} AS policy
ENV CARGO_TERM_COLOR=never \
    CARGO_INCREMENTAL=0
RUN apt-get update \
 && apt-get install -y --no-install-recommends git ca-certificates pkg-config libssl-dev \
 && rm -rf /var/lib/apt/lists/* \
 && git config --system --add safe.directory /work
RUN cargo install cargo-audit cargo-deny --locked
WORKDIR /work

# ---------------------------------------------------------------------------
# Coverage-guided fuzzing (Phase 7). A pinned *dated* nightly (never a floating
# `nightly`) plus `cargo-fuzz`, so libFuzzer runs are reproducible. RUSTUP_TOOLCHAIN
# overrides rust-toolchain.toml (which requests stable 1.99.0) so the fuzz crate
# builds under the nightly that cargo-fuzz/libfuzzer require.
# ---------------------------------------------------------------------------
FROM ${BASE_FUZZ} AS fuzz
ENV CARGO_TERM_COLOR=never \
    CARGO_INCREMENTAL=0 \
    RUST_BACKTRACE=1 \
    RUSTUP_TOOLCHAIN=nightly-2026-10-04
RUN apt-get update \
 && apt-get install -y --no-install-recommends git ca-certificates build-essential \
 && rm -rf /var/lib/apt/lists/* \
 && git config --system --add safe.directory /work \
 && cargo install cargo-fuzz --locked --version 0.13.2
WORKDIR /work

# ---------------------------------------------------------------------------
# PDF / semantic oracle court (Phase 3+). Independent validators, never the
# representation authority: qpdf, Poppler, MuPDF, Ghostscript.
# ---------------------------------------------------------------------------
FROM ${BASE_TOOLS} AS tools
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
      qpdf \
      poppler-utils \
      mupdf-tools \
      ghostscript \
      coreutils \
 && rm -rf /var/lib/apt/lists/*
WORKDIR /work

# ---------------------------------------------------------------------------
# Generator-family PDF corpus (Phase 7.0b). Deliberately a SEPARATE stage so the
# fast `tools` semantic gate stays small; only the opt-in `producers` service
# builds it. Unlike qpdf/Ghostscript (transformers), these are real *authoring*
# generators with distinct DEFLATE behaviour:
#   * ReportLab   (python3-reportlab)          — Python PDF canvas; pageCompression
#   * Cairo       (python3-cairo + python3-gi) — vector PDF surface (pycairo)
#   * LibreOffice (libreoffice-writer-nogui)   — office-suite headless export
#   * pdfTeX      (texlive-latex-base + texlive-fonts-recommended)
# Plus qpdf (--deterministic-id post-normalization) and git/ca-certificates.
# Size/build tradeoff (measured on BASE_TOOLS): ~38 s cold apt install, the
# image grows to ~740 MB on disk (dev is ~1.02 GB; tools ~264 MB). Kept because
# LibreOffice and pdfTeX are precisely the *authoring-application* families the
# Phase-7.0b question needs, and because this stage never affects any other gate.
# ---------------------------------------------------------------------------
FROM ${BASE_TOOLS} AS producers
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
      python3 \
      python3-reportlab \
      python3-cairo \
      python3-gi \
      libreoffice-writer-nogui \
      texlive-latex-base \
      texlive-fonts-recommended \
      qpdf \
      git \
      ca-certificates \
      coreutils \
 && rm -rf /var/lib/apt/lists/* \
 && git config --system --add safe.directory /work
WORKDIR /work

# ---------------------------------------------------------------------------
# Generic-compressor baseline ladder (Phase 7.0c) and the Phase-7.3
# partial-materialization query court. Derives from the pinned `dev` toolchain
# (same base digest, so rustc/cargo match the measurement binary) and adds the
# generic compressors the honest comparison needs: gzip, zstd, xz and brotli,
# plus jq to reduce the JSON table. For the query-cost court it also adds `pv`
# (counts the compressed bytes a sequential decoder must read and the
# decompressed bytes it must inflate to reach an offset) and GNU `time`
# (`/usr/bin/time -v` for wall/CPU seconds and peak RSS). It is deliberately NOT
# part of any fast gate; only the opt-in `baseline` service builds it.
# `tools/baselines.sh` runs the compressors and the VOLE lanes over complete
# files; `tools/partial-court.sh` runs the random-access query head-to-head.
# ---------------------------------------------------------------------------
FROM dev AS baseline
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
      gzip \
      zstd \
      xz-utils \
      brotli \
      jq \
      coreutils \
      pv \
      time \
 && rm -rf /var/lib/apt/lists/*
WORKDIR /work