defmodule VavPipeline.Tablet46MishmarTest do @moduledoc """ Tablet 46 (2026-10-06) โ€” no gate had a watch. Tamid ยง1.1 writes the pe'ah's limit in the spec; nothing enforced it, on any tier. Every admitted request spends manna; one caller could gather the whole omer. """ use ExUnit.Case, async: false import Plug.Test import Plug.Conn alias VavPipeline.BigdeiKodesh.{Mishmar, Router} @opts Router.init([]) setup do original = Application.get_env(:vav_pipeline, :rate_limits) Application.put_env(:vav_pipeline, :rate_limits, peah: [minute: 3, hour: 5], courtyard: [minute: 2, hour: 100], chatzer: [minute: 10_000, hour: 100_000] ) Mishmar.reset() on_exit(fn -> Application.put_env(:vav_pipeline, :rate_limits, original) Mishmar.reset() end) :ok end describe "Mishmar.knock/3" do test "counts the minute, then the hour, per subject; a refusal is not counted" do t = 1_000_000 * 60 assert {:ok, 2} = Mishmar.knock(:peah, "a", t) assert {:ok, 1} = Mishmar.knock(:peah, "a", t + 1) assert {:ok, 0} = Mishmar.knock(:peah, "a", t + 2) assert {:error, :minute, 57} = Mishmar.knock(:peah, "a", t + 3) assert {:error, :minute, 57} = Mishmar.knock(:peah, "a", t + 3) # Another subject is another count. assert {:ok, 2} = Mishmar.knock(:peah, "b", t + 3) # The next minute opens โ€” but the hour (5) is nearly spent: 3 so far. assert {:ok, 2} = Mishmar.knock(:peah, "a", t + 60) assert {:ok, 1} = Mishmar.knock(:peah, "a", t + 61) assert {:error, :hour, retry} = Mishmar.knock(:peah, "a", t + 62) assert retry == 3600 - rem(t + 62, 3600) # The next hour opens. assert {:ok, 2} = Mishmar.knock(:peah, "a", t + 3600) end test "tiers are counted apart" do t = 2_000_000 * 60 assert {:ok, 1} = Mishmar.knock(:courtyard, "k", t) assert {:ok, 0} = Mishmar.knock(:courtyard, "k", t) assert {:error, :minute, _} = Mishmar.knock(:courtyard, "k", t) assert {:ok, 2} = Mishmar.knock(:peah, "k", t) end test "the sweep drops closed windows and nothing else" do t = 3_000_000 * 60 assert {:ok, _} = Mishmar.knock(:peah, "old", t) assert {:ok, _} = Mishmar.knock(:peah, "new", t + 7200) :ok = Mishmar.sweep(Mishmar, t + 7200) # "old" has been forgotten entirely; "new" is still counted. assert :ets.info(Mishmar, :size) == 2 assert {:ok, 1} = Mishmar.knock(:peah, "new", t + 7200) end test "the table holds hashes, never the subject" do :ok = Mishmar.reset() {:ok, _} = Mishmar.knock(:peah, "203.0.113.7") for {{id, _, _}, _} <- :ets.tab2list(Mishmar) do assert is_binary(id) and byte_size(id) == 32 refute id =~ "203.0.113" end end end describe "at the router" do test "the pe'ah: the fourth knock from one address in a minute is 429 with Retry-After and the manna explanation" do statuses = for _ <- 1..4, do: ask({203, 0, 113, 9}).status assert Enum.take(statuses, 3) |> Enum.all?(&(&1 != 429)) conn = ask({203, 0, 113, 9}) assert conn.status == 429 [retry] = get_resp_header(conn, "retry-after") assert String.to_integer(retry) in 1..60 body = Jason.decode!(conn.resp_body) assert body["error"]["code"] == "RATE_LIMITED" assert body["error"]["guidance"]["manna"] =~ "Shemot 16:18" # Another address is not held back by this one. refute ask({203, 0, 113, 10}).status == 429 end test "the courtyard: per key, and only past the gate" do # A wrong key knocks all it likes and is never counted โ€” 401, not 429. for _ <- 1..5, do: assert(bedikah("Bearer wrong").status == 401) assert bedikah("Bearer test-token").status != 429 assert bedikah("Bearer test-token").status != 429 conn = bedikah("Bearer test-token") assert conn.status == 429 assert Jason.decode!(conn.resp_body)["error"]["guidance"]["issue"] =~ "courtyard allows 2 a minute" # The chatzer key is its own hand, even at the same door. refute bedikah("Bearer chatzer-test-token").status == 429 end end defp ask(ip) do %{conn(:post, "/peah/ask", Jason.encode!(%{question: "x"})) | remote_ip: ip} |> put_req_header("content-type", "application/json") |> Router.call(@opts) end defp bedikah(auth) do conn(:post, "/courtyard/bedikah", Jason.encode!(%{output: "", model: "gpt"})) |> put_req_header("content-type", "application/json") |> put_req_header("authorization", auth) |> Router.call(@opts) end end