Skip to content

docs: reflect group/status sender-key leasing and store incarnation (whatsapp-rust#1027) - #404

Merged
jlucaso1 merged 3 commits into
mainfrom
claude/nifty-bohr-ii34a6
Jul 15, 2026
Merged

docs: reflect group/status sender-key leasing and store incarnation (whatsapp-rust#1027)#404
jlucaso1 merged 3 commits into
mainfrom
claude/nifty-bohr-ii34a6

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Reflects whatsapp-rust#1027 ("fix(signal): gate the group sender-key advance before the wire"), which:

  • Found that the production group-send encrypt path (wacore::send::encrypt_group_message) was a second, unguarded implementation that didn't gate the sender-key advance on durability — the docs claim that group/status sends "always persist synchronously" was true in intent but not in the code that actually ran. That path now delegates to the shared group_encrypt primitive.
  • Extended the batched counter-lease pattern DMs already use (SessionRecord, documented for #1026) to group/status sends via a new SenderKeyRecord::reserve_iterations, so most group/status sends now ride the coalesced write-behind instead of flushing on every send.
  • Introduced a store-incarnation marker (local-only field 101) so a clean reconnect or same-process store reload is recognized as exact and doesn't burn an unused lease batch — previously every clean reconnect/direct-store reload fast-forwarded conservatively, same as an actual crash.
  • Changed connection teardown to call the new SignalStoreCache::clear_after_flush(), which only evicts fully-settled cache entries instead of unconditionally clearing everything after a flush.

Changes

  • advanced/signal-protocol.mdx — updated the "flush scheduling" bullet for group/status sends (was: "ignores the lease... on every send... not implemented yet"), updated the downgrade warning, and added a new "Clean reload vs. crash recovery" section documenting the store-incarnation mechanism.
  • api/send.mdx — updated the send_message durability note to describe the shared DM/group/status lease model.
  • api/client.mdx — updated flush_pending_signal_state docs to match.
  • concepts/architecture.mdx — updated the disconnect-cleanup table row and added a note on settled-only eviction (clear_after_flush).

No changes under changelog/ (per project convention, that's maintained by a human).

Test plan

  • Read the full upstream diff (wacore/src/store/signal_cache.rs, wacore/libsignal/src/protocol/{sender_keys,group_cipher,state/session}.rs, wacore/libsignal/src/protocol/local_field.rs, wacore/src/send/encrypt.rs, src/store/signal.rs, src/message/commit_batch.rs) to verify every claim against the actual code changes and new tests.
  • Grepped the docs repo for every other place that stated the old "group/status sends always flush synchronously" behavior to make sure none were missed.
  • mint broken-links (not run locally in this environment — no network-installed Mintlify CLI)

Generated by Claude Code


Summary by cubic

Update docs for group/status sender-key leasing and a unified, durability‑gated group/status encrypt path that only flushes on lease extension. Add store‑incarnation behavior for trusted reloads, clarify the DM fast‑forward wording to match it, note settled‑only eviction via SignalStoreCache::clear_after_flush(), and fix the OnceLock article nit.

  • Migration
    • Avoid downgrading to versions that predate leases. They ignore local lease fields on SessionRecord/SenderKeyRecord and can reuse counters/iterations that were only reserved (status@broadcast reactions follow DM lease rules).

Written for commit 53730a6. Summary will update on new commits.

…whatsapp-rust#1027)

PR #1027 fixed a crash-safety gap where the production group-send path
bypassed the durability gate entirely, and folded group/status sender-key
advances into the same batched counter-lease pattern DMs already use
(instead of a synchronous flush on every send). It also introduced a
store-incarnation marker so a clean reload/reconnect no longer burns an
unused lease batch the way an actual crash recovery must.
@coderabbitai

coderabbitai Bot commented Jul 15, 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: 59 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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: 60ac7333-6cd0-4c0f-95b3-2248540cac26

📥 Commits

Reviewing files that changed from the base of the PR and between 46478d7 and 53730a6.

📒 Files selected for processing (4)
  • advanced/signal-protocol.mdx
  • api/client.mdx
  • api/send.mdx
  • concepts/architecture.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.

@mintlify

mintlify Bot commented Jul 15, 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 Jul 15, 2026, 5:58 PM

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

@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown

Greptile Summary

This docs-only PR updates four documentation files to reflect whatsapp-rust#1027, which extended the batched counter-lease durability model from DM sends to group/status sends and introduced a store-incarnation marker for distinguishing clean reloads from crash recovery.

  • advanced/signal-protocol.mdx — revised the flush-scheduling bullet for group/status sends (was "ignores the lease, flushes on every send"), updated the downgrade warning to cover SenderKeyRecord, and added a new "Clean reload vs. crash recovery" section explaining the 128-bit incarnation field and clear_after_flush().
  • api/send.mdx and api/client.mdx — updated the send_message durability note and flush_pending_signal_state docs to describe the now-unified DM/group/status lease model.
  • concepts/architecture.mdx — updated the disconnect-cleanup table row and added a "Settled-only eviction" note explaining SignalStoreCache::clear_after_flush() behavior.

Confidence Score: 5/5

All four changed files are documentation only; no executable code was modified. Claims across files are mutually consistent, field numbers and batch sizes agree, cross-reference anchors match their target section headings, and the MAX_FORWARD_JUMPS arithmetic (32 × 64 = 2,048 > 2,000) is correct.

The changes are accurate documentation updates that reflect an already-merged upstream code change. All behavioral claims are consistent across the four files, internal cross-links resolve to real section anchors, and the only finding is a minor tense inconsistency in one sentence that does not affect correctness.

No files require special attention.

Important Files Changed

Filename Overview
advanced/signal-protocol.mdx Flush-scheduling bullet updated for group/status sends; downgrade warning expanded; new "Clean reload vs. crash recovery" section added. One minor past-tense verb ("followed") in the group/status bullet could be read as indicating the behavior changed, when it is in fact unchanged.
api/send.mdx Durability note updated to describe the unified DM/group/status batched-lease model; accurate and consistent with the signal-protocol doc.
api/client.mdx flush_pending_signal_state doc updated to cover group/status lease parity; wording is consistent with the other changed files.
concepts/architecture.mdx Disconnect-cleanup table row tightened to "settled entries cleared"; new "Settled-only eviction" note added, cross-referencing the signal-protocol section. Accurate and complete.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Send["send_message()"] --> Type{Message type?}

    Type -->|DM / 1:1| DM["SessionRecord\n(field 100 counter lease)"]
    Type -->|Group / Status post| GS["SenderKeyRecord\n(field 100 iteration lease)"]
    Type -->|Status reaction| SR["DM branch\n(SessionRecord lease)"]

    DM --> LeaseCheck1{Lease\nexhausted?}
    GS --> LeaseCheck2{Lease\nexhausted?}
    SR --> LeaseCheck1

    LeaseCheck1 -->|~1 in 64| SyncFlush1["Synchronous flush\nbefore wire"]
    LeaseCheck1 -->|covered| WriteBack["Coalesced write-behind\n(~25 ms window)"]
    LeaseCheck2 -->|~1 in 64| SyncFlush2["Synchronous flush\nbefore wire"]
    LeaseCheck2 -->|covered| WriteBack

    SyncFlush1 --> IncarnationCheck["Incarnation marker\n(field 101)"]
    SyncFlush2 --> IncarnationCheck
    WriteBack --> IncarnationCheck

    IncarnationCheck -->|Marker matches cache| TrustedReload["Exact resume\n(no fast-forward)"]
    IncarnationCheck -->|No match / missing / crash| ConservativeReload["Fast-forward to\nlease ceiling"]

    SyncFlush1 -->|flush fails| Abort["send_message → Err\n(no stanza sent)"]
    SyncFlush2 -->|flush fails| Abort
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    Send["send_message()"] --> Type{Message type?}

    Type -->|DM / 1:1| DM["SessionRecord\n(field 100 counter lease)"]
    Type -->|Group / Status post| GS["SenderKeyRecord\n(field 100 iteration lease)"]
    Type -->|Status reaction| SR["DM branch\n(SessionRecord lease)"]

    DM --> LeaseCheck1{Lease\nexhausted?}
    GS --> LeaseCheck2{Lease\nexhausted?}
    SR --> LeaseCheck1

    LeaseCheck1 -->|~1 in 64| SyncFlush1["Synchronous flush\nbefore wire"]
    LeaseCheck1 -->|covered| WriteBack["Coalesced write-behind\n(~25 ms window)"]
    LeaseCheck2 -->|~1 in 64| SyncFlush2["Synchronous flush\nbefore wire"]
    LeaseCheck2 -->|covered| WriteBack

    SyncFlush1 --> IncarnationCheck["Incarnation marker\n(field 101)"]
    SyncFlush2 --> IncarnationCheck
    WriteBack --> IncarnationCheck

    IncarnationCheck -->|Marker matches cache| TrustedReload["Exact resume\n(no fast-forward)"]
    IncarnationCheck -->|No match / missing / crash| ConservativeReload["Fast-forward to\nlease ceiling"]

    SyncFlush1 -->|flush fails| Abort["send_message → Err\n(no stanza sent)"]
    SyncFlush2 -->|flush fails| Abort
Loading

Reviews (3): Last reviewed commit: "docs: qualify DM fast-forward claim agai..." | Re-trigger Greptile

Comment thread advanced/signal-protocol.mdx Outdated
Addresses greptile review nit on PR #404.
greptile-apps[bot]
greptile-apps Bot previously approved these changes Jul 15, 2026
The DM flush-scheduling bullet unconditionally said every load
fast-forwards, which contradicted the Clean reload vs. crash recovery
section added just below it (a trusted store-backed reload does not
fast-forward). Addresses greptile review feedback on PR #404.
@greptile-apps
greptile-apps Bot dismissed their stale review July 15, 2026 18:07

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

@mintlify

mintlify Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

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

Project Status Preview Updated (UTC)
whatsapp-rust 🟡 Building Jul 15, 2026, 5:56 PM

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

@jlucaso1
jlucaso1 merged commit 041bf76 into main Jul 15, 2026
4 checks passed
jlucaso1 pushed a commit that referenced this pull request Jul 15, 2026
#404 (whatsapp-rust#1027 docs) merged to main and rewrote the same
"Flush scheduling" bullets this branch touched. Kept #404's version of
the DM/group-send bullets, downgrade warning, and new "Clean reload vs.
crash recovery" section, and re-layered this branch's retry-recovery
paragraph on top.

Also added a caveat, prompted by review, that the pre-wire flush gate
is a point-in-time check: a session checked out by a concurrent
operation is skipped by flush() without failing it, so a successful
flush doesn't guarantee that specific session's reservation cleared.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mpevz37YPKV1SB8GNmwCqB
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