P0 — implement ZARA/1 ZeroMQ ROUTER/DEALER protocol and daemon client SDK #129

Closed
opened 2026-08-21 23:40:40 +00:00 by lost-rob0t · 1 comment
lost-rob0t commented 2026-08-21 23:40:40 +00:00 (Migrated from github.com)

Parent epic: #127
Depends on: #128
Research: docs/research/001-daemon-zeromq-voice-service.md

Goal

Implement the first versioned Zara application protocol over ZeroMQ and a reusable client library that maps onto the existing runtime command/event boundary.

Permanent executable boundary:

  • zara remains the client-facing executable;
  • zara-server is the long-lived daemon/service executable;
  • do not reintroduce zara --daemon as the canonical service interface.

Transport

  • daemon/server: ROUTER
  • client: DEALER
  • keep the existing Pet PUB/SUB bridge as a compatibility adapter only
  • no REQ/REP lock-step protocol for live assistant traffic

v1 application frame

DEALER sends:

Frame 0: b"ZARA/1"
Frame 1: UTF-8 JSON envelope
Frame 2+: optional opaque binary payload frames

ROUTER receives its transport-owned routing id before those frames. Never serialize or trust the ROUTER routing id as the authenticated user identity.

Envelope

Define and validate a closed schema containing at least:

  • type
  • id
  • reply_to where applicable
  • session_id
  • conversation_id where applicable
  • canonical Zara turn_id where applicable
  • stream_id where applicable
  • seq
  • timestamp_ns
  • trace_id where applicable
  • content_type for binary media
  • payload_count
  • bounded flags/extensions

No pickle, Python class paths, arbitrary import names, or provider-specific response objects may cross the wire.

Handshake

Implement hello / hello.ok negotiation for:

  • supported/selected protocol version;
  • client/server version metadata;
  • codec capabilities;
  • payload/message limits;
  • session id;
  • heartbeat/liveness settings;
  • optional resume capability.

Unknown major versions fail closed. Unknown message types return a typed protocol error and are never dynamically dispatched.

Initial command/event vocabulary

At minimum implement text/runtime flow:

  • conversation.open
  • turn.submit
  • turn.cancel
  • runtime.status
  • turn.started
  • assistant text/result events available from the current runtime
  • turn.completed
  • turn.cancelled
  • runtime.error
  • ping/pong

Reserve/validate the documented audio message names but do not require full voice streaming in this slice.

Reliability and bounds

  • bounded SNDHWM/RCVHWM;
  • bounded JSON envelope and payload frame sizes;
  • MAXMSGSIZE;
  • connect/send/receive timeouts;
  • heartbeat settings;
  • ROUTER_MANDATORY where appropriate;
  • strict frame counts and payload_count validation;
  • stable request ids and explicit reply correlation;
  • side-effect retry semantics documented as idempotency-based rather than relying on socket delivery alone;
  • per-route outbound pressure so one stalled route cannot evict or starve a healthy route.

Client SDK

Add one reusable client abstraction consumed later by CLI and desktop:

  • connect/disconnect;
  • handshake;
  • request correlation;
  • async/non-blocking event stream;
  • reconnect with bounded behavior;
  • cancellation;
  • conversation/session selection;
  • protocol errors as typed Zara errors;
  • sanitized diagnostics.

Do not implement separate desktop and CLI protocol clients.

Tests

  • golden frame fixtures;
  • ROUTER/DEALER localhost/inproc integration;
  • protocol version mismatch;
  • unknown message type;
  • malformed JSON;
  • extra/missing payload frames;
  • oversized envelope/payload;
  • ordering/correlation;
  • reconnect and daemon restart;
  • HWM/backpressure behavior;
  • slow client does not block another client;
  • cancellation maps to canonical turn id;
  • no user identity is accepted from transport routing id or arbitrary envelope metadata;
  • zara-server lifecycle owns the gateway and defaults to owner-private local IPC;
  • focused non-interactive script plus full repo/Nix gate.

Acceptance

A test client can connect to zara-server, negotiate ZARA/1, submit/cancel a normal Zara turn, query runtime status, and consume typed runtime events without owning an assistant runtime itself.

Parent epic: #127 Depends on: #128 Research: `docs/research/001-daemon-zeromq-voice-service.md` ## Goal Implement the first versioned Zara application protocol over ZeroMQ and a reusable client library that maps onto the existing runtime command/event boundary. Permanent executable boundary: - `zara` remains the client-facing executable; - `zara-server` is the long-lived daemon/service executable; - do not reintroduce `zara --daemon` as the canonical service interface. ## Transport - daemon/server: ROUTER - client: DEALER - keep the existing Pet PUB/SUB bridge as a compatibility adapter only - no REQ/REP lock-step protocol for live assistant traffic ## v1 application frame DEALER sends: ```text Frame 0: b"ZARA/1" Frame 1: UTF-8 JSON envelope Frame 2+: optional opaque binary payload frames ``` ROUTER receives its transport-owned routing id before those frames. Never serialize or trust the ROUTER routing id as the authenticated user identity. ## Envelope Define and validate a closed schema containing at least: - `type` - `id` - `reply_to` where applicable - `session_id` - `conversation_id` where applicable - canonical Zara `turn_id` where applicable - `stream_id` where applicable - `seq` - `timestamp_ns` - `trace_id` where applicable - `content_type` for binary media - `payload_count` - bounded flags/extensions No pickle, Python class paths, arbitrary import names, or provider-specific response objects may cross the wire. ## Handshake Implement `hello` / `hello.ok` negotiation for: - supported/selected protocol version; - client/server version metadata; - codec capabilities; - payload/message limits; - session id; - heartbeat/liveness settings; - optional resume capability. Unknown major versions fail closed. Unknown message types return a typed protocol error and are never dynamically dispatched. ## Initial command/event vocabulary At minimum implement text/runtime flow: - `conversation.open` - `turn.submit` - `turn.cancel` - `runtime.status` - `turn.started` - assistant text/result events available from the current runtime - `turn.completed` - `turn.cancelled` - `runtime.error` - `ping`/`pong` Reserve/validate the documented audio message names but do not require full voice streaming in this slice. ## Reliability and bounds - bounded SNDHWM/RCVHWM; - bounded JSON envelope and payload frame sizes; - `MAXMSGSIZE`; - connect/send/receive timeouts; - heartbeat settings; - `ROUTER_MANDATORY` where appropriate; - strict frame counts and payload_count validation; - stable request ids and explicit reply correlation; - side-effect retry semantics documented as idempotency-based rather than relying on socket delivery alone; - per-route outbound pressure so one stalled route cannot evict or starve a healthy route. ## Client SDK Add one reusable client abstraction consumed later by CLI and desktop: - connect/disconnect; - handshake; - request correlation; - async/non-blocking event stream; - reconnect with bounded behavior; - cancellation; - conversation/session selection; - protocol errors as typed Zara errors; - sanitized diagnostics. Do not implement separate desktop and CLI protocol clients. ## Tests - golden frame fixtures; - ROUTER/DEALER localhost/inproc integration; - protocol version mismatch; - unknown message type; - malformed JSON; - extra/missing payload frames; - oversized envelope/payload; - ordering/correlation; - reconnect and daemon restart; - HWM/backpressure behavior; - slow client does not block another client; - cancellation maps to canonical turn id; - no user identity is accepted from transport routing id or arbitrary envelope metadata; - `zara-server` lifecycle owns the gateway and defaults to owner-private local IPC; - focused non-interactive script plus full repo/Nix gate. ## Acceptance A test client can connect to `zara-server`, negotiate `ZARA/1`, submit/cancel a normal Zara turn, query runtime status, and consume typed runtime events without owning an assistant runtime itself.
lost-rob0t commented 2026-08-22 12:26:24 +00:00 (Migrated from github.com)

RAGE Iteration 2 complete.

Merged PR #142 as 1cae2e32cc40112aa13af6b8f4b7319869c72bd9.

Final merge authority was exact head 3ab7d04c6af2e62f00570fb9ebdc731c4eb075c0, CI #284 / run 32572470202:

  • complete scripts/test-all.sh: PASS
  • nix flake check: PASS
  • packaged nix build: PASS
  • Arch Linux shared-mic: PASS
  • Ubuntu 24.04 shared-mic: PASS
  • PR mergeable, no unresolved review threads

Delivered the versioned ZARA/1 framing/validation, ROUTER/DEALER transport, reusable ZmqZaraClient, runtime command/event adapters, request correlation, reconnect/idempotency, bounded backpressure/fairness, and local-owner zara-server IPC integration. Authentication and hard multi-user isolation remain owned by #130/#131.

RAGE Iteration 2 complete. Merged PR #142 as `1cae2e32cc40112aa13af6b8f4b7319869c72bd9`. Final merge authority was exact head `3ab7d04c6af2e62f00570fb9ebdc731c4eb075c0`, CI #284 / run `32572470202`: - complete `scripts/test-all.sh`: PASS - `nix flake check`: PASS - packaged `nix build`: PASS - Arch Linux shared-mic: PASS - Ubuntu 24.04 shared-mic: PASS - PR mergeable, no unresolved review threads Delivered the versioned `ZARA/1` framing/validation, ROUTER/DEALER transport, reusable `ZmqZaraClient`, runtime command/event adapters, request correlation, reconnect/idempotency, bounded backpressure/fairness, and local-owner `zara-server` IPC integration. Authentication and hard multi-user isolation remain owned by #130/#131.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/zara#129
No description provided.