> ## Documentation Index
> Fetch the complete documentation index at: https://whatsapp-rust.jlucaso.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Week of June 2, 2026

> Bot message decryption, streaming uploads, typed event subscriptions, and WhatsApp Web parity improvements

This week brings native bot message decryption, constant-memory streaming uploads, and a host of WhatsApp Web parity fixes.

## New features

**Bot message decryption (msmsg)**
Meta AI and other fbid bot replies are now decrypted automatically and dispatched as a normal `Event::Message`. No special handling required — just listen for messages as usual. See the [Signal API reference](/api/signal).

**Constant-memory streaming uploads**
Audio and video uploads can now stream from disk without loading the full file into memory, and produce a per-64 KiB HMAC sidecar that enables progressive playback for recipients. Ideal for large media on memory-constrained hosts. See [Upload](/api/upload).

**Inline edit decryption**
Secret-encrypted edits (message edits, poll edits, event edits, and poll-add-option) are now decrypted automatically on receive. Most apps no longer need to call the manual decryption helpers. See [Polls](/api/polls).

**Typed event subscriptions**
Event handlers can now declare which event kinds they care about via `EventHandler::interest()` and `on_event_for(&[EventKind], …)`, letting the runtime skip work for events you don't consume. See [Events](/concepts/events) and [Bot](/api/bot).

**`messageSecret` retention policy**
A new configurable retention policy (`Managed`, `BotOnly`, `Full`, `Disabled`) controls how long `messageSecret` values are kept per message class, with sensible defaults (30d / 90d / 30d). History seeding and a fallback resolver are also available. See [Bot](/api/bot).

## Updates

**Longer retry receipt window**
The default `sent_message_ttl_secs` has been bumped from 5 minutes to 2 hours so retry receipts from slow or briefly offline recipients still resolve to the original message.

**Persisted sender-key chains on disconnect**
`disconnect()` now flushes the Signal cache to your backend before clearing it, so advanced sender-key chains survive reconnects and avoid unnecessary SKDM re-fanouts.

**Renamed `ConnectFailureReason::MainDeviceGone` → `AccountLocked`**
Matches WhatsApp Web's `REASON_LOCKED` (HTTP 403) and better reflects the actual condition. Update any match arms accordingly.

**`TransportEvent::Disconnected` now carries a reason**
Custom transports now report `DisconnectReason` (`ServerClose`, `StreamEnded`, `ReadError`, or `Unknown`) so reconnect logic can branch on cause. This is a breaking change for custom `Transport` implementations — see [Transport](/api/transport) and [Custom backends](/guides/custom-backends).

**Batched app-state mutation MACs**
`AppSyncStore::get_mutation_macs` provides a batched lookup that backends can override with a SQL `IN` query, eliminating an N+1 during app-state sync. See [Store](/api/store).

**`CompactString` for LID lookups**
`get_current_lid` and `SendContextResolver::get_lid_for_phone` now return `Option<CompactString>` instead of `Option<String>` for lower allocation pressure. See [Storage](/concepts/storage).

**Spawnable marker trait**
A new `Spawnable` marker (`Send + 'static` on native, `'static` on wasm32) makes generic spawn helpers easier to write across targets. See [Custom backends](/guides/custom-backends).

**WhatsApp Web parity**

* Uniform plaintext padding (1..=16 bytes) replaces the previous biased scheme.
* Full device set included on every send for participant-hash calculation, with standard base64 alphabet and persisted group metadata for not-modified group queries.
* Sender-key chains are now serialized per `(group, sender)` pair.
* DM sends now fail fast when every per-device encrypt fails instead of silently producing an empty stanza.
* Stanza classification fixes: `poll-add-option` is classified as `poll`, and `album` as `text`.
* `unwrap_message` now peels a wider set of `FutureProofMessage` wrappers (including `groupStatusV2` and `spoiler`).

## Bug fixes

**`decrypt-fail=hide` coverage**
`conditional_reveal_message`, `secret_encrypted_message`, and `PollAddOption` are now correctly hidden on decrypt failure, and `SenderRevoke` is excluded from hide alongside `AdminRevoke`.

**Peer edit sender resolution**
`MessageEdit` events from peers now resolve the original sender from the envelope rather than the edit target, fixing mis-attribution on multi-device accounts.

**Session-recreate cooldown is bounded**
The session-recreate history is now a bounded TTL cache (\~256 entries, 1h) with atomic per-peer check-and-stamp, so long-running clients no longer accumulate unbounded state. Per-peer cooldown behavior is unchanged.

**SKDM-only decrypt acking**
Sender-key distribution-only decrypts are now acked so they drain from the offline queue instead of being redelivered.
