endpoint-libs 2.1.1

WebSocket RPC server and endpoint schema model, with MCP tool exposure and JSON Schema / OpenAPI / AsyncAPI generation. Shared runtime for services generated by endpoint-gen.
Documentation
# Migrating to endpoint-libs 2.0

2.0 makes the schema/handler/MCP machinery **transport-agnostic**: the same server core
now runs over TCP+TLS+WebSocket (unchanged) *and* over local transports — Unix sockets,
Windows named pipes, macOS XPC — implemented in a sibling crate.

**The wire protocols did not change.** Legacy `{method, seq, params}` frames and MCP
JSON-RPC are byte-identical to 1.9. Deployed frontends need no changes.

Most consumers touch two or three lines. The table below is exhaustive.

## Per-symbol changes

| 1.9 | 2.0 | Action |
|---|---|---|
| `WsMessage` (= `tungstenite::Message` when `ws` on) | `WireMessage` | Alias `WsMessage` still works **in type positions**. Method calls need changes — see below. |
| `WsConnection.address: SocketAddr` | `WsConnection.peer: PeerIdentity` | Use `.peer`. `conn.address()` exists, is `#[deprecated]`, and returns `127.0.0.1:0` for local peers. |
| `WsStream` (trait) | `MessageStream` | Alias `WsStream` still works. Rename at your convenience. |
| `RequestContext.ip_addr` | unchanged | Still present, still populated. Local peers report loopback. |
|| `RequestContext.peer`, `.extensions` | New fields. Only affects code constructing `RequestContext` by literal. |
| `Type`, `Field`, `EnumVariant`, `EndpointSchema`, `EndpointErrorSchema` | same, now `#[non_exhaustive]` | Out-of-crate `match` on `Type` or `Attestation` needs a `_ =>` arm. Construct via `::new()` + `with_*`, not struct literals. |
|| `Field.meta`, `EndpointSchema.meta` | New, empty. Reserved for the 2.1 OpenAPI/AsyncAPI emitters. |

### `WsMessage` method calls

The alias covers types, not tungstenite's inherent methods. Replacements:

| 1.9 (tungstenite method) | 2.0 |
|---|---|
| `msg.into_text()?` / `msg.to_text()?` | `msg.as_text()``Option<&str>` (also handles `Binary` UTF-8) |
| `msg.is_close()` | `msg.is_close()` — unchanged |
| `msg.into_data()` | `match msg { WireMessage::Binary(b) => b, .. }` |
| `Message::Text(s.into())` | `WireMessage::Text(s)` — takes `String` directly |

If you need tungstenite's type at a boundary, `From` impls convert both ways when the
`ws` feature is on.

### Logging

`?addr` on a `SocketAddr` becomes `%conn.peer` (compact `Display`, e.g.
`local(pid=42,xpc-codesign-requirement)`) or `conn.peer.display()`.

```rust
// 1.9
tracing::info!(ip = %conn.address, "connected");
// 2.0
tracing::info!(peer = %conn.peer, "connected");
```

## What's new (all additive)

- **`serve_connection(peer, states, stream, auth_protocol)`** — run auth + session for
  one already-established connection, over any transport.
- **`serve_with(listener)` + `SessionListener`** — accept loop over any listener.
- **`WsClient::from_stream(stream)`** — the client-side mirror.
- **`framed-transport` feature**`framed_json()`, length-delimited `WireMessage`
  framing over any byte stream. Format documented in
  `libs::ws::transport::framed`.
- **Hooks**`BeforeRequest`, `AfterRequest`, `OnConnect` via `add_*_hook`.
- **`PeerIdentity` / `Attestation`** — peer identity including verified code identity.
- **`Extensions`** — type-keyed map on connections and requests.

## Gotchas

1. **`MessageStream` is `?Send`.** `serve_connection`, `serve_with` and a
   `from_stream` client must run inside a `tokio::task::LocalSet`. `listen()` already
   does this internally; only the new entry points expose it.
2. **`serve_with` is single-runtime.** The shard-per-core model belongs to `listen()`
   and buys nothing for a 1:1 sidecar channel.
3. **`Extensions` values must be `Clone`.** `RequestContext` derives `Clone` and
   consumers rely on it, so the map stores `Clone` values (same trade
   `http::Extensions` makes).
4. **`cargo test --all-features` does not work in 2.0.** `ws` and `ws-wtx` are mutually
   exclusive by `compile_error!`. Use `cargo all-features test` (what CI runs) or an
   explicit feature list. Fixed in 2.1, which removes the `ws-wtx` backend.
5. **`ws-wtx` remains deprecated and non-building.** Untouched by 2.0; removed
   entirely in 2.1 (see CHANGELOG — it never compiled, so nothing can break).
6. **Handler naming**: `check_handler` requires the struct be named
   `Method<SchemaName>`. Unchanged, but easy to trip when adding endpoints.

## Known limitation

`WsClient::from_stream` lives behind the `ws-client` feature, which pulls
tokio-tungstenite and rustls. A sidecar that only speaks a local transport still
compiles those in. Splitting the client so `from_stream` is available from `ws-core`
alone is **additive and non-breaking**, and can land in a later release.

## Release order

`endpoint-libs`, `honey_id-types` and `endpoint-gen` must be released in a specific
order, and the six backends bump `endpoint-libs` and `honey_id-types` **together**.
See [`release-order.md`](release-order.md) — it explains the two-copies-in-one-graph
failure, gives the verification command, and covers pre-release pinning.

## endpointgen

endpointgen moves in lockstep. Bump to the matching 2.0 release; its
`ENDPOINT_LIBS_REQUIREMENT` check will fail loudly on a mismatch.