Files
bikoret/deploy/docker/Dockerfile.vav_pipeline
T
Scott KarpandClaude Fable 5.1 5e325d36cc the second scroll: the mesorah snapshot, pinned and read (bishe'arecha step 6)
Devarim 17:18 — the king writes his copy from before the priests, not from
memory. scripts/build_mesorah.py takes one open-licence version per work
per language from the Sefaria export (bucket sefaria-export, catalogue of
2026-10-02; Public Domain / CC0 / CC-BY / CC-BY-SA only, checked in every
file; no CC-BY-NC — the Bavli is Wikisource's) and lays it down beside
L1: mesorah/works/<slug>/{he,en}.json, index.json, integrity.sha256,
build_report.json. 128 works (Rashi, Onkelos, Ramban, Ibn Ezra, Sforno
on the Torah; all of Mishnah; 37 Bavli tractates; Bereshit and Shemot
Rabbah, Sifrei, Tanchuma), 256 files, 44.9 MiB, tree hash 7d5b3a6c…
computed as L1's (sorted relative path, then bytes; the two post-hash
files excluded). What is out, and why (licence), is in Terumah §E5.

Read, never fetched: korban_processor/mesorah.py finds citations as
written (Rashi on Devarim 6:5, Berakhot 2a, Mishnah Berakhot 1:1,
Bereshit Rabbah 1:1, Sifrei Devarim 32, Tanchuma Bereshit 1 …), resolves
each against the snapshot (complex works through their unnamed node,
Tanchuma by parashah), lists them as examination.mesorah_references, and
makes every passage found a given source for that examination — so a
claim about Rashi anchors in Rashi or does not. The Vav Pipeline couples
coupled(reference(R), mesorah(Work, [Address])) or not_in_mesorah; the
engine accepts mesorah/2 as a terminal and not_in_mesorah is Form 4.
VavPipeline.Mesorah pins the hash, re-reads the tree at startup and every
ten minutes, and /kodesh/health carries mesorah_hash. Mounted read-only at
/mnt/mesorah in the vav-pipeline and korban-processor images. L3
bedikot.mesorah (migration 20261013000002).

Also: the 1-in-12 Day6 serving failure of 2026-10-04 reproduced with seed
446116 — HaltMonitorTest left the system halted; it now resolves on exit
and the Day6 setup is defensive. Construction §3.11, Terumah §E5, Tamid
§1.1, bishearecha §IV, KOHEN, AGENTS. Doorpost 0638d4eb…. Elixir 604/0
(seeds 835592 and 446116), korban 294/1 skipped, Prolog bedikah 44/44,
L3 10/0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 19:13:36 +00:00

139 lines
5.5 KiB
Docker

# check=skip=FromPlatformFlagConstDisallowed
# ^ The --platform=linux/amd64 pins below are DELIBERATE (Exoscale SKS
# nodes are amd64). BuildKit lints a constant --platform as a smell;
# here it is the fix. Silenced so a real warning is not lost in noise.
# Shorashim Vav Pipeline — Elixir/OTP release with Sanhedrin
# Construction spec §1.1: Elixir 1.16.1, OTP 26.2.1
# The pipeline and Sanhedrin run in the same BEAM VM.
#
# PLATFORM PIN:
# Both FROM directives below pin `--platform=linux/amd64`. Exoscale
# SKS nodes are amd64; without this pin, a build on an Apple Silicon
# workstation would emit an arm64 image that the cluster cannot exec
# (the kohen's Day 3 fails with "exec format error"). The pin makes
# the build artifact self-correct regardless of build host.
# Local multi-arch dev (linux/amd64,linux/arm64) is supported by
# scripts/build_and_push.sh — see that script for the canonical build.
# === BUILD STAGE ===
FROM --platform=linux/amd64 hexpm/elixir:1.16.1-erlang-26.2.1-ubuntu-jammy-20240125 AS build
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Copy Sanhedrin (Erlang dep, referenced as path dep from vav_pipeline)
COPY sanhedrin/ sanhedrin/
# Copy Vav Pipeline
COPY vav_pipeline/ vav_pipeline/
WORKDIR /app/vav_pipeline
# Fetch deps and compile in prod mode
ENV MIX_ENV=prod
# EMULATED-BUILD JIT WORKAROUND — see the incident note at the top of
# this file. +JMsingle makes the BEAM JIT use a SINGLE writable/
# executable mapping for generated machine code instead of the default
# dual W^X mapping. The dual mapping is what dies (SIGSEGV, exit 139)
# when this amd64 stage runs emulated inside BuildKit's sandbox on an
# Apple Silicon host. Build-stage only: it does not appear in the
# runtime stage, so the shipped release runs with the ordinary
# dual-mapping JIT on the amd64 cluster node.
ENV ERL_FLAGS="+JMsingle true"
RUN mix local.hex --force && \
mix local.rebar --force && \
mix deps.get --only prod && \
mix compile
# Build OTP release
RUN mix release
# === RUNTIME STAGE ===
FROM --platform=linux/amd64 ubuntu:jammy-20240125
# libgmp10 is here for the SHORESH ENGINE, not for the BEAM.
# VavPipeline.ShoreshEnginePort spawns the Haskell binary as an Erlang
# Port — a child process of THIS container (deployment.yaml stages the
# binary onto the shoresh-bin volume with an init container). GHC-built
# executables link libgmp; without it the spawn dies with
# error while loading shared libraries: libgmp.so.10
# and Shorashim runs with no root activation, no te'amim parsing and no
# gematria while still reporting itself healthy.
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libstdc++6 libgmp10 openssl ca-certificates locales && \
rm -rf /var/lib/apt/lists/* && \
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
# Non-root user — the system serves, it does not own
RUN useradd --create-home --shell /bin/bash shorashim
USER shorashim
WORKDIR /home/shorashim
# Copy the release
COPY --from=build --chown=shorashim:shorashim \
/app/vav_pipeline/_build/prod/rel/vav_pipeline ./app
# L1 Torah filesystem — baked into the image (read-only, ~29MB)
# The scroll is sealed in the aron. It ships with the vessel.
# L1 is read-only in fact, not only in name. Until 2026-10-04 the scroll
# was copied in owned by the service user with its write bits on: the
# process that reads Torah could also have rewritten it, and only the
# SHA-256 check would have noticed afterwards. Owned by root, no write
# bit for anyone; the service user can read and traverse, nothing more.
USER root
COPY --chown=root:root l1/ /mnt/torah/
RUN chmod -R a-w,a+rX /mnt/torah
# The second scroll (bishe'arecha §IV): the mesorah snapshot, read-only like L1.
COPY --chown=root:root mesorah/ /mnt/mesorah/
RUN chmod -R a-w,a+rX /mnt/mesorah
USER shorashim
# === INSCRIBE THE DOORPOST ===
# Devarim 11:20 — ukhtavtam al mezuzot beitecha uvish'arecha. A running
# pod IS a threshold, and VavPipeline.Doorpost exists to prove that the
# corporate text at THIS threshold is the same corporate text the system
# was built to hold. It cannot prove that against files it does not have.
#
# The @spec_files set (see vav_pipeline/lib/vav_pipeline/doorpost.ex)
# is inscribed here at the repo-relative paths the module hashes, rooted
# at :doorpost_repo_root from config/prod.exs. Copying whole directories
# rather than 23 individual files means a spec file added to @spec_files
# under specs/, talmudic_engine/src/halt/, or .../middot/ is carried
# automatically instead of silently going :missing in production.
#
# The hash over these files must equal Doorpost.expected_hash(); if it
# does not, this image was built from a tree whose specs and witness
# disagreed, and the pod says so at startup.
COPY --chown=shorashim:shorashim BUILD_AZAZEL.md BUILD_KORBAN.md \
/opt/shorashim/spec/
COPY --chown=shorashim:shorashim specs/ /opt/shorashim/spec/specs/
COPY --chown=shorashim:shorashim talmudic_engine/src/halt/ \
/opt/shorashim/spec/talmudic_engine/src/halt/
COPY --chown=shorashim:shorashim talmudic_engine/src/middot/ \
/opt/shorashim/spec/talmudic_engine/src/middot/
# L1 mount point
ENV L1_MOUNT_POINT=/mnt/torah
ENV MESORAH_MOUNT_POINT=/mnt/mesorah
# Manna provision file location
ENV MANNA_PROVISION_FILE=/var/lib/shorashim/manna/today.json
# PostgreSQL connection for L3
# Set DATABASE_URL in production deployment
# ENV DATABASE_URL=
# Health check port
EXPOSE 4000
CMD ["./app/bin/vav_pipeline", "start"]