Skip to content

[P1] No RELAY Rust binding at all: missing relay dependency, to_message()/from_message(), RELAY_SPEC_VERSION, and serde derives on canonical types (§18.3) #6

Description

@SoundMatt

What's wrong

rust-RCP has no dependency on any shared relay/relay-rs crate (Cargo.toml:19-27 dependency list: thiserror, parking_lot, serde, serde_json, serde_yaml only), and consequently:

  • No to_message()/from_message() conversions between Command/Response/Status and a canonical relay::Message exist anywhere (grep -rn "relay::Message|to_message|from_message" src/ outside adapt.rs's unrelated generic trait returns nothing).
  • The spec-version constant is named SPEC_VERSION (src/lib.rs:120) rather than RELAY_SPEC_VERSION, which §18.3 states "MUST be exported from the crate root" and §19.4 gives verbatim as pub const RELAY_SPEC_VERSION: &str = "1.11";.
  • The canonical types Command, Response, Status (src/lib.rs, #[derive(Debug, Clone, Default, PartialEq)]) and Zone/Priority/CommandType/ResponseStatus derive no Serialize/Deserialize at all, contradicting §18.3: "All canonical types MUST derive Clone, Debug, and serde Serialize/Deserialize with the field names from the §15 JSON tags."
  • Zone/Priority/CommandType/ResponseStatus are hand-rolled tuple structs (pub struct Zone(pub u8)) rather than the #[repr(u8)] enum shapes the spec gives verbatim in §18.3's "Core types (Rust)" block.

This is not a whole-ecosystem gap — it's a regression relative to this org's own sibling crate. rust-CAN (same org, same language) already has all of this:

$ gh api repos/SoundMatt/rust-CAN/contents/src/lib.rs --jq .content | base64 -d | grep -n "SPEC_VERSION|fn adapt|to_message"
62:pub use adapt::{adapt, from_message, to_message};
75:pub const SPEC_VERSION: &str = "1.10";
77:/// Alias for `SPEC_VERSION` for explicitness in CLI contexts.
78:pub const RELAY_SPEC_VERSION: &str = "1.10";

rust-CAN also has a real src/adapt.rs, src/relay.rs, and a src/mock submodule wired into the canonical conversion path — none of which rust-RCP has.

Expected per spec

§18.3 in full: crate-root RELAY_SPEC_VERSION, canonical types deriving Serialize/Deserialize per the §15.5 JSON field names, and to_message()/from_message() conversions using the shared relay::Message envelope.

Suggested fix

Adopt rust-CAN's pattern: add a relay-equivalent dependency (or vendor the minimal relay::Message/Error types until relay-rs is published), add RELAY_SPEC_VERSION alongside SPEC_VERSION, derive Serialize/Deserialize on Command/Response/Status/Zone/Priority/CommandType/ResponseStatus with the §15.5 JSON tag names, and implement real to_message()/from_message() + Adapt() (which then legitimately flips "adapt" to true, see the companion P0 finding).


Filed from the RELAY ecosystem audit (2026-07-27), category: spec-conformance, severity: P1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions