# `AttestoMCP.Server.UrlElicitation`
[🔗](https://github.com/XukuLLC/attesto_mcp_server/blob/v2.8.0/lib/attesto_mcp_server/url_elicitation.ex#L1)

Helpers for staging, resolving, and consuming URL elicitation approval records.

A link with `mode: "url"` must carry the operation the human is approving by
its opaque staged-record ID rather than as a bare route. The staged record is
bound to the calling subject hash, contains the exact fields that the action
will execute with, is single-use with a short TTL, renders an explicit dead
end when expired, consumed, or foreign, and is periodically swept.

The raw principal binding is never persisted in the store; only its
deterministic SHA-256 digest is stored.

# `handler_context`

```elixir
@type handler_context() :: map()
```

# `resolve_result`

```elixir
@type resolve_result() ::
  {:ok, staged_content()}
  | {:error, :not_found | :foreign | :consumed | :expired | :store_unavailable}
```

# `server`

```elixir
@type server() :: pid() | atom()
```

# `stage_error`

```elixir
@type stage_error() ::
  {:error,
   :principal_binding_required
   | :invalid_action
   | :invalid_fields
   | :invalid_ttl
   | :store_unavailable}
```

# `stage_result`

```elixir
@type stage_result() :: {:ok, %{id: String.t(), expires_at_ms: non_neg_integer()}}
```

# `staged_content`

```elixir
@type staged_content() :: %{
  action: String.t(),
  fields: map(),
  expires_at_ms: non_neg_integer()
}
```

# `consume_url_elicitation`

```elixir
@spec consume_url_elicitation(server(), String.t(), term()) :: resolve_result()
```

Atomically consumes a staged URL elicitation record upon confirmation.

Can be consumed at most once. Returns `{:error, :foreign}` if the subject
does not match, `{:error, :consumed}` if already consumed, and `{:error, :expired}`
if expired. Malformed or unknown IDs return `{:error, :not_found}`.

# `resolve_url_elicitation`

```elixir
@spec resolve_url_elicitation(server(), String.t(), term()) :: resolve_result()
```

Resolves a staged URL elicitation record for display on an approval page.

Returns `{:error, :foreign}` if the principal binding does not match the
staged subject hash before revealing any action or field content. Returns
`{:error, :consumed}` if already consumed, or `{:error, :expired}` if expired.
Malformed or unknown IDs return `{:error, :not_found}`.

# `stage_url_elicitation`

```elixir
@spec stage_url_elicitation(server(), handler_context(), String.t(), map(), keyword()) ::
  stage_result() | stage_error()
```

Stages a URL elicitation record before returning an interactive `mode: "url"` request.

The context must contain a non-nil `:principal_binding`. The action must be a
non-empty string of at most 256 bytes. Fields must be a JSON object within the
server's `max_json_bytes` budget.

# `subject_hash`

```elixir
@spec subject_hash(term()) :: String.t()
```

Computes the deterministic SHA-256 hex digest for a principal binding.

Only this hash is stored by the URL elicitation store; the raw binding is
never persisted in the store record.

---

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