fix(matrix): send markdown replies and improve e2ee diagnostics
Enable matrix-sdk markdown support and send Matrix messages with text_markdown so clients can render formatted_body. Add listener startup diagnostics for device verification and backup state to reduce confusion around matrix_sdk_crypto backup warnings. Expand Matrix docs with backup-warning interpretation, unverified-device guidance, markdown formatting expectations, and updated log keyword appendix.
This commit is contained in:
parent
a9fcf6b58c
commit
606f2860a0
5 changed files with 85 additions and 5 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
|
@ -4225,6 +4225,24 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"memchr",
|
||||
"pulldown-cmark-escape",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark-escape"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.9"
|
||||
|
|
@ -4657,6 +4675,7 @@ dependencies = [
|
|||
"js_int",
|
||||
"js_option",
|
||||
"percent-encoding",
|
||||
"pulldown-cmark",
|
||||
"regex",
|
||||
"ruma-common",
|
||||
"ruma-identifiers-validation",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ tokio-util = { version = "0.7", default-features = false }
|
|||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "blocking", "multipart", "stream", "socks"] }
|
||||
|
||||
# Matrix client + E2EE decryption
|
||||
matrix-sdk = { version = "0.16", default-features = false, features = ["e2e-encryption", "rustls-tls"] }
|
||||
matrix-sdk = { version = "0.16", default-features = false, features = ["e2e-encryption", "rustls-tls", "markdown"] }
|
||||
|
||||
# Serialization
|
||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -150,6 +150,10 @@ allowed_users = ["*"]
|
|||
|
||||
See [Matrix E2EE Guide](./matrix-e2ee-guide.md) for encrypted-room troubleshooting.
|
||||
|
||||
Notes:
|
||||
- Outbound Matrix replies are emitted as markdown-capable `m.room.message` text content so common clients can render lists, emphasis, and code blocks.
|
||||
- If you still see `matrix_sdk_crypto::backups` warnings, follow the backup/recovery section in the Matrix E2EE guide.
|
||||
|
||||
### 4.6 Signal
|
||||
|
||||
```toml
|
||||
|
|
@ -316,7 +320,7 @@ rg -n "Matrix|Telegram|Discord|Slack|Mattermost|Signal|WhatsApp|Email|IRC|Lark|D
|
|||
| Discord | `Discord: connected and identified` | `Discord: ignoring message from unauthorized user:` | `Discord: received Reconnect (op 7)` / `Discord: received Invalid Session (op 9)` |
|
||||
| Slack | `Slack channel listening on #` | `Slack: ignoring message from unauthorized user:` | `Slack poll error:` / `Slack parse error:` |
|
||||
| Mattermost | `Mattermost channel listening on` | `Mattermost: ignoring message from unauthorized user:` | `Mattermost poll error:` / `Mattermost parse error:` |
|
||||
| Matrix | `Matrix channel listening on room` / `Matrix room ... is encrypted; E2EE decryption is enabled via matrix-sdk.` | `Matrix whoami failed; falling back to configured session hints for E2EE session restore:` / `Matrix whoami failed while resolving listener user_id; using configured user_id hint:` | `Matrix sync error: ... retrying...` |
|
||||
| Matrix | `Matrix channel listening on room` / `Matrix room ... is encrypted; E2EE decryption is enabled via matrix-sdk.` / `Matrix room-key backup is enabled for this device.` / `Matrix device '...' is verified for E2EE.` | `Matrix whoami failed; falling back to configured session hints for E2EE session restore:` / `Matrix whoami failed while resolving listener user_id; using configured user_id hint:` / `Matrix room-key backup is not enabled for this device...` / `Matrix device '...' is not verified...` | `Matrix sync error: ... retrying...` |
|
||||
| Signal | `Signal channel listening via SSE on` | (allowlist checks are enforced by `allowed_from`) | `Signal SSE returned ...` / `Signal SSE connect error:` |
|
||||
| WhatsApp (channel) | `WhatsApp channel active (webhook mode).` | `WhatsApp: ignoring message from unauthorized number:` | `WhatsApp send failed:` |
|
||||
| Webhook / WhatsApp (gateway) | `WhatsApp webhook verified successfully` | `Webhook: rejected — not paired / invalid bearer token` / `Webhook: rejected request — invalid or missing X-Webhook-Secret` / `WhatsApp webhook verification failed — token mismatch` | `Webhook JSON parse error:` |
|
||||
|
|
@ -336,4 +340,3 @@ If a specific channel task crashes or exits, the channel supervisor in `channels
|
|||
- `Channel message worker crashed:`
|
||||
|
||||
These messages indicate automatic restart behavior is active, and you should inspect preceding logs for root cause.
|
||||
|
||||
|
|
|
|||
|
|
@ -109,8 +109,16 @@ curl -sS -H "Authorization: Bearer $MATRIX_TOKEN" \
|
|||
- The bot device must receive room keys from trusted devices.
|
||||
- If keys are not shared to this device, encrypted events cannot be decrypted.
|
||||
- Verify device trust and key sharing in your Matrix client/admin workflow.
|
||||
- If logs show `matrix_sdk_crypto::backups: Trying to backup room keys but no backup key was found`, key backup recovery is not enabled on this device yet. This warning is usually non-fatal for live message flow, but you should still complete key backup/recovery setup.
|
||||
- If recipients see bot messages as "unverified", verify/sign the bot device from a trusted Matrix session and keep `channels_config.matrix.device_id` stable across restarts.
|
||||
|
||||
### E. Fresh start test
|
||||
### E. Message formatting (Markdown)
|
||||
|
||||
- ZeroClaw sends Matrix text replies as markdown-capable `m.room.message` text content.
|
||||
- Matrix clients that support `formatted_body` should render emphasis, lists, and code blocks.
|
||||
- If formatting appears as plain text, check client capability first, then confirm ZeroClaw is running a build that includes markdown-enabled Matrix output.
|
||||
|
||||
### F. Fresh start test
|
||||
|
||||
After updating config, restart daemon and send a new message (not just old timeline history).
|
||||
|
||||
|
|
|
|||
|
|
@ -438,6 +438,40 @@ impl MatrixChannel {
|
|||
})
|
||||
.to_string()
|
||||
}
|
||||
|
||||
async fn log_e2ee_diagnostics(&self, client: &MatrixSdkClient) {
|
||||
match client.encryption().get_own_device().await {
|
||||
Ok(Some(device)) => {
|
||||
if device.is_verified() {
|
||||
tracing::info!(
|
||||
"Matrix device '{}' is verified for E2EE.",
|
||||
device.device_id()
|
||||
);
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"Matrix device '{}' is not verified. Some clients may label bot messages as unverified until you sign/verify this device from a trusted session.",
|
||||
device.device_id()
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
tracing::warn!(
|
||||
"Matrix own-device metadata is unavailable; verify/signing status cannot be determined."
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("Matrix own-device verification check failed: {error}");
|
||||
}
|
||||
}
|
||||
|
||||
if client.encryption().backups().are_enabled().await {
|
||||
tracing::info!("Matrix room-key backup is enabled for this device.");
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"Matrix room-key backup is not enabled for this device; `matrix_sdk_crypto::backups` warnings about missing backup keys may appear until recovery is configured."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -465,7 +499,7 @@ impl Channel for MatrixChannel {
|
|||
anyhow::bail!("Matrix room '{}' is not in joined state", target_room_id);
|
||||
}
|
||||
|
||||
room.send(RoomMessageEventContent::text_plain(&message.content))
|
||||
room.send(RoomMessageEventContent::text_markdown(&message.content))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -491,6 +525,8 @@ impl Channel for MatrixChannel {
|
|||
};
|
||||
let client = self.matrix_client().await?;
|
||||
|
||||
self.log_e2ee_diagnostics(&client).await;
|
||||
|
||||
let _ = client.sync_once(SyncSettings::new()).await;
|
||||
|
||||
tracing::info!(
|
||||
|
|
@ -725,6 +761,20 @@ mod tests {
|
|||
assert!(!MatrixChannel::has_non_empty_body(" \n\t "));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_content_uses_markdown_formatting() {
|
||||
let content = RoomMessageEventContent::text_markdown("**hello**");
|
||||
let value = serde_json::to_value(content).unwrap();
|
||||
|
||||
assert_eq!(value["msgtype"], "m.text");
|
||||
assert_eq!(value["body"], "**hello**");
|
||||
assert_eq!(value["format"], "org.matrix.custom.html");
|
||||
assert!(value["formatted_body"]
|
||||
.as_str()
|
||||
.unwrap_or_default()
|
||||
.contains("<strong>hello</strong>"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_filter_for_room_targets_requested_room() {
|
||||
let filter = MatrixChannel::sync_filter_for_room("!room:matrix.org", 0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue