# `Raxol.AgentClientProtocol.Ext.AttachPolicy`
[🔗](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#L41)

Fail-closed attach admission behaviour.

An attach grants **read access to a session's full durable record stream** —
history from an offset plus the live tail (one decision gates both).
Records carry prompts, tool output, file contents; admission is security-core.

A policy module implements `authorize_attach/1`. It is **never trusted to be
well-behaved**: every invocation is wrapped by
`Raxol.AgentClientProtocol.Ext.AttachPolicy.Runner` (the SOLE funnel),
which isolates it in a `Task.Supervisor.async_nolink` task with a bounded
`Task.yield` + `Task.shutdown(:brutal_kill)`, so a hostile policy can neither
block nor crash the bus, and every non-`{:ok, %Grant{}}` outcome denies.

## ctx (attach context)

`transport` is a REQUIRED key (its value MAY be nil). It is sourced ONLY from
Connection-side knowledge, NEVER from a peer-asserted field — a peer does not
get to claim `kind: :process`. `LocalNode` (the default) consults it and denies
a nil transport; `Token` ignores it.

## The default policy

Unconfigured ⇒ `LocalNode` (deny-by-default). There is **no `AllowAll` module**
in this package — the absent module is the guarantee.

# `ctx`

```elixir
@type ctx() :: %{
  session_id: String.t(),
  actor: map() | nil,
  surface: atom(),
  capability: binary() | nil,
  from_offset: non_neg_integer(),
  transport: %{kind: atom(), peer: term()} | nil
}
```

Attach context. A grow-only map — a policy MUST tolerate unknown keys
and pattern-match only what it needs.

# `authorize_attach`

```elixir
@callback authorize_attach(ctx()) ::
  {:ok, Raxol.AgentClientProtocol.Ext.AttachPolicy.Grant.t()}
  | {:error, reason :: term()}
```

Authorize an attach. A **plain, pure-ish** function on the policy module,
wrapped by the Runner. MUST return a well-formed `%Grant{}` inside `{:ok, _}`
to admit; anything else (incl. `{:error, _}`, a raise, a hang) denies.

# `default_policy`

```elixir
@spec default_policy() :: module()
```

The configured attach policy, or `LocalNode` when unconfigured. Never an
allow-all.

---

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