# `Ankusa.Audit.Context`
[🔗](https://github.com/jamescarr/ankusa/blob/ankusa-v0.7.0/packages/ankusa/lib/ankusa/audit/context.ex#L1)

Who is making a change, from where, and under which request: the part of an
audit row (`Ankusa.Audit`) that the mutation itself does not know.

Mounted as a plug behind `Ankusa.Admin.Auth` on the admin and route-management
APIs, it builds the context from the authenticated `Ankusa.Principal`
(`actor`), `Ankusa.Net.ClientIP` (`remote_ip`, with `routes.trusted_proxies`
deciding whose `X-Forwarded-For` is believed) and the caller's `X-Request-Id`
(a fresh UUIDv7 when absent or not a plain token), and answers the request id
in the `x-request-id` response header. A change made from code, with no
request, is `system/0`.

# `t`

```elixir
@type t() :: %Ankusa.Audit.Context{
  actor: String.t(),
  remote_ip: String.t() | nil,
  request_id: String.t() | nil
}
```

# `from_conn`

```elixir
@spec from_conn(Plug.Conn.t()) :: t()
```

The context carried by `conn`, `system/0` when the plug did not run.

# `from_opts`

```elixir
@spec from_opts(keyword()) :: t()
```

The context in `opts[:audit]`, `system/0` when the caller gave none.

# `system`

```elixir
@spec system() :: t()
```

The context of a change that no request made.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
