Skip to content

docs: document stanza interception and DecryptedPayload event from whatsapp-rust#1239/#1240/#1241 - #492

Closed
jlucaso1 wants to merge 3 commits into
mainfrom
claude/nifty-bohr-q7z369
Closed

docs: document stanza interception and DecryptedPayload event from whatsapp-rust#1239/#1240/#1241#492
jlucaso1 wants to merge 3 commits into
mainfrom
claude/nifty-bohr-q7z369

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Documentation for a three-PR stack that shipped together in whatsapp-rust:

  • whatsapp-rust#1239 ("feat(client): let a consumer take a stanza before the built-in pipeline") — Client::add_stanza_interceptor, the StanzaInterceptor trait, and the Interception enum: a seam that lets a consumer claim a decoded stanza before the built-in pipeline, instead of watching it get nacked.
  • whatsapp-rust#1240 ("feat(client): hand over a decrypted payload before it is decoded") — Event::DecryptedPayload, gated by Client::acquire_decrypted_payload_forwarding(): hands over a decrypted <enc> payload before the client tries to decode it into a wa::Message, so a payload this build can't decode isn't just lost.
  • whatsapp-rust#1241 ("feat(plugins): let a plugin claim a stanza through a capability") — PluginCapability::StanzaInterception / PluginStanzaInterception: the plugin-host wrapper over #1239's interceptor seam, adding panic isolation and terminal-shutdown invalidation for untrusted plugin code.

Changes

  • api/client.mdx — new ### add_stanza_interceptor and ### acquire_decrypted_payload_forwarding sections under Protocol Operations, and a stanza_interceptors row in the MemoryReport fields table.
  • concepts/events.mdxDecryptedPayload added to the Event enum listing, and a new ## Decrypted payload events / ### DecryptedPayload section documenting its fields and gating.
  • advanced/plugins.mdxPluginCapability::StanzaInterception added to the capabilities table and overview sentence; new ## Stanza interception section (registration, panic isolation, terminal invalidation, Signal-durability interaction); removed "no ingress interception of inbound stanzas" from the top <Note> and the "What's not supported yet" section (pre-ack decisions are still unsupported); Diagnostics section extended to mention the new per-plugin counters.

Out of scope

api/client.mdx's existing set_raw_node_forwarding(&self, enabled: bool) section documents a signature that predates this stack — the actual method is acquire_raw_node_forwarding(self: &Arc<Self>) -> RawNodeLease. That drift isn't caused by #1239/#1240/#1241 (the lease-based API was already in place before this stack), so it's left alone here rather than folded into an unrelated docs PR.

No changes to changelog/, per standing instructions that changelog entries are human-authored only.


Generated by Claude Code


Summary by cubic

Documents stanza interception and decrypted-payload forwarding, clarifying that interception happens before Signal decryption and decode. Adds client APIs and a plugin capability with safety notes and diagnostics.

  • New Features
    • Client: add_stanza_interceptor with StanzaInterceptor/Interception and InterceptorHandle (RAII). Runs before the pipeline and Signal decryption; first-claim wins; preserves required acks; excludes connection-critical stanzas.
    • Events: Event::DecryptedPayload and acquire_decrypted_payload_forwarding (lease-gated). Fires after unpadding and before decode; forwards Bytes without copies and skips serialization.
    • Plugins: PluginCapability::StanzaInterception/PluginStanzaInterception wrapper over client interception, with panic isolation and terminal-shutdown invalidation. Diagnostics include per-plugin stanza_interceptors and interception panic counters; health degrades on panics.
    • Docs updates: api/client (interception + decrypted-payload sections, interception-before-decryption note, MemoryReport.stanza_interceptors), concepts/events (DecryptedPayload), and advanced/plugins (capability table, stanza interception, “Interaction with Signal durability,” and note clarified to “no pre-ack decisions”).

Written for commit b58f0e4. Summary will update on new commits.

jlucaso1 and others added 2 commits August 7, 2026 22:19
Reflects whatsapp-rust#1239, #1240, and #1241.
Reflects whatsapp-rust#1239, #1240, and #1241.
@mintlify

mintlify Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
whatsapp-rust 🟢 Ready View Preview Aug 8, 2026, 1:29 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jlucaso1, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 32 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 52d0b285-b066-4d1d-a972-bc8869b28580

📥 Commits

Reviewing files that changed from the base of the PR and between 99587a9 and b58f0e4.

📒 Files selected for processing (3)
  • advanced/plugins.mdx
  • api/client.mdx
  • concepts/events.mdx

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 8, 2026

Copy link
Copy Markdown

Greptile Summary

The PR documents stanza interception and opt-in decrypted-payload forwarding across the client, event, and plugin APIs.

  • Adds client API contracts, lifecycle behavior, acknowledgement responsibilities, and memory reporting for stanza interceptors.
  • Documents the DecryptedPayload event, lease gating, payload fields, and decode ordering.
  • Adds plugin stanza-interception registration, panic isolation, shutdown invalidation, diagnostics, and Signal-durability guidance.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
advanced/plugins.mdx Documents the stanza-interception capability, registration lifecycle, panic isolation, diagnostics, and responsibility for claimed Signal-bearing stanzas.
api/client.mdx Documents the interceptor and decrypted-payload lease APIs; the revised interception note consistently states that claimed stanzas undergo no Signal processing.
concepts/events.mdx Adds the opt-in DecryptedPayload event contract, fields, ordering, serialization behavior, and usage example.

Reviews (2): Last reviewed commit: "docs(client): interception precedes Sign..." | Re-trigger Greptile

Comment thread api/client.mdx Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Confidence score: 4/5

  • advanced/plugins.mdx currently states that a stanza path leaves “nothing decrypted, no session mutated, no prekey consumed,” but that conflicts with the add_stanza_interceptor behavior described in api/client; this can mislead plugin authors into unsafe assumptions about signal durability and interceptor side effects. Align the two sections (or explicitly scope when each statement is true) so readers get one consistent contract.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="advanced/plugins.mdx">

<violation number="1" location="advanced/plugins.mdx:216">
P2: The "Interaction with Signal durability" claim that a claimed stanza involves "nothing decrypted, no session mutated, no prekey consumed" directly contradicts the sibling `add_stanza_interceptor` section in api/client.mdx (same PR stack), which states a claimed `<message>` "has already been decrypted or not by the time an interceptor sees it, exactly as the built-in handler would have found it". A plugin author reading both pages gets opposite guidance about whether claiming advances Signal state/prekeys, which undercuts the no-durability-contract rationale here. Reconcile the two: either the interceptor runs after decryption (keeping the client.mdx framing) and this section must not claim zero Signal work, or interception truly precedes all Signal work and client.mdx needs correcting.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread advanced/plugins.mdx

### Interaction with Signal durability

Interception runs *before* the built-in pipeline, so a claimed stanza is one the client did no Signal work on at all: nothing decrypted, no session mutated, no prekey consumed. There's no half-advanced state to reconcile, which is what makes claiming safe to reason about and needs no dedicated durability contract.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The "Interaction with Signal durability" claim that a claimed stanza involves "nothing decrypted, no session mutated, no prekey consumed" directly contradicts the sibling add_stanza_interceptor section in api/client.mdx (same PR stack), which states a claimed <message> "has already been decrypted or not by the time an interceptor sees it, exactly as the built-in handler would have found it". A plugin author reading both pages gets opposite guidance about whether claiming advances Signal state/prekeys, which undercuts the no-durability-contract rationale here. Reconcile the two: either the interceptor runs after decryption (keeping the client.mdx framing) and this section must not claim zero Signal work, or interception truly precedes all Signal work and client.mdx needs correcting.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At advanced/plugins.mdx, line 216:

<comment>The "Interaction with Signal durability" claim that a claimed stanza involves "nothing decrypted, no session mutated, no prekey consumed" directly contradicts the sibling `add_stanza_interceptor` section in api/client.mdx (same PR stack), which states a claimed `<message>` "has already been decrypted or not by the time an interceptor sees it, exactly as the built-in handler would have found it". A plugin author reading both pages gets opposite guidance about whether claiming advances Signal state/prekeys, which undercuts the no-durability-contract rationale here. Reconcile the two: either the interceptor runs after decryption (keeping the client.mdx framing) and this section must not claim zero Signal work, or interception truly precedes all Signal work and client.mdx needs correcting.</comment>

<file context>
@@ -141,11 +142,80 @@ impl ClientPlugin for SearchPlugin {
+
+### Interaction with Signal durability
+
+Interception runs *before* the built-in pipeline, so a claimed stanza is one the client did no Signal work on at all: nothing decrypted, no session mutated, no prekey consumed. There's no half-advanced state to reconcile, which is what makes claiming safe to reason about and needs no dedicated durability contract.
+
+What it does mean is that the claim is final. The ack that follows tells the server not to redeliver, so a claimed `<message>` stays undecrypted forever, and a claimed `<notification type="encrypt">` is a prekey top-up that never happens. A plugin claiming stanzas that carry Signal state takes over that responsibility whole — see [Signal Protocol](/advanced/signal-protocol) for what that involves. Match narrowly.
</file context>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same contradiction Greptile flagged on the api/client.mdx side — fixed there in b58f0e4, so this line's framing ("nothing decrypted, no session mutated, no prekey consumed") is now the reconciled, correct account: interception truly precedes all Signal work. Nothing to change here in advanced/plugins.mdx.


Generated by Claude Code

A claimed <message> is never decrypted — the client does no Signal
work at all on a claimed stanza. Fixes ambiguous wording flagged in
PR review.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Re-trigger cubic

@jlucaso1

jlucaso1 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator Author

@claude solve conflicts

@jlucaso1 jlucaso1 closed this Aug 8, 2026

jlucaso1 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator Author

Closing rather than resolving conflicts: this PR duplicates work. Three concurrent runs of the same automated task (for the same whatsapp-rust PR stack, #1239/#1240/#1241) produced three docs PRs here — #490, this one (#492), and #493. #490 merged first (01:27 UTC, ~1 minute before this one was opened) and covers the same three files with equivalent-or-better content: it documents the same add_stanza_interceptor/Interception/StanzaInterceptor seam, the DecryptedPayload event, and the plugin StanzaInterception capability, without the decryption-timing ambiguity this PR briefly had (and fixed in b58f0e4) — and it additionally fixed the pre-existing set_raw_node_forwarding docs drift that this PR explicitly left out of scope. #493 was already closed as the same duplicate.

Since main now has #490's version of advanced/plugins.mdx, api/client.mdx, and concepts/events.mdx, merging this PR's conflicting diff on top would just reintroduce redundant/conflicting sections rather than add anything new. No further action needed here.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants