Files
bikoret/vav_pipeline/lib/vav_pipeline/application.ex
T
Scott KarpandClaude Opus 4.6 d6fe069a79 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

83 lines
2.8 KiB
Elixir

defmodule VavPipeline.Application do
@moduledoc """
OTP Application for the Vav Pipeline.
Starts the supervision tree with:
- Repo (L3 PostgreSQL — oral tradition persistence)
- Chatzotzrot (silver trumpets — signal system)
- AreiMiklat (cities of refuge — protection protocol)
- EglahArufah (accountability for unknown harm)
- Bikurim (first fruits — release protocol)
- MannaLedger (consumption tracking and anti-hoarding enforcement)
- HaltMonitor (esh tamid — cardinal sin detection)
- ShabbatTimer (mandatory cessation monitor)
- ShoreshEnginePort (Erlang Port to Haskell engine, if binary found)
- TalmudicEngineSocket (Unix socket to Prolog engine)
Step 14 (Architecture §4): Component connections supervised.
The port and socket are optional — the pipeline degrades gracefully
if external engines are not available (clients fall back to stubs).
"""
use Application
require Logger
@impl true
def start(_type, _args) do
shoresh_binary = Application.get_env(:vav_pipeline, :shoresh_engine_binary, "shoresh-engine")
shoresh_cwd = Application.get_env(:vav_pipeline, :shoresh_engine_cwd, nil)
talmudic_socket = Application.get_env(:vav_pipeline, :talmudic_socket_path, "/tmp/shorashim/talmudic.sock")
children =
[
{VavPipeline.Chatzotzrot, []},
{VavPipeline.AreiMiklat, []},
{VavPipeline.EglahArufah, []},
{VavPipeline.Bikurim, []},
{VavPipeline.MannaLedger, []},
{VavPipeline.HaltMonitor, []},
{VavPipeline.ShabbatTimer, []}
]
|> maybe_add_repo()
|> maybe_add_shoresh_port(shoresh_binary, shoresh_cwd)
|> maybe_add_talmudic_socket(talmudic_socket)
opts = [strategy: :one_for_one, name: VavPipeline.Supervisor]
Supervisor.start_link(children, opts)
end
defp maybe_add_repo(children) do
repo_config = Application.get_env(:vav_pipeline, VavPipeline.Repo)
cond do
is_nil(repo_config) ->
Logger.warning("VavPipeline.Repo: no config found — running without L3 persistence")
children
repo_config[:start] == false ->
Logger.info("VavPipeline.Repo: start disabled — running without L3 persistence")
children
true ->
[VavPipeline.Repo | children]
end
end
defp maybe_add_shoresh_port(children, binary, cwd) do
case System.find_executable(binary) do
nil ->
Logger.warning("ShoreshEnginePort: binary '#{binary}' not in PATH — running without Haskell engine")
children
path ->
children ++ [{VavPipeline.ShoreshEnginePort, [binary: path, cwd: cwd]}]
end
end
defp maybe_add_talmudic_socket(children, socket_path) do
# Always add the socket client — it connects lazily on first request
children ++ [{VavPipeline.TalmudicEngineSocket, [socket_path: socket_path]}]
end
end