ryu-hardware 0.1.7

Ryu Hardware Protocol (RHP v1) node backend — an extracted Core capability crate: the paired-device registry (SQLite store + revocable per-device tokens), pairing nonce verification, the Opus/WAV codec edge, the per-connection realtime session state machine (audio buffering + ambient meeting bridge), the live device-sender registry, the display-nudge loop, and the device-registry + TRMNL display HTTP surface. In-process default; Core consumes it as a NON-optional path dependency (the codec is also used by the voice module, the store backs ServerState in every build). The public ws/pair ingress route + the chat-turn orchestration (welded to Core's run_text_turn/voice/TTS session loop) stay Core-side as consumers of this crate's types.
Documentation
# ryu-hardware

Ryu Hardware Protocol (RHP v1) node backend — an extracted **Core capability crate**.
It is the node half of the protocol in `apps/hardware/PROTOCOL.md`: Ryu devices
(watch / necklace / desk, all ESP32-S3) talk to a node over a WebSocket, either
directly over WiFi (Mode B) or tunneled through the mobile app over BLE (Mode A,
transparent to the node).

## Role in the decomposition

A primitive lifted out of `apps/core`. It owns the paired-device registry, token
lifecycle, the audio codec edge, the per-connection realtime session state machine,
the display-nudge loop, and the device-registry + TRMNL display HTTP surface. The crate
has **zero dependency on `apps/core`** (it depends only on the `ryu-dashboards` and
`ryu-meetings` app-store backends for the display + ambient-meeting bridges).

## Layout / key modules

- `protocol` — serde structs/enums mirroring PROTOCOL.md §3 (the wire contract shared
  by the firmware and mobile relay).
- `store` — device registry (SQLite): paired devices, per-device revocable Bearer
  tokens, last-seen/battery presence. `DeviceStore`, `DeviceRecord`, `hash_token`.
- `pairing` — pairing-nonce verification and token issuance.
- `codec` — the Opus/WAV codec edge, so the rest of Core sees PCM/WAV.
- `session` — the realtime session state machine (audio buffering + ambient meetings
  bridge), the live device-sender registry, `HardwareSession`, `TurnInput`,
  `SessionOutput`.
- `nudge` — the live display-nudge loop (dashboard change → device re-poll).
- `api` — device-registry CRUD (`/`, `/:device_id`) + TRMNL display
  (`/:device_id`, `/:device_id/image`) axum router.

## What stays Core-side (consumers of this crate's types)

The **public ws/pair ingress route** (a per-device Bearer/nonce that the global
`RYU_TOKEN` `require_auth` cannot gate, plus mesh/SSRF-guarded node-URL resolution) and
the **chat-turn orchestration** (welded to Core's `run_text_turn` / voice ASR / TTS
session loop) stay in `apps/core` and consume this crate's `session`/`protocol` types.

## Placement (Core vs Gateway)

The device registry, token lifecycle, and realtime session decide *what runs* → Core.

## Consumed as

Compiled-into-core crate (non-optional path dependency): the codec is reused by the
voice module and the store backs `ServerState` in every build.