# `Raxol.AgentClientProtocol.Ext.AttachPolicy.Grant`
[🔗](https://github.com/DROOdotFOO/raxol-agent/blob/raxol_agent_client_protocol-v0.1.0/packages/raxol_agent_client_protocol/lib/raxol/agent_client_protocol/ext/attach_policy.ex#L1)

A successful attach grant.

The value the bus records at registration. `%Grant{}` is the ONLY structural
shape the `Runner` (the fail-closed funnel) admits — a policy cannot "mostly"
grant. The Runner enforces well-formedness:

  * `actor` — a map carrying a **binary `"id"`** (audit identity, never
    empty). For a token grant this is the token's `act` claim; for LocalNode a
    synthesized local identity.
  * `scope` — an atom in the Runner's allow-list (`[:attach]`).
  * `session_id` — binary, MUST `==` `ctx.session_id` (the Runner denies a
    mismatch).
  * `via` — non-nil provenance for audit (`:local_node | {:token, kid}`).
  * `expires_at` — token `exp` (unix seconds) or nil. Consumed by
    `Ext.Reattach`'s mid-attach expiry timer: a held live tail is force-closed
    at `expires_at`.
  * `lens` — RESERVED: a grow-only redaction transform threaded opaquely by
    the bus, NEVER interpreted. Always nil.

# `t`

```elixir
@type t() :: %Raxol.AgentClientProtocol.Ext.AttachPolicy.Grant{
  actor: map(),
  expires_at: integer() | nil,
  lens: term() | nil,
  scope: atom(),
  session_id: String.t(),
  via: :local_node | {:token, String.t()} | term()
}
```

---

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