You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Disappearing-messages support (Baileys engine). Outbound messages now honor a chat's disappearing-messages timer and set it on each send (text, media, and replies), so recipients no longer see "This message won't disappear — the sender may be using an older version of WhatsApp." The timer is learned from inbound messages — the reliable source, since the cached chat setting is often absent for a long-standing timer — and resolved across both phone and @lid chat identifiers so it applies on LID-migrated 1:1 chats, with a fallback to the chat's cached setting. It is applied only when a positive value is known; when it's unknown or disabled, the per-message expiration is omitted, exactly as before. Reactions, deletes/revokes, and status posts are unaffected. Thanks @ulises2k. (#473, #513)
Selective skip for disappearing messages. New STORE_EPHEMERAL_MESSAGES env var (default true). Set to false to skip persisting and dispatching incoming disappearing messages (those with ephemeralDuration > 0) — no DB insert, no webhook dispatch, no websocket event. Backward compatible; existing deployments are unaffected. The ephemeralDuration field is also surfaced on IncomingMessage for consumers that want to handle it themselves. Thanks @spidgrou. (#506)
Durable dead-letter record for failed webhook deliveries. A webhook delivery that permanently fails — exhausting its retries or being rejected before it is sent — is now persisted to a new webhook_delivery_failures table instead of disappearing when its job is evicted from the queue. Operators can review the recorded failures (endpoint, event, status, error, attempts) through a new admin endpoint, GET /webhooks/delivery-failures. (#520)
Fixed
Deleting a session now removes its message history and bulk batches. The messages and message_batches tables had no cascade from sessions, so a deleted session left its rows behind — growing the largest tables without bound and skewing dashboard statistics. They are now removed in the same transaction as the session. (#504)
Deleting a session while it is reconnecting no longer leaks its engine. A delete that landed during the multi-second engine initialization of an in-flight reconnect (or start) could leave the freshly-launched browser/socket registered under the now-deleted session, still counting toward the concurrent-session limit. The post-init guard now re-checks that the session still exists before keeping the engine. (#521)
Inbound media downloads are bounded by a wall-clock timeout. A slow or stalled inbound media transfer could hold a download slot — and, on the Baileys engine, the entire inbound-message pipeline — open indefinitely. Downloads now time out (MEDIA_DOWNLOAD_TIMEOUT_MS, default 30s) and the message is delivered with the media omitted. (#510)
Webhook delivery identifiers stay consistent with the signed body. The X-OpenWA-Idempotency-Key / X-OpenWA-Delivery-Id headers could diverge from the signed payload when a webhook:before plugin returned a modified payload, and all webhooks for an event shared one data object. Each webhook now receives an isolated copy of the data and the server-generated identifiers are authoritative. (#512)
POST /auth/validate no longer double-counts key usage and now validates IP-restricted keys correctly (it previously reported a valid IP-pinned key as invalid). (#507)
⚠️GET /settings now requires an ADMIN key (behavior change) — matching the rest of the configuration surface; it was previously readable by any authenticated key. A client that read settings with a non-admin key must switch to an ADMIN key. (#514)
Bulk-message batchId uniqueness is scoped per session, so two sessions can reuse a batch id and neither can probe the other's id namespace. (#515)
⚠️ Boot-time configuration validation now rejects 0 for the rate-limit limits and the webhook timeout (behavior change) — values that silently disabled throttling or aborted every delivery. A deployment that set 0 to disable these must remove the override or use a positive value. (#516)
SSRF protection now blocks the RFC6052 IPv4-translatable IPv6 form (::ffff:0:a.b.c.d), closing a gap where an internal address could be reached behind a NAT64/SIIT translator. (#518)
Per-key IP allowlist now uses the shared, hardened IP matcher and rejects a malformed client address instead of coercing it into an allowed range. (#519)
Dashboard: the Infrastructure page is no longer rendered for non-admin roles, and image-attachment preview object URLs are released after use. (#508)
Released a small in-memory leak: a deleted session's stored failure reason is now cleared. (#505)
The webhook worker now connects to the configured Redis. Configuration from .env and the dashboard-saved file is loaded before the application modules are evaluated, so the webhook delivery worker reads its Redis host/port/password from the configured values instead of falling back to a local default when those are supplied by file rather than the process environment. (#523)
Performance
Configurable webhook worker concurrency (WEBHOOK_WORKER_CONCURRENCY, default 10): a single slow or unresponsive receiver no longer head-of-line-blocks delivery for every other webhook. (#511)
Dropped a redundant single-column index on messages(sessionId) already covered by the existing composite indexes, reducing write-time overhead on a high-volume table. (#509)