# `ConduitMcp.Client.Grants`
[🔗](https://github.com/nyo16/conduit_mcp/blob/v0.11.0/lib/conduit_mcp/client/grants.ex#L1)

"Always allow" approvals of a `ConduitMcp.Client` (PO-10, PO-11).

When `ConduitMcp.Client.Policy` decides `:ask` for a call, the client's
`:on_ask` approver is called (see `ConduitMcp.Client.Pipeline`). An answer
of `{:allow, :always}` records a grant keyed

    {principal, server_id, tool_name, fingerprint}

that answers the same question for `:grant_ttl` (default 24 hours)
without asking again:

  * `principal` is the call's `:principal` option (the end user the host
    acts for; `nil` when not given), so one user's grant never applies to
    another (PO-10). Without principals, grants are per client.
  * `fingerprint` is the tool's `ConduitMcp.Client.Fingerprint` when it
    was approved: a server that changes the tool's definition gets asked
    about again (PO-6).

A grant only settles an `:ask`. It never overrides a deny rule, and it
marks the tool's current fingerprint as approved for that principal, so
the policy's pin (`pin_tools`) and `allow_new_tools` checks treat the
tool as known.

Grants live in the client's governance table: `:protected` ETS owned by a
process under the client's supervisor, read directly by callers and
written only by that process. They are lost when the client restarts
(which only means asking again).

# `grant`

```elixir
@type grant() :: %{
  principal: term(),
  server_id: String.t(),
  tool: String.t(),
  fingerprint: String.t(),
  expires_at: integer()
}
```

One live grant.

# `clear`

```elixir
@spec clear(term()) :: :ok | {:error, ConduitMcp.Client.Error.t()}
```

Removes every grant.

# `list`

```elixir
@spec list(term()) :: {:ok, [grant()]} | {:error, ConduitMcp.Client.Error.t()}
```

The client's unexpired grants. `expires_at` is Unix time in milliseconds
(from the client's `:clock`).

# `revoke`

```elixir
@spec revoke(term(), term()) :: :ok | {:error, ConduitMcp.Client.Error.t()}
```

Removes every grant of `principal`.

---

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