Limen.Decision (limen v0.2.1)

Copy Markdown View Source

The explainable record of a verdict.

Every request Limen evaluates produces exactly one decision. It carries the action, whether the action was enforced, the stage that produced it, every rule that matched together with the values it observed, the decide clause that picked the action with the values it observed, the facts the application stated about the request (see Limen.put_facts/2), and every signal collected for it. explain/1 renders it for humans.

Actions

  • :allow - the request continues.
  • :challenge - the client must solve a proof-of-work challenge (params.difficulty leading zero bits, from 1 to 32; 1 costs nothing and only shows that the client runs the challenge's script, see the tuning guide).
  • :throttle - 429 Too Many Requests (params.retry_after seconds).
  • :deny - 403 Forbidden; params.ban seconds, when set, also bans the client prefix.
  • :tarpit - nothing is sent for params.delay milliseconds, then 403 Forbidden. A tarpit never bans.
  • :maze - the client gets a slow, endless maze page (see Limen.Maze) instead of the application; params.ban seconds, when set, also flags the client prefix so every later request goes to the maze too.

Stages

The stage names the step of the pipeline that settled the decision: :off, :endpoint (a Limen challenge endpoint), :trap (a honeypot, see Limen.Trap), :trust (a policy's trust rule), :ban, :limit, :pass, :rule (an allow, deny or maze rule short-circuited), :decide (the score thresholds), or :socket (a WebSocket or LiveView connection check).

Summary

Functions

Renders a decision as human-readable lines.

Normalises the value returned by a policy's decide block into an action and its parameters.

Types

action()

@type action() :: :allow | :challenge | :throttle | :deny | :tarpit | :maze

mode()

@type mode() :: :dry_run | :enforce

stage()

@type stage() ::
  :off
  | :endpoint
  | :trap
  | :trust
  | :ban
  | :limit
  | :pass
  | :rule
  | :decide
  | :socket

t()

@type t() :: %Limen.Decision{
  action: action(),
  at: integer(),
  clause: String.t() | nil,
  clause_observed: [{String.t(), term()}],
  duration: non_neg_integer(),
  enforced: boolean(),
  errors: [term()],
  evidence: map(),
  facts: map(),
  identity: map(),
  instance: atom() | nil,
  matches: [Limen.Decision.Match.t()],
  method: String.t() | nil,
  mode: mode(),
  params: map(),
  path: String.t() | nil,
  policy: module() | nil,
  route: String.t() | nil,
  score: integer(),
  signals: map(),
  stage: stage()
}

Functions

explain(decision)

@spec explain(t()) :: String.t()

Renders a decision as human-readable lines.

normalize(other)

@spec normalize(term()) :: {action(), map()}

Normalises the value returned by a policy's decide block into an action and its parameters.