# `Portals.Handshake`
[🔗](https://github.com/Ziinc/portals/blob/v0.1.0/lib/portals/handshake.ex#L1)

Exact-version handshake rules shared by every SDK.

Wire shape:

    HELLO = [tag=1, protocol_version, runtime, max_concurrency, max_streams, features]
    READY = [tag=2, protocol_version, limits]

The worker sends `HELLO` first; the BEAM replies with `READY` only when
`protocol_version` matches `Portals.Protocol.version/0` exactly. Any
mismatch is a deterministic, unrecoverable startup failure: the
connection is closed and the worker is not marked ready.

# `build_hello`

```elixir
@spec build_hello(binary(), pos_integer(), pos_integer(), [binary()]) :: list()
```

# `build_ready`

```elixir
@spec build_ready(Portals.Protocol.limits()) :: list()
```

# `negotiate`

```elixir
@spec negotiate([term()]) ::
  {:ok, Portals.Handshake.Hello.t()}
  | {:error, {:protocol_version_mismatch, pos_integer(), term()}}
  | {:error, term()}
```

Validate a decoded HELLO envelope against the BEAM's own protocol version.

Returns `{:ok, %Hello{}}` only on an exact version match. Any mismatch
returns `{:error, {:protocol_version_mismatch, expected, actual}}` and
callers must close the connection without sending `READY`.

---

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