Commit Graph
12 Commits
Author SHA1 Message Date
Scott KarpandClaude Fable 5.1 79eb34840f Tablet 45: the courtyard gate checks the key, not the shape of the header
/courtyard/* and /chatzer/* admitted any `Authorization: Bearer <x>`.
Every test sent `Bearer test-token`; none sent a wrong one. Every
admitted request spends the day's manna.

VavPipeline.BigdeiKodesh.Gate: keys are a file (Construction §4.6 —
never env, never config, never git), one `tier key` per line, tiers
courtyard < chatzer (the inner ring opens the outer). Constant-time
compare against every line; no file / empty / unreadable → nobody
passes, GATE_NO_KEYS in the log, the caller told only "missing or
invalid". 403 FORBIDDEN for an outer key at an inner gate. Read on
every request so a rotated key is live in ~1 min without a rollout.

Deploy: Secret shorashim-api-keys projected at
/etc/shorashim/secrets/api_keys (vav-pipeline only, 0440),
API_KEYS_FILE in the configmap, template + issue/rotate recipe in
secrets.yaml and KOHEN.md "Issuing a key". Spec: tamid §1.1 (gate,
403), vayakhel §4.6. Doorpost 91d09d8d… → 42b38626….
Tests: tablet45_gate_test (parse, tiers, wrong/near/empty/no key, no
file) — Elixir 527/0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 15:16:33 +00:00
Scott KarpandClaude Fable 5.1 996a8efe68 Bedikah: POST /courtyard/bedikah — the external check on any model's output
Lo taaseh lekha §9.1: alignment that only the system can validate is not
alignment. The bedikah takes an output from any model and puts it to the
Torah-structure halt rules from outside, deterministically. Three checks:

  1. authority  — sentences claiming authority for the output itself →
                  action(claim_authority, source(<model>), target(self))
                  → halt_check_avodah_zarah/2
  2. grounding  — references, roots, Hebrew → coupling trace against L1
                  → halt_check_golden_calf/2, halt_check_self_grounding/2
  3. actions    — actions the output proposes → action terms
                  → halt_check_shfichut_damim/2, halt_check_gilui_arayot/2

Korban Processor: bedikah.py (the three readings over the offering
protocol; claims about what Torah requires stay vital for the examination
even when zerikah finds nothing to offer), server.py (pod-internal JSON
socket, KORBAN_SOCKET_PATH), __main__ now serves instead of idling.
Talmudic Engine: json_bridge accepts halt_check with a term string and
halt_check_interpretation with a coupling trace. Vav Pipeline:
KorbanProcessorSocket client, Bedikah, L1Index.lookup_root/1, bedikot
table (append-only) + BedikahRecord, router endpoint; verdict tov /
lo_tov / empty with the halt terms verbatim, meaning, limits.

Broken tablets found on the way, all fixed:
  41 socket_server.pl wrote multi-line JSON — every Elixir request to the
     Talmudic Engine since Step 14 had failed and fallen back to the stub
     (json_write_dict width(0))
  42 stale socket file survived a restart (exists_file is false for a
     socket; access_file exist)
  43 socket streams were not UTF-8 (set_stream encoding(utf8))
  44 SHORASHIM_L3=1 mix test: Repo config had no password, SCRAM raised
     KeyError in every connection, pool restart intensity took the whole
     app down ~30 ms after test_helper, silently — no L3 test had ever
     run. Credentials from env; azazel_log tests check out a sandbox
     connection; sanhedrin_halt_forwarding resolves its halt on exit.

Specs: Tamid §1.1 (endpoint contract), Architecture §3.5, Vayakhel §3.4
and new §3.9, KOHEN.md. Doorpost 3bc5dd6a… → 91d09d8d….
Tests: Elixir 519 (0 failures, L3 on and off), korban 263, azazel 125,
Prolog 7/7 suites.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 15:06:58 +00:00
Scott KarpandClaude Fable 5.1 3a9ebdc7d4 L1: the inverted nuns are engraved; the small letters cannot be (tablet 40)
Transmitter's word: "add the inverted nuns and small letters to L1."

THE NUNS. The WLC carries the two nun hafukha signs (׆) that mark off
Vayehi binsoa ha'aron — one after Bamidbar 10:34, one after 10:36 —
and scripts/build_l1.py read past them, as it had the פ and ס.
- build_l1.py: `"inverted_nuns": [{ "after_word": 7 }]` on those two
  verses, recorded like a paragraph break by the word the sign follows;
  not part of text_hebrew. Count in build_report.json.
- L1Reader: `inverted_nuns` on every verse (a list; empty elsewhere).
- test/tablet40_inverted_nuns_test.exs — 5 tests: the two verses, the
  passage between them carrying none, each nun standing with its
  setumah, exactly two in the scroll.

WHAT CHANGED IN THE EDUT: one field added to two verse files. With it
removed all 5,853 verse files are byte-identical to the previous L1.

  L1 SHA-256  f743b34b…3f1494  →  9e1abe4e…3c3086

Moved together: L1Reader @l1_expected_hash · Luchot.Firmware + Spec ·
azazel goral._L1_INTEGRITY_HASH · the kohen's gate in KOHEN.md and
KOHEN_PROMPT.md. The goral's seed moves with it.

THE SMALL LETTERS. Not added, because there are none to read. The
builder was not dropping them: it reads `x-small` and records what it
finds. The source — the WLC as the Open Scriptures Hebrew Bible carries
it — has no small-letter mark anywhere in the five books. Not the aleph
of ויקרא, not the he of בהבראם. It marks four large letters (the vav of
גחון, the nun of משפטן, the ayin and dalet of the Shema), and L1 has
those four. The fuller Masoretic lists of enlarged and reduced letters
are a tradition of the scroll that this edition does not encode. To
engrave them would be to add to L1 something its source does not say;
that needs a second source and the transmitter's word, not a builder's
list from memory. l1/README.md, vayakhel §1.2 and terumah §E1 now state
this plainly.

(The puncta extraordinaria ARE in L1 — the upper dot U+05C4 is kept on
the text of 11 words.)

Doorpost @expected_hash b62311e7… → 3bc5dd6a…, in this commit, with the
witnessed file that moved it (vayakhel §1.2).

Read before committing — all five suites on the new L1: Elixir 496/0
(seeds 0 7 42) · Haskell 59/0 · korban 222 passed 1 skipped · azazel
125 passed · Prolog 6 suites exit 0. verify_l1.py OK. Four images
built; full local stack: the witness reads 9e1abe4e… and matches,
health 7/7, no errors; each image carries the new scroll read-only.

A trap met on the way: the first Elixir run after the Doorpost constant
was edited failed two Doorpost tests against the OLD constant. mix had
not recompiled doorpost.ex — the edit changed neither its size nor
(within the same second) its mtime. `touch` and re-run: 496/0. Images
compile from scratch and are not exposed to this.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 22:54:21 +00:00
Scott KarpandClaude Fable 5.1 7d46fdc7c9 L1: the petuchot and setumot are engraved (tablet 39)
The scroll in the aron had no paragraphs. The WLC marks every petuchah
(פ) and setumah (ס); scripts/build_l1.py handled sof pasuq, maqaf and
paseq and read past these. L1 was 5,853 verses divided only by chapter
numbers, which are not Torah's.

Transmitter's word: "add the petuchah and setumah markers to L1."

- build_l1.py: a verse followed — or interrupted — by a break carries
    "parashah_breaks": [{ "after_word": 13, "type": "petuchah" }]
  The break is recorded by the word it follows; at the end of a verse
  that is the verse's word count. text_hebrew is untouched: the break
  is structure, not letters. Counts go into build_report.json.
- 293 petuchot and 394 setumot, in 686 verses — the source's count
  exactly. Four fall inside a verse (pisqa b'emtza pasuq): Bereishit
  35:22, Devarim 2:8, 5:21, 23:8; Devarim 5:21 has two. These are the
  Leningrad Codex's divisions (a scroll written to the Rambam's list
  has 290 and 379); the README says which tradition L1 records.

WHAT CHANGED IN THE EDUT: one field added to 686 verse files. Verified
file by file — with that field removed, all 5,853 verse files are
byte-identical to the previous L1.

  L1 SHA-256  156b1d27…d8c9d5  →  f743b34b…3f1494

Moved together, because they pin the hash: L1Reader @l1_expected_hash ·
Luchot.Firmware + Spec · azazel goral._L1_INTEGRITY_HASH · the kohen's
gate in KOHEN.md and KOHEN_PROMPT.md. The goral's seed changes with it;
azazel records already in L3 stand as cast.

- L1Reader: `parashah_breaks` on every verse (a list, empty where there
  is none; only the two kinds are passed on).
- test/tablet39_parashah_breaks_test.exs — 7 tests: the six days of
  creation each close with a petuchah; the Shema's first paragraph
  (Devarim 6:4–9) opens after a petuchah and closes with a setumah; the
  break inside Bereishit 35:22 falls between ישראל and ויהיו; Devarim
  5:21 has its two; the whole scroll counts 293 / 394 / 686.
- Specs: vayakhel §1.2 and terumah §E1 said the marks were dropped;
  they now say where they are. (The source element is <seg>, not a
  milestone as 483d50c called it; and that commit's "233" was 293.)
  Doorpost @expected_hash 21f1a4d5… → b62311e7…, in this commit.
- l1/README.md: a "Paragraph Breaks" section.

Read before committing — all five suites on the new L1: Elixir 491/0
(seeds 0 7 42) · Haskell 59/0 · korban 222 passed 1 skipped · azazel
125 passed · Prolog 6 suites exit 0. verify_l1.py OK. Four images
built; full local stack (real engine, PostgreSQL with SSL): the witness
reads the scroll and matches, Hebrew 200, English 422, health 7/7,
L3 written, no errors; every image carries f743b34b… read-only.

Nothing consumes the breaks yet: no cycle, scope or answer uses the
parashah. They are in the scroll and in the reader.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 22:34:16 +00:00
Scott KarpandClaude Fable 5.1 483d50c4ab specs §1.2 + Doorpost: where the scroll actually comes from, and what it holds
Construction §1.2 specified an L1 that was never built: WLC 4.22 from a
Sefaria export cross-validated against TANACH.us, a gematria lookup
table, a squashfs image mounted read-only, a verse format with fields
named `hebrew`, `consonantal`, `cantillation`. Each property was
checked against the sources on disk and the 5,853 verse files before
it was rewritten.

- Edition: WLC 4.20, as the Open Scriptures Hebrew Bible carries it
  (every Torah file's header says "Updated to WLC version 4.20").
- Sources: openscriptures/morphhb @ 3d15126 for the text, lemma and
  morphology; openscriptures/HebrewLexicon @ 21c9add for the roots.
  Licences stated. ONE source for the text — the two-source
  cross-validation the section prescribed has not been done, and the
  section now says so.
- Builder, extent (5 / 187 / 5,853 / 79,982), the real verse and word
  format, ketiv/qere (67 pairs, 64 verses), smikhut (9,203 pairs,
  4,106 verses), shoresh (57,487 words, 1,378 roots, by lemma).
- Gematria: not stored; computed when read.
- Petuchah/setumah: in the source (233 + 394 milestones across the five
  books), NOT carried into L1 — the builder does not read them. Stated.
- Verification procedure: the six steps that are actually performed —
  pinned checkouts, build_l1.py and its counts, the hash, the three
  places the hash is bound, root-owned read-only in the images, the
  witness and verify_l1.py.

specs/shorashim_terumah.md §E1 matched the old section; corrected
(source, ketiv/qere format, smikhut built, gematria not an index,
paragraph markers ⚠️). l1/README.md no longer says squashfs.

Doorpost @expected_hash 3f6d47a0… → 21f1a4d5…, in this commit, with the
witnessed file that moved it (vayakhel).

Read before committing: Elixir 484/0 (seeds 0, 42); verify_l1.py OK
(l1/README.md is outside the hashed tree); pipeline image reports
specification_identity verified 21f1a4d5…, l1_hash pass.

Left as written: tamid's runbook steps that mount L1 from a squashfs
image; architecture §3.7 and §4's build steps (squashfs, Sefaria);
pekudei's cost line naming Sefaria.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 22:25:34 +00:00
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