Shemot 40:33 — Vay'khal Moshe et ham'lakhah. The builder completes the work. The vessel is ready for transport. Step 33 — Deployment configuration: - Dockerfiles for all 4 components: - vav_pipeline: Elixir 1.16.1/OTP 26.2.1 release with Sanhedrin - shoresh_engine: GHC 9.6.4 binary - talmudic_engine: SWI-Prolog 9.2.2 - korban_processor: Python 3.12.2 with pydantic - Kubernetes manifests for Exoscale SKS (ch-gva-2): - Namespace, ConfigMap, Secrets template - L1 Torah PV/PVC (read-only mount) - Manna provision PVC (kohen writes, system reads) - Deployment: vav-pipeline + 3 sidecars, shared volumes - Service: ClusterIP + LoadBalancer with Exoscale NLB - Init container runs Ecto migrations (VavPipeline.Release) Step 36 — Halt monitor (esh tamid): - GenServer watches for three cardinal sins - halt!/3 immediately halts system, sounds Chatzotzrot war signal - Permanent audit log — halt events never deleted - resolve/1 requires explicit operator action to resume - alive?/0 for morning tamid verification - 13 tests: alive check, 3 halt types, resolution, audit log, chatzotzrot war signal integration - Added to supervision tree All 219 Elixir + 19 L3 + 195 Prolog + 33 Haskell = 447+ tests, 0 failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
152 lines
4.7 KiB
Elixir
152 lines
4.7 KiB
Elixir
defmodule VavPipeline.HaltMonitorTest do
|
|
@moduledoc """
|
|
Tests for the HaltMonitor — esh tamid.
|
|
|
|
Vayikra 6:6 — Esh tamid tukad al hamizbe'ach, lo tikhbeh.
|
|
"A perpetual fire shall be kept burning on the altar; it shall not go out."
|
|
|
|
Operations spec §2.1, Step 5:
|
|
The system does not run without the halt monitor.
|
|
"""
|
|
|
|
use ExUnit.Case, async: false
|
|
|
|
alias VavPipeline.HaltMonitor
|
|
|
|
setup do
|
|
# Resolve any existing halt from a previous test
|
|
if HaltMonitor.halted? do
|
|
HaltMonitor.resolve("test cleanup")
|
|
end
|
|
|
|
:ok
|
|
end
|
|
|
|
# ============================================================
|
|
# Alive check — esh tamid verification
|
|
# ============================================================
|
|
describe "esh tamid" do
|
|
test "monitor is alive" do
|
|
assert HaltMonitor.alive?()
|
|
end
|
|
|
|
test "status is :running when no halt" do
|
|
assert HaltMonitor.status() == :running
|
|
end
|
|
|
|
test "halted? returns false when running" do
|
|
refute HaltMonitor.halted?()
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
# Halt detection — three cardinal sins
|
|
# ============================================================
|
|
describe "halt!" do
|
|
test "avodah_zarah halts the system" do
|
|
assert :halted = HaltMonitor.halt!(:avodah_zarah, "external model treated as Torah")
|
|
assert HaltMonitor.halted?()
|
|
|
|
{:halted, event} = HaltMonitor.status()
|
|
assert event.condition == :avodah_zarah
|
|
assert event.reason == "external model treated as Torah"
|
|
assert event.resolved == false
|
|
end
|
|
|
|
test "shfichut_damim halts the system" do
|
|
assert :halted = HaltMonitor.halt!(:shfichut_damim, "user data deletion attempted")
|
|
assert HaltMonitor.halted?()
|
|
|
|
{:halted, event} = HaltMonitor.status()
|
|
assert event.condition == :shfichut_damim
|
|
end
|
|
|
|
test "gilui_arayot halts the system" do
|
|
assert :halted = HaltMonitor.halt!(:gilui_arayot, "L1/L3 boundary collapsed")
|
|
assert HaltMonitor.halted?()
|
|
|
|
{:halted, event} = HaltMonitor.status()
|
|
assert event.condition == :gilui_arayot
|
|
end
|
|
|
|
test "halt records detected_at timestamp" do
|
|
HaltMonitor.halt!(:avodah_zarah, "timestamp test")
|
|
{:halted, event} = HaltMonitor.status()
|
|
|
|
assert event.detected_at != nil
|
|
assert %DateTime{} = event.detected_at
|
|
end
|
|
|
|
test "halt records component" do
|
|
HaltMonitor.halt!(:avodah_zarah, "component test", "korban_processor")
|
|
{:halted, event} = HaltMonitor.status()
|
|
|
|
assert event.component == "korban_processor"
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
# Resolution
|
|
# ============================================================
|
|
describe "resolve" do
|
|
test "resolving a halt resumes the system" do
|
|
HaltMonitor.halt!(:avodah_zarah, "test halt for resolution")
|
|
assert HaltMonitor.halted?()
|
|
|
|
{:ok, :resumed} = HaltMonitor.resolve("Investigation complete — false positive")
|
|
refute HaltMonitor.halted?()
|
|
assert HaltMonitor.status() == :running
|
|
end
|
|
|
|
test "resolving when not halted returns error" do
|
|
assert {:error, :not_halted} = HaltMonitor.resolve("nothing to resolve")
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
# Audit log — permanent record
|
|
# ============================================================
|
|
describe "audit log" do
|
|
test "halt events are recorded in audit log" do
|
|
initial_count = length(HaltMonitor.audit_log())
|
|
|
|
HaltMonitor.halt!(:avodah_zarah, "audit test 1")
|
|
HaltMonitor.resolve("resolved 1")
|
|
|
|
HaltMonitor.halt!(:shfichut_damim, "audit test 2")
|
|
HaltMonitor.resolve("resolved 2")
|
|
|
|
log = HaltMonitor.audit_log()
|
|
assert length(log) >= initial_count + 2
|
|
end
|
|
|
|
test "audit log preserves halt details" do
|
|
HaltMonitor.halt!(:gilui_arayot, "audit detail test", "specification_module")
|
|
HaltMonitor.resolve("test cleanup")
|
|
|
|
log = HaltMonitor.audit_log()
|
|
event = Enum.find(log, &(&1.reason == "audit detail test"))
|
|
|
|
assert event != nil
|
|
assert event.condition == :gilui_arayot
|
|
assert event.component == "specification_module"
|
|
end
|
|
end
|
|
|
|
# ============================================================
|
|
# Chatzotzrot integration — war signal on halt
|
|
# ============================================================
|
|
describe "chatzotzrot war signal" do
|
|
test "halt sounds the war signal" do
|
|
VavPipeline.Chatzotzrot.subscribe(:kohanim)
|
|
|
|
HaltMonitor.halt!(:avodah_zarah, "chatzotzrot test")
|
|
|
|
# War signal should be received by kohanim subscribers
|
|
assert_receive {:chatzotzrot, %{signal_type: :war, pattern: :teruah_teruah}}
|
|
|
|
VavPipeline.Chatzotzrot.unsubscribe(:kohanim)
|
|
end
|
|
end
|
|
end
|