feat(channels): add Linq channel for iMessage/RCS/SMS support

The existing iMessage channel relies on AppleScript and only works on macOS.
Linq provides a REST API for iMessage, RCS, and SMS — this gives ZeroClaw
native iMessage support on any platform via webhooks.

Implements LinqChannel following the same patterns as WhatsAppChannel:
- Channel trait impl (send, listen, health_check, typing indicators)
- Webhook handler with HMAC-SHA256 signature verification
- Sender allowlist filtering
- Onboarding wizard step with connection testing
- 18 unit tests covering parsing, auth, and signature verification

Resolves #656 — the prior issue was closed without a merged PR, so this
is the actual implementation.
This commit is contained in:
George McCain 2026-02-18 11:04:45 -05:00 committed by Chummy
parent e23edde44b
commit 361e750576
5 changed files with 1003 additions and 5 deletions

View file

@ -1974,6 +1974,7 @@ pub struct ChannelsConfig {
pub matrix: Option<MatrixConfig>,
pub signal: Option<SignalConfig>,
pub whatsapp: Option<WhatsAppConfig>,
pub linq: Option<LinqConfig>,
pub email: Option<crate::channels::email_channel::EmailConfig>,
pub irc: Option<IrcConfig>,
pub lark: Option<LarkConfig>,
@ -2002,6 +2003,7 @@ impl Default for ChannelsConfig {
matrix: None,
signal: None,
whatsapp: None,
linq: None,
email: None,
irc: None,
lark: None,
@ -2148,6 +2150,20 @@ pub struct WhatsAppConfig {
pub allowed_numbers: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LinqConfig {
/// Linq Partner API token (Bearer auth)
pub api_token: String,
/// Phone number to send from (E.164 format)
pub from_phone: String,
/// Webhook signing secret for signature verification
#[serde(default)]
pub signing_secret: Option<String>,
/// Allowed sender handles (phone numbers) or "*" for all
#[serde(default)]
pub allowed_senders: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IrcConfig {
/// IRC server hostname
@ -3246,6 +3262,7 @@ default_temperature = 0.7
matrix: None,
signal: None,
whatsapp: None,
linq: None,
email: None,
irc: None,
lark: None,
@ -3751,6 +3768,7 @@ allowed_users = ["@ops:matrix.org"]
}),
signal: None,
whatsapp: None,
linq: None,
email: None,
irc: None,
lark: None,
@ -3915,6 +3933,7 @@ channel_id = "C123"
app_secret: None,
allowed_numbers: vec!["+1".into()],
}),
linq: None,
email: None,
irc: None,
lark: None,