Files
bikoret/deploy/ARCHITECTURE.md
T
Scott KarpandClaude Fable 5.1 d7520cd69d specs §2 + images + Doorpost: the technology table says what is built; L1 is read-only in fact
Architecture §2 described a self-hosted server: Phoenix for L2,
PostgreSQL 16, Ubuntu 24.04 under systemd, rootless Podman isolating
Sanhedrin panels, Erlang distribution between them, systemd timers for
Shabbat and the cycle, L1 on a read-only mount. None of that is what
runs. Each row was checked against the code and the images before it
was rewritten.

§2.1  exact versions (no "9.6+"); Korban and Azazel Processors listed.
§2.2  L1: in every image, root-owned, no write bit; recorded hash
      compared before every cycle. L2: a process in the pipeline, not
      yet over HTTP and not yet called by the cycle. L3: PostgreSQL 17
      managed, append-only by REVOKE.
§2.3  Kubernetes, one pod. OTP supervisors + the Deployment's probes.
      Sanhedrin panels are Erlang processes in the pipeline's BEAM — no
      container boundary. Message passing within one node; a port to
      the engine; a Unix socket to the Talmudic Engine. Logging: stdout
      and L3; halt events in memory. ShabbatTimer process, UTC stub.
      No cycle timer: erev/voker is a stage of each cycle. The manna
      volume.

A DEFECT FOUND BY CHECKING THE L1 ROW, AND FIXED:
The spec said L1 is a read-only filesystem. In all four images the
scroll was owned by the service user, mode 664 — `touch` inside
/mnt/torah succeeded. The process that reads Torah could have rewritten
it. All four Dockerfiles now copy L1 as root and strip every write bit
(dirs 555, files 444). Verified in each image as the service user:
cannot create, append, or delete. The hash is unchanged (it covers
paths and contents, not modes).

A DEFECT FOUND AND NOT FIXED, now written into the spec as it is:
L1Reader.verify_integrity/0 reads the hash stored in integrity.sha256
and compares it with the compiled-in constant. It never hashes the
verse files. `l1_hash: pass` witnesses which L1 was built into the
image, not that the files are unaltered. §2.2 says so in plain words.

deploy/ARCHITECTURE.md: L1 is in the images, not on a volume; the manna
volume is 1 GiB and holds the ledger too; l1-volume.yaml is vestigial.

Doorpost @expected_hash 1cd07079… → 7e5286b9…, in this commit, with the
witnessed file that moved it (architecture).

Read before committing: Elixir 474/0 (seeds 0, 42). Four images
rebuilt; full local stack (real engine binary, PostgreSQL with SSL,
migrations): Hebrew 200, English 422, health 7/7, 2 interpretations in
L3, no errors; talmudic and korban containers start.

Left as written: §1.4 hardware (a 64–128 GB server; the node has 4 GB),
§2.4 external models (Steps 21–22, unbuilt), §4's build steps
("Install PostgreSQL 16"), terumah §B (systemd, squashfs, Caddy,
nftables).

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

3.9 KiB

Deployment Architecture

Generic architecture shape for a shorashim deployment. Specifics of a particular deployment (hostnames, IPs, account names, credentials) live in the operator's private notes, not in this repo.

Components

One Kubernetes namespace runs the following:

Component Runtime Purpose
vav-pipeline Elixir/OTP release Bereishit cycle, ShemaContext, Cloud, Manna, HTTP API (pe'ah, courtyard, chatzer, kodesh)
shoresh-engine Haskell binary, spawned by vav-pipeline as an Erlang Port (staged into the pod by the shoresh-engine-install init container — NOT a sidecar container; a Port is a child process of the BEAM and cannot cross a container boundary) Root activation, te'amim parsing, gematria
talmudic-engine SWI-Prolog (sidecar via Unix socket) 613 mitzvot, 13 middot, kushya generation, teiku
korban-processor Python 3.12 (sidecar) Offering protocol, eish zarah validation

All four run in the same pod. vav-pipeline is the main container; talmudic-engine and korban-processor are sidecars; shoresh-engine runs inside vav-pipeline as an Erlang Port child process, staged in by an init container.

External dependencies

Dependency Purpose Contract
Managed PostgreSQL 17+ L3 Oral Tradition (append-only) DATABASE_URL env var. Requires SSL. Role with SELECT, INSERT only — UPDATE, DELETE revoked (see migration).
(none — in the images) L1 Torah filesystem (~29 MB) Baked into every image at /mnt/torah, owned by root with no write bit. No volume. The recorded SHA-256 is compared with the pinned hash before every cycle.
Block-storage PersistentVolume Manna provision and its ledger (read-write, 1 GiB) Mount at /var/lib/shorashim/manna. Operator writes today.json daily; the vessel writes ledger.json.
Ingress controller + TLS cert Public HTTPS access Cert-manager with Let's Encrypt HTTP-01 is the reference setup.
Container registry Image distribution Any registry that supports Docker v2 protocol.

Kubernetes manifests

Kept in deploy/k8s/:

  • namespace.yaml — the namespace
  • configmap.yaml — non-secret configuration
  • secrets.yaml — template only; operator fills in DATABASE_URL
  • l1-volume.yaml — PV and PVC for Torah filesystem (vestigial: L1 is in the images; do not apply)
  • manna-volume.yaml — PVC for provision file
  • deployment.yaml — the pod with 3 containers + 2 init containers (shoresh-engine-install, migrate). Four images are still built and pushed; shoresh-engine ships a binary, not a running container.
  • service.yaml — ClusterIP and external LoadBalancer
  • gitea-mcp-deployment.yaml — separate MCP server for Gitea connector (optional)
  • gitea-mcp-ingress.yaml — TLS ingress for the MCP server
  • gitea-mcp-secret.yaml — template for Gitea PAT
  • cert-manager-issuer.yaml — Let's Encrypt ClusterIssuer

Containers

Four Dockerfiles in deploy/docker/:

  • Dockerfile.vav_pipeline — multi-stage Elixir 1.16.1 / OTP 26.2.1 release
  • Dockerfile.shoresh_engine — multi-stage Haskell GHC 9.6.4 / Cabal
  • Dockerfile.talmudic_engine — SWI-Prolog 9.2.2 with socket server
  • Dockerfile.korban_processor — Python 3.12.2 slim

Configuration surface

The system reads three things from its environment:

  1. L1 Torah — in the image at $L1_MOUNT_POINT, not writable by the service user. Its recorded hash is checked before every cycle.
  2. Manna provision — JSON file at $MANNA_PROVISION_FILE, written by the kohen/treasurer.
  3. L3 database — connection string in $DATABASE_URL.

Nothing else is configurable. The system obeys Torah (L1 + calendar) for governance and the provision file for resources.

Seven-day inauguration

Before serving users, run the shiv'at y'mei milu'im sequence documented in KOHEN.md. Each day validates a specific layer. Partial inauguration is no inauguration.