From 4ac62d99e01ca0e3f1bd35d7f9703434b20e146e Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Mon, 25 May 2026 06:27:23 +0400 Subject: [PATCH] =?UTF-8?q?fix(audit):=20M1=20=E2=80=94=20add=20version:?= =?UTF-8?q?=20u8=20to=20all=20SignalMessage=20variants?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert Hold/Unhold/Mute/Unmute/TransferAck from unit variants to struct variants with `version: u8` (serde default = 2). Every SignalMessage variant now carries a version field, enabling future semantic versioning and clean rejection of deprecated variants during federation routing. 305 tests passing. Co-Authored-By: Claude Sonnet 4.6 --- crates/wzp-client/src/featherchat.rs | 18 +++++------ crates/wzp-proto/src/packet.rs | 47 ++++++++++++++++++---------- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/crates/wzp-client/src/featherchat.rs b/crates/wzp-client/src/featherchat.rs index 17d1d68..d86d313 100644 --- a/crates/wzp-client/src/featherchat.rs +++ b/crates/wzp-client/src/featherchat.rs @@ -99,12 +99,12 @@ pub fn signal_to_call_type(signal: &SignalMessage) -> CallSignalType { SignalMessage::LossRecoveryUpdate { .. } => CallSignalType::Offer, // reuse (telemetry) SignalMessage::Ping { .. } | SignalMessage::Pong { .. } => CallSignalType::Offer, SignalMessage::AuthToken { .. } => CallSignalType::Offer, - SignalMessage::Hold => CallSignalType::Hold, - SignalMessage::Unhold => CallSignalType::Unhold, - SignalMessage::Mute => CallSignalType::Mute, - SignalMessage::Unmute => CallSignalType::Unmute, + SignalMessage::Hold { .. } => CallSignalType::Hold, + SignalMessage::Unhold { .. } => CallSignalType::Unhold, + SignalMessage::Mute { .. } => CallSignalType::Mute, + SignalMessage::Unmute { .. } => CallSignalType::Unmute, SignalMessage::Transfer { .. } => CallSignalType::Transfer, - SignalMessage::TransferAck => CallSignalType::Offer, // reuse + SignalMessage::TransferAck { .. } => CallSignalType::Offer, // reuse SignalMessage::PresenceUpdate { .. } => CallSignalType::Offer, // reuse SignalMessage::RouteQuery { .. } => CallSignalType::Offer, // reuse SignalMessage::TransportFeedback { .. } => CallSignalType::Offer, // reuse (BWE) @@ -199,19 +199,19 @@ mod tests { )); assert!(matches!( - signal_to_call_type(&SignalMessage::Hold), + signal_to_call_type(&SignalMessage::Hold { version: default_signal_version() }), CallSignalType::Hold )); assert!(matches!( - signal_to_call_type(&SignalMessage::Unhold), + signal_to_call_type(&SignalMessage::Unhold { version: default_signal_version() }), CallSignalType::Unhold )); assert!(matches!( - signal_to_call_type(&SignalMessage::Mute), + signal_to_call_type(&SignalMessage::Mute { version: default_signal_version() }), CallSignalType::Mute )); assert!(matches!( - signal_to_call_type(&SignalMessage::Unmute), + signal_to_call_type(&SignalMessage::Unmute { version: default_signal_version() }), CallSignalType::Unmute )); diff --git a/crates/wzp-proto/src/packet.rs b/crates/wzp-proto/src/packet.rs index d6d7e27..37c1595 100644 --- a/crates/wzp-proto/src/packet.rs +++ b/crates/wzp-proto/src/packet.rs @@ -669,13 +669,25 @@ pub enum SignalMessage { }, /// Put the call on hold (stop sending media, keep session alive). - Hold, + Hold { + #[serde(default = "default_signal_version")] + version: u8, + }, /// Resume a held call. - Unhold, + Unhold { + #[serde(default = "default_signal_version")] + version: u8, + }, /// Mute request from the remote side (server-initiated mute, like IAX2 QUELCH). - Mute, + Mute { + #[serde(default = "default_signal_version")] + version: u8, + }, /// Unmute request from the remote side (like IAX2 UNQUELCH). - Unmute, + Unmute { + #[serde(default = "default_signal_version")] + version: u8, + }, /// Transfer the call to another peer. Transfer { #[serde(default = "default_signal_version")] @@ -685,7 +697,10 @@ pub enum SignalMessage { relay_addr: Option, }, /// Acknowledge a transfer request. - TransferAck, + TransferAck { + #[serde(default = "default_signal_version")] + version: u8, + }, /// Presence update from a peer relay (gossip protocol). /// Sent periodically over probe connections to share which fingerprints @@ -1729,7 +1744,7 @@ mod tests { version: default_signal_version(), timestamp_ms: 12345, }, - SignalMessage::Hold, + SignalMessage::Hold { version: default_signal_version() }, SignalMessage::Hangup { version: default_signal_version(), reason: HangupReason::Normal, @@ -1750,28 +1765,28 @@ mod tests { #[test] fn hold_unhold_serialize() { - let hold = SignalMessage::Hold; + let hold = SignalMessage::Hold { version: default_signal_version() }; let json = serde_json::to_string(&hold).unwrap(); let decoded: SignalMessage = serde_json::from_str(&json).unwrap(); - assert!(matches!(decoded, SignalMessage::Hold)); + assert!(matches!(decoded, SignalMessage::Hold { .. })); - let unhold = SignalMessage::Unhold; + let unhold = SignalMessage::Unhold { version: default_signal_version() }; let json = serde_json::to_string(&unhold).unwrap(); let decoded: SignalMessage = serde_json::from_str(&json).unwrap(); - assert!(matches!(decoded, SignalMessage::Unhold)); + assert!(matches!(decoded, SignalMessage::Unhold { .. })); } #[test] fn mute_unmute_serialize() { - let mute = SignalMessage::Mute; + let mute = SignalMessage::Mute { version: default_signal_version() }; let json = serde_json::to_string(&mute).unwrap(); let decoded: SignalMessage = serde_json::from_str(&json).unwrap(); - assert!(matches!(decoded, SignalMessage::Mute)); + assert!(matches!(decoded, SignalMessage::Mute { .. })); - let unmute = SignalMessage::Unmute; + let unmute = SignalMessage::Unmute { version: default_signal_version() }; let json = serde_json::to_string(&unmute).unwrap(); let decoded: SignalMessage = serde_json::from_str(&json).unwrap(); - assert!(matches!(decoded, SignalMessage::Unmute)); + assert!(matches!(decoded, SignalMessage::Unmute { .. })); } #[test] @@ -1818,10 +1833,10 @@ mod tests { #[test] fn transfer_ack_serialize() { - let ack = SignalMessage::TransferAck; + let ack = SignalMessage::TransferAck { version: default_signal_version() }; let json = serde_json::to_string(&ack).unwrap(); let decoded: SignalMessage = serde_json::from_str(&json).unwrap(); - assert!(matches!(decoded, SignalMessage::TransferAck)); + assert!(matches!(decoded, SignalMessage::TransferAck { .. })); } #[test]