Everything Limen knows about a request while it is being evaluated.
A context is built once per request by Limen.Plug, for one
Limen.Instance, which it carries so that everything downstream reads its
configuration and state without looking anything up. Identity fields
(client_ip, prefix, ja4, user_agent) are always populated; the
signals map is filled by the Limen.Signal modules a policy depends on.
Limen.Signal.identify/2 reads the identity headers in one pass over the
request headers, and with them the ones later stages need: fetch_dest
(the sec-fetch-dest
header) and cookie_headers (the values of the cookie headers, in
order, unparsed).
via_proxy tells whether client_ip came from a forwarding header set by
a trusted proxy (see Limen.Signal.ClientIP); a request from a trusted
proxy that carried no such header is the proxy's own.
mode, when set, is the request's own mode, overriding every other (see
Limen.Test.put_mode/2, which sets the :limen_mode private connection
field); it is nil otherwise.
facts are what the application knows about the request and Limen
cannot, such as whether the client is signed in. The application states
them with Limen.put_facts/2 before Limen.Plug runs (or with
Limen.LiveView.put_facts/2 and the :facts option of
Limen.Socket.check/3 for sockets), and policies read them with
fact/1.
Every signal value and fact that ends up in a context is copied into the
Limen.Decision record, so a decision can always be explained from the
values that produced it.
Summary
Functions
Returns the fact key the application stated, or nil.
Builds a context for instance from a Plug.Conn, without resolving
identity.
Returns the first value of the request header name, or nil.
The identity of the client, as recorded in decisions and bound into tokens.
Stores a signal value and, optionally, the evidence that produced it.
Stores several signal values at once, with evidence for some of them.
Returns the value of signal key, or nil when it was not collected.
Types
@type prefix() :: Limen.IP.prefix()
@type t() :: %Limen.Context{ client_ip: :inet.ip_address() | nil, cookie_headers: [String.t()], evidence: %{optional(atom()) => term()}, facts: %{optional(atom()) => term()}, fetch_dest: String.t() | nil, headers: [{String.t(), String.t()}], host: String.t(), instance: Limen.Instance.t() | nil, ja4: String.t() | nil, method: String.t(), mode: :dry_run | :enforce | nil, monotonic: integer(), now: integer(), path: String.t(), peer_ip: :inet.ip_address() | nil, prefix: prefix() | nil, query: String.t(), rates: %{optional(term()) => non_neg_integer() | tuple()}, scheme: :http | :https, signals: %{optional(atom()) => term()}, user_agent: String.t() | nil, via_proxy: boolean() }
Functions
Returns the fact key the application stated, or nil.
@spec from_conn(Plug.Conn.t(), Limen.Instance.t() | nil) :: t()
Builds a context for instance from a Plug.Conn, without resolving
identity.
now is the system time in milliseconds, used for time windows and token
expiry; monotonic is monotonic time in microseconds, used for limits.
Tests can pin both with the :limen_now and :limen_monotonic private
connection fields, and its mode with :limen_mode. Facts come from
Limen.put_facts/2.
Returns the first value of the request header name, or nil.
name must be lowercase, as Plug normalises header names.
The identity of the client, as recorded in decisions and bound into tokens.
Stores a signal value and, optionally, the evidence that produced it.
Stores several signal values at once, with evidence for some of them.
Equivalent to calling put_signal/4 for each value, in one update of the
context.
Returns the value of signal key, or nil when it was not collected.