Commit Graph
7 Commits
Author SHA1 Message Date
Scott KarpandClaude Fable 5.1 bbe2c4b7ba L1: the integrity check reads the scroll (tablet 38)
L1Reader.verify_integrity/0 read the hash stored in integrity.sha256
and compared that string with the hash compiled into the module. It
never opened a verse. On that comparison of a constant with its own
copy rested `l1_hash: pass`, the Cloud's "L1 corrupted — the cloud is
not visible", and Construction §1.2. A changed verse would have passed
every one of them. Every existing test passed too, because every test
asked about an untouched L1.

- L1Reader.compute_tree_hash/1: SHA-256 over every file under torah/ —
  relative path, then bytes — in the order scripts/build_l1.py hashed
  them (directories by path, files by name, plain string order). On the
  real L1 it yields the pinned 156b1d27…; for a tampered copy it yields
  the same hash the Python implementation does.
- VavPipeline.L1Integrity (new, supervised): reads and hashes the scroll
  when the pipeline starts (~0.9 s in the image) and again every ten
  minutes; logs and signals the assembly when the answer changes.
- verify_integrity/0 now requires BOTH: the recorded hash is the pinned
  one, AND the scroll on disk hashes to it (answered from the witness's
  last reading; computed on the spot where the witness is not running).
  Callers are unchanged — the Shema context, the health check and the
  status endpoint all inherit the real check.
- scripts/verify_l1.py: the same reading by hand. KOHEN.md and
  KOHEN_PROMPT.md used the hollow comparison as their L1 gate; they now
  run this.
- test/tablet38_l1_integrity_test.exs — 9 tests: the hash and its
  order; one byte / one added file / one rename each change it; the
  witness; and the whole path — with an altered scroll and an untouched
  integrity.sha256, verify_integrity fails, health says l1_hash: fail,
  and /peah/ask does not answer.

Specs: architecture §2.2 (which had been made to confess the hollow
check in d7520cd) and Construction §1.2 now describe the real one — and
its limit: a change is noticed within ten minutes, not at the instant.
deploy/ARCHITECTURE.md likewise. Doorpost @expected_hash 7e5286b9… →
3f6d47a0…, in this commit, with the witnessed files that moved it
(architecture, vayakhel).

Read before committing: Elixir 483/0 on seeds 0 7 42 99 191243. The
built image, run twice: on the engraved scroll — "read and matches
(928ms)", l1_hash pass, /peah/ask 200; on a copy with ONE LETTER changed
in Bereishit 1:1 and integrity.sha256 untouched — L1_INTEGRITY_FAILED,
l1_hash fail, cloud not readable, /peah/ask 503.

Not done: the Haskell side. Luchot.Firmware.l1ExpectedHash is compared
with nothing; the engine reads L1 without hashing it (that would need a
SHA-256 dependency). The engine is reached only through the pipeline,
which now gates every cycle on the real check.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 19:37:40 +00:00
Scott KarpandClaude Fable 5.1 f4e8e5afc8 specs §1.1/§1.5 + Doorpost: the pins say what is built, and the build obeys them
The pin audit (2026-10-04) found Construction §1 wrong in three ways.

1. §1.5's mix.exs block was not the real mix.exs.
   phoenix ~> 1.7.11 was never a dependency (the API is Plug on
   Bandit); `ecto` is `ecto_sql`; telemetry is transitive (locked
   1.4.2, outside the stated ~> 1.2.1); bandit, plug and the sanhedrin
   path dependency were missing. The block now matches mix.exs and adds
   the versions mix.lock actually builds. Terumah's Elixir table
   matched the wrong block and also said postgrex ~0.17.4; corrected.

2. §1.1's component table described a machine that is not the one
   running. PostgreSQL 16.2 via apt → 17, managed (17.11 today).
   Podman 4.9.3 → Kubernetes/containerd, managed; Podman is used
   nowhere. Ubuntu 24.04.1 → what each image is in fact built on
   (Ubuntu 22.04 for pipeline and engine, Debian 12 for korban and
   talmudic) and the managed node (24.04). rebar3 3.23.0 → 3.22.0, the
   version in the build image. Azazel Processor added as a component.
   The spec is corrected to the deployment, not the reverse.

3. §1.1's rule — "No >=. No +. No ranges." — was not true of the spec's
   own Elixir deps, and "lock files are committed" was not true of two
   components. Both halves fixed:
   - The rule now says what is the case: a manifest may give a range;
     the committed lock is the pin; every image is built from its
     lock; base images are pinned by tag; managed services are pinned
     to a major version and patched by the provider.
   - And the build was made to obey it. The Korban image installed
     three packages named by hand and let pip pick every transitive
     one on the day of the build, plus an unpinned poetry-core. It now
     installs the lock's main group by exact version AND hash
     (scripts/lock_to_requirements.py; --require-hashes --no-deps;
     pip check). The image holds the lock's 12 packages and nothing
     else.
   - azazel_processor/poetry.lock: generated (it had none).
   - kushya_generator/pyproject.toml + poetry.lock: the four §1.4 pins
     (llama-cpp-python 0.2.55, peft 0.9.0, transformers 4.38.2,
     datasets 2.17.1) were pinned nowhere in the repo. They are now
     declared and locked (74 packages). The lock resolves; it has NOT
     been installed or run — Step 21 is unbuilt and needs a GPU.
     Its test config gains the korban and azazel source paths, which
     the external backend needs: 3 tests there had been failing since
     the azazel build, unnoticed because that suite is in no total.

Doorpost @expected_hash 39b66c31… → 1cd07079…, in this commit, with the
witnessed file that moved it (vayakhel).

Read before committing: Elixir 474/0 (seeds 0, 42) · korban 222 passed
1 skipped and azazel 125 passed, each with dependencies installed from
its lock by hash · kushya 17 passed (was 14 of 17) · korban image
starts, imports korban_processor + azazel_processor, pip check clean ·
pipeline image reports specification_identity verified 1cd07079….

Left as written: architecture §2's technology table still names
Phoenix, PostgreSQL 16, Ubuntu 24.04 and rootless Podman for Sanhedrin
isolation, and terumah §B still lists systemd, squashfs, Caddy,
nftables for a self-hosted server. Those describe a design, not a pin.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 19:17:46 +00:00
Scott KarpandClaude Fable 5.1 521f263e69 specs §1.3 + Doorpost: the Haskell versions the engine is actually built from
Construction §1.3 is headed "Haskell Dependencies (Exact)" and shows an
excerpt of cabal.project.freeze. Six of its nine versions were not the
ones in the committed freeze file:

  aeson       2.2.1.0   → 2.2.3.0
  vector      0.13.1.0  → 0.13.2.0
  bytestring  0.12.1.0  → 0.12.2.0
  filepath    1.4.200.1 → 1.4.301.0
  directory   1.3.8.4   → 1.3.10.1
  hspec       2.11.7    → 2.11.16

base 4.18.2.0, containers 0.6.7 and text 2.0.2 already agreed. The
freeze file has not changed since Phase 1 (ae78ed2) and every engine
image has been built from it; the build plan inside the build image
(dist-newstyle/cache/plan.json, GHC 9.6.4) lists exactly these nine
versions. The spec is corrected to the freeze, not the freeze to the
spec: the freeze is the tested vessel.

- specs/shorashim_vayakhel.md §1.3: the six versions.
- specs/shorashim_terumah.md §D: the same, plus rows for filepath and
  directory; bytestring was marked "ships with GHC" — GHC 9.6.4 ships
  0.11.5.3, and the freeze pins a newer one from Hackage.
- Doorpost @expected_hash 5094e48e… → 39b66c31…, in this commit, with
  the witnessed file that moved it (vayakhel).

Read before committing: Elixir 474/0 on seeds 0 and 42; the built
pipeline image reports specification_identity verified 39b66c31….
No engine change: the engine image is untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 19:00:10 +00:00
Scott KarpandClaude Fable 5.1 efd35bb194 specs + Doorpost: pyswip removed — a material the vessel never used (tablet 36)
Architecture §3.5 listed a Python-Prolog FFI among the Korban
Processor's dependencies ("swipl-ffi (or pyswip)"); Construction §1.4
and terumah pinned pyswip. It was declared, installed in every image,
and never imported. The Korban Processor does not call Prolog: haktarah
emits Prolog-format STRINGS, and the pipeline carries them to the
Talmudic Engine over its Unix socket (Construction §3.3). The korban
image has no libswipl, so the package could not have been used there
had anything tried. Tablet 35 corrected its version; the transmitter's
word is to remove it.

Removed from:
- specs/shorashim_architecture.md §3.5 requirements
- specs/shorashim_vayakhel.md §1.4
- specs/shorashim_terumah.md (materials row; the compatibility-testing
  line now names hebrew-tokenizer alone)
- BUILD_KORBAN.md
- korban_processor/pyproject.toml, poetry.lock (regenerated)
- deploy/docker/Dockerfile.korban_processor

Doorpost @expected_hash 81da49d4… → 2f40c382…, in this commit, with the
three witnessed files that moved it (architecture, vayakhel,
BUILD_KORBAN).

Read before committing: Elixir 461/0 (seeds 0, 42); korban 222 passed,
1 skipped against the installed package with pyswip absent; korban
image starts and idles as before; vav-pipeline image reports
specification_identity verified 2f40c382… and l1_hash pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 17:57:58 +00:00
Scott KarpandClaude Fable 5.1 505a967a1c specs §1.4 + Doorpost: pyswip 0.2.10 — the pinned version was never published (tablet 35)
Construction §1.4 pinned `pyswip = "0.2.11"`. PyPI has 0.2.10 (2020) and
then 0.3.0; 0.2.11 does not exist and never did. pyproject.toml copied
the spec faithfully, so `pip install .` in korban_processor has failed
since Step 13. Nobody saw it: the Dockerfile installs its dependencies
by hand and already said 0.2.10, and the test run uses PYTHONPATH. The
pin was wrong in the one place that was never executed. Found
2026-10-04, the first time the korban suite was run from a clean
container by installing the package.

The spec is corrected to what the vessel has in fact carried since the
first image:

- specs/shorashim_vayakhel.md §1.4, BUILD_KORBAN.md, terumah §row:
  0.2.11 → 0.2.10. Terumah now also says what is true of this
  material: declared and installed, not imported anywhere, and not
  usable in the korban image as built (no libswipl) — it must be
  tested against SWI-Prolog 9.2.2 before first use.
- korban_processor/pyproject.toml: 0.2.10. `pip install .` succeeds in
  python:3.12.2-slim; 222 passed, 1 skipped against the installed
  package.
- korban_processor/poetry.lock: regenerated (poetry 2.5.1). It had
  never contained pyswip, httpx or hebrew-tokenizer at all.
- Doorpost @expected_hash: ed2a6aec… → 81da49d4…, in this commit, with
  the two witnessed files that moved it (vayakhel, BUILD_KORBAN), per
  the Doorpost's own rule and the precedent of 0572a2c (postgrex).

No behaviour changes: the image installs the same four packages it
installed yesterday.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 17:49:42 +00:00
Scott KarpandClaude Opus 5 0572a2cffd specs §1.5 + Doorpost: postgrex ~> 0.22.3 — ma'akeh before the roof is walked on
TORAH ANCHOR — Devarim 22:8:
כִּי תִבְנֶה בַּיִת חָדָשׁ וְעָשִׂיתָ מַעֲקֶה לְגַגֶּךָ וְלֹא תָשִׂים
דָּמִים בְּבֵיתֶךָ כִּי יִפֹּל הַנֹּפֵל מִמֶּנּוּ.
"When you BUILD a new house, make a parapet for your roof, and do not
place blood in your house, for the faller will fall from it."

The obligation attaches at BUILD time and to the BUILDER — ki tivneh,
not ki teshev. The kohen who dwells in the house does not owe the
parapet; the one who builds it does. That is why this is Bezalel's
commit and not the kohen's, and why it lands before the vessel is
handed over rather than after.

The roof in question is /peah/ask. It is unauthenticated BY DESIGN —
Vayikra 19:9-10, lo techalleh pe'at sadcha b'kutzrecha. The corner is
left open on purpose. Ma'akeh is not a wall around the corner; it is
what keeps a deliberate opening from becoming a fall.

WHAT WAS FOUND (kohen escalation, BUILDER_HANDOFF_amd64.md §Second
Finding, confirmed by `mix deps.get` advisory output in an amd64
container on 2026-08-23):

  postgrex 0.17.5  VULNERABLE
    EEF-CVE-2026-32687 / GHSA-r73h-97w8-m54h   HIGH
      SQL injection via channel name in
      Postgrex.Notifications.listen/3 and unlisten/3
      introduced 0.16.0, fixed 0.22.2
    EEF-CVE-2026-58225 / GHSA-4mw9-4qgj-m97w   LOW
      SQL injection via unescaped dollar-quote in reconnect replay
      → notification denial of service
      introduced 0.16.0, fixed 0.22.3

  plug 1.19.1      VULNERABLE
    EEF-CVE-2026-54892 / GHSA-j43x-5hjq-rgxf   HIGH
      quadratic-time decoding of nested query/body parameters
      → denial of service
      1.19.x line fixed in 1.19.3

Affected ranges read from api.osv.dev, not from the advisory titles.
There is no 0.17.6; the postgrex fix does not exist below 0.22.2, so
the pin must cross two minor lines. 0.22.3 is the lowest version that
clears BOTH postgrex advisories.

THE SPEC CHANGE (Layer 1, lo_tosif.md):

  specs/shorashim_vayakhel.md §1.5
    {:postgrex, "~> 0.17.4"}  →  {:postgrex, "~> 0.22.3"}

  vav_pipeline/lib/vav_pipeline/doorpost.ex
    @expected_hash c7ac85cd…b98bb6af  →  ed2a6aec…6b72c2e22

Committed atomically per specs/lo_tosif.md Layer 1: the spec file and
its witness move together, in one reviewable unit, with the Torah
anchor named. Verified before the hash was updated that the mechanism
actually fired — verify_identity/0 returned SPEC_INTEGRITY_FAILED and
chatzotzrot :assembly_leaders (teruah) sounded on the drift. The
doorpost is not decorative; it caught this change on the way through.

NOT A SPEC CHANGE:
plug is not pinned in §1.5, so the plug bump (1.19.1 → 1.20.3) is an
operations change per lo_tosif.md "What is NOT a spec change" and
touches mix.lock only. Same for the transitive movers that came with
the resolution: db_connection 2.9.0→2.10.2, decimal 2.3.0→2.4.1,
jason 1.4.4→1.4.5, plug_crypto 2.1.1→2.2.0, telemetry 1.4.1→1.4.2.

VERIFIED:
- `mix deps.get` reports no advisories against the resolved tree
- `mix compile --force` clean
- `mix test` — 412 tests, 0 failures, 35 excluded (:l3, need PostgreSQL)
- VavPipeline.Doorpost.verify_identity() → :ok
- l1/integrity.sha256 unchanged: 99bbd07a…4ea377

FLAGGED, NOT FIXED — §1.5 has further drift this commit deliberately
does not touch. The block still lists {:phoenix, "~> 1.7.11"} and
{:ecto, "~> 3.11.1"}, while vav_pipeline/mix.exs actually depends on
ecto_sql, bandit, plug and the sanhedrin path dep, and has never
depended on phoenix. Correcting that is a larger category-grade
question than the security finding I was handed, and lo tosif says
the builder does not widen a commanded change on his own motion.
Raised in the handoff-back instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 12:00:32 -04:00
Scott KarpandClaude Opus 4.6 6dcb72ec5e Rename spec files to Torah-faithful names per parshah
Each spec corresponds to a parshah of Shemot. The earlier names
were generic English (materials, operations, construction,
economic_model). Torah names them precisely:

- Shemot 25:2 — terumah (תרומה, root רום, "what is lifted")
- Shemot 27:20 — tamid (תמיד, "continual" — the lamp that never goes out)
- Shemot 35:1 — vayakhel (קהל, "assembled" — community-formed building)
- Shemot 38:21 — pekudei (פקד, "accounted" — every material counted)

Renames:
  shorashim_materials.md       → shorashim_terumah.md
  shorashim_operations.md      → shorashim_tamid.md
  shorashim_construction.md    → shorashim_vayakhel.md
  shorashim_economic_model.md  → shorashim_pekudei.md

Updated cross-references in:
- README.md (parshah table + repo tree, also fixed stale tree
  showing src/ and transcripts/ that no longer exist)
- AGENTS.md
- BUILD_KORBAN.md
- specs/shorashim_terumah.md (internal Document Registry)

Generic English is silver. Torah's words are gold (Mishlei 25:11).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 08:19:33 -04:00