defmodule MvWeb.JoinRateLimit do @moduledoc """ Rate limiting for the public join form (submit action). Uses Hammer with ETS backend. Key is derived from client IP so each IP is limited independently. Config from :mv :join_rate_limit (scale_ms, limit). """ use Hammer, backend: :ets @doc """ Checks if the given key (e.g. client IP) is within rate limit for join form submit. Returns: - `:allow` - submission allowed - `{:deny, _retry_after_ms}` - rate limit exceeded """ def check(key) when is_binary(key) do # Read at runtime so config can be changed without restart (e.g. in tests). config = Application.get_env(:mv, :join_rate_limit, []) scale_ms = Keyword.get(config, :scale_ms, 60_000) limit = Keyword.get(config, :limit, 10) case hit(key, scale_ms, limit) do {:allow, _count} -> :allow {:deny, retry_after} -> {:deny, retry_after} end end end