A source of facts about a request.
A signal reads the request (and, for behavioural signals, Limen's shared
state) and stores one or more named values in the Limen.Context. Policies
refer to those values by name with signal/1; the core knows nothing about
what they mean.
Every value a signal stores is copied into the Limen.Decision, together
with any evidence the signal attached with Limen.Context.put_signal/4, so
a decision can always be explained from its inputs.
Identity
The client address, its prefix and the JA4 fingerprint are resolved for
every request, before any other signal, because the pass cookie fast path
is bound to them. See Limen.Signal.ClientIP and Limen.Signal.JA4.
Built-in signals
| Module | Values |
|---|---|
Limen.Signal.HttpShape | :ua_family, :ua_name, :ua_version, :shape, :shape_flags |
Limen.Signal.Behaviour | :requests_per_minute, :not_found_ratio, :asset_ratio, ... |
Limen.Signal.Asn | :asn, :asn_kind, :asn_country, :asn_name |
Limen.Signal.Fcrdns | :fcrdns |
Writing a signal
defmodule MyApp.Signal.Tor do
@behaviour Limen.Signal
@impl true
def provides, do: [:tor_exit]
@impl true
def collect(ctx) do
exit? = Limen.Lists.member?(:tor_exits, ctx.client_ip)
Limen.Context.put_signal(ctx, :tor_exit, exit?)
end
endcollect/1 runs on the request path: it must not call processes or send
messages, and should cost at most a few microseconds.
Summary
Callbacks
Computes the signal's values and stores them in the context.
The names of the values this signal stores.
Functions
Runs signals in order over the context.
The built-in signals collected by default.
Resolves the client identity: address, prefix, JA4 and user agent.
Callbacks
@callback collect(Limen.Context.t()) :: Limen.Context.t()
Computes the signal's values and stores them in the context.
@callback provides() :: [atom()]
The names of the values this signal stores.
Functions
@spec collect(Limen.Context.t(), [module()]) :: Limen.Context.t()
Runs signals in order over the context.
@spec defaults() :: [module()]
The built-in signals collected by default.
@spec identify(Limen.Context.t(), Limen.Config.t()) :: Limen.Context.t()
Resolves the client identity: address, prefix, JA4 and user agent.
Also reads the sec-fetch-dest and cookie headers into the context, in
the same pass over the headers.