Files
bikoret/vav_pipeline/test/halt_monitor_test.exs
T
Scott KarpandClaude Opus 4.6 fe93c11d13 Phase 5 deployment: Dockerfiles, K8s manifests, halt monitor (Steps 33, 36)
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>
2026-03-22 07:11:02 -04:00

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