feat(edit): support message-secret encrypted edits (secret_encrypted_message) - #762
Conversation
…message) Only the plaintext protocolMessage edit could be sent; the message-secret encrypted form (secret_encrypted_message, secret_enc_type=MESSAGE_EDIT) was decode-only. That form is what Community Announcement Group / channel edits require, and what WA Web sends when message_edit_to_message_secret_sender_enabled is on. Add Client::edit_message_encrypted(to, original_id, message_secret, new_content): it builds the same protocolMessage(MESSAGE_EDIT) inner via build_edit_message, encrypts it under the original message's secret with the existing wacore::message_edit::encrypt_message_edit (ModificationType::MessageEdit), and wraps it as secret_encrypted_message + messageContextInfo.messageSecret, matching WAWebGenerateSecretMessageEditProto. You can only edit your own message, so the HKDF original-sender and editor are both self (resolved to the chat's namespace, own participant JID for groups). The send path already classifies this envelope as edit=1. Opt-in: the plaintext edit_message stays the default for normal chats. Tests: encrypt/decrypt roundtrip recovers the edited content; a wrong secret fails to decrypt.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a public API ChangesEncrypted Message Edit Sending
Sequence Diagram(s)sequenceDiagram
participant Client
participant Builder as build_secret_message_edit
participant WACore as wacore::message_edit
participant Sender as send_message_impl
Client->>Builder: build_secret_message_edit(original_id, self_jid, new_content, message_secret)
Builder->>WACore: encrypt_message_edit(MessageEditContext, plaintext, message_secret)
WACore-->>Builder: secret_encrypted_message
Builder-->>Client: wa::Message (secret_encrypted_message + message_context_info)
Client->>Sender: send_message_impl(wa::Message, EditAttribute::MessageEdit)
Sender-->>Client: send result / ok
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Mark: code needs to work reliably — focus review on the editor JID resolution, strict 32-byte secret handling, and the integration point with send_message_impl. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3ec35731c6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| new_content, | ||
| )?; | ||
|
|
||
| self.send_message_impl( |
There was a problem hiding this comment.
Route channel edits off the E2E send path
When to is a WhatsApp channel/newsletter JID, this new API still delegates to send_message_impl, but that path explicitly rejects newsletters before building any stanza (send.rs returns newsletter JIDs are not valid on the E2E send path). That means the documented channel use case for edit_message_encrypted always errors instead of sending the encrypted edit; handle newsletter/channel edits through the channel send path or reject them before constructing this envelope.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/client/messaging.rs`:
- Around line 121-127: The edit_message_encrypted API accepts message_secret:
&[u8] but does not validate its length; add an explicit check in
edit_message_encrypted that message_secret.len() == 32 and return a clear error
(e.g. using anyhow::anyhow! with a descriptive message) if it isn't, before
calling encrypt_message_edit or other crypto functions so callers get a fast,
meaningful validation error referencing edit_message_encrypted and avoiding
downstream cryptic failures.
- Around line 354-361: The helper build_secret_message_edit should validate its
inputs before using them: add a defensive check at the top of
build_secret_message_edit validating message_secret (and optionally
participant/self_jid_str format if relevant) and return an anyhow::Error when
the key is the wrong length or shape instead of deferring to the crypto layer;
locate build_secret_message_edit (params: original_id, message_secret,
participant, self_jid_str) and perform an explicit length/format check (compare
message_secret.len() against the expected secret key length constant or value)
and return a clear error via anyhow::Error if it fails.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: bda3df6b-894d-430b-8c57-088e86c23385
📒 Files selected for processing (1)
src/client/messaging.rs
Benchmark Results67 unchanged benchmark(s)
|
…ge_encrypted Review follow-ups on the encrypted-edit PR: - Codex: a newsletter/channel JID would always error deep in send_message_impl (which rejects newsletters from the E2E path). Encrypted edits don't apply to plaintext channels anyway, so reject them up front with a clear boundary error pointing at edit_message. - CodeRabbit: validate message_secret is 32 bytes at the API boundary so a wrong-size secret fails fast instead of erroring deep inside encrypt_message_edit.
Closes the features-30 gap.
Only the plaintext protocolMessage edit could be sent; the message-secret encrypted form (
secret_encrypted_message,secret_enc_type = MESSAGE_EDIT) was decode-only. That encrypted form is what Community Announcement Group / channel edits require, and what WA Web sends whenmessage_edit_to_message_secret_sender_enabledis on.Adds
Client::edit_message_encrypted(to, original_id, message_secret, new_content):protocolMessage(MESSAGE_EDIT)inner via the existingbuild_edit_message.wacore::message_edit::encrypt_message_edit(ModificationType::MessageEdit).secret_encrypted_message { target_message_key, enc_payload, enc_iv, secret_enc_type = MESSAGE_EDIT }+messageContextInfo.messageSecret, matchingWAWebGenerateSecretMessageEditProto.You can only edit your own message, so the HKDF original-sender and editor are both self (resolved to the chat's namespace — own participant JID for groups, PN for 1:1). The send path already classifies this envelope as
edit=1(existinginfer_stanza_metadatatest).This is opt-in: the plaintext
edit_messagestays the default for normal chats (WA Web gates the encrypted producer behind an AB prop, so it's not the universal default).Tests: encrypt → decrypt roundtrip recovers the edited content; a wrong secret fails to decrypt.
Verified against
docs/captured-js/references forWAWebGenerateSecretMessageEditProto/WAWebCreateEncryptedMessageEditMsgDataand the existing decode path insrc/features/message_edit.rs.