[Unreleased]
[0.1.0-alpha.9] - 2026-06-02
WhatsApp/Baileys v7 compatibility update. This release moves BaileysEx from the
Baileys v7 rc9 behavior set to v7.0.0-rc13 and brings over the rc10-rc13
protocol fixes that affect pairing, message resend, app-state sync, trusted
contact tokens, device lists, newsletters, groups, and account-limit handling.
Upgrade Impact
- No public BaileysEx function was intentionally removed or renamed.
- QR pairing payloads now use Baileys rc13's linked-device format. Regenerate any in-flight QR codes after upgrading.
- Direct 1:1 message sends may now attach trusted-contact tokens or issue fresh tokens after sending. Apps that inspect raw stanzas or count outbound protocol traffic may see additional token-related traffic.
- Missing/unavailable messages can now emit Baileys-shaped placeholder stubs and request a resend from the phone device. Message consumers should tolerate unavailable-message placeholders and later replacement messages.
- App-state sync can now retry with snapshots, park collections while waiting for missing app-state keys, and resume when a key-share arrives. This improves recovery after reconnects and key rotation, but sync completion may now proceed with partial state when WhatsApp sends an individually corrupted sync record.
- Device-list removals now clear stale sessions. This can cause a session to be rebuilt on the next send instead of reusing an outdated device session.
- New account restriction and message-cap notifications can be emitted when WhatsApp reports reachout timelocks or new-chat limits.
- Parsed events may include new fields such as usernames, group participant usernames, and group online counts.
Added
fetch_account_reachout_timelock/2andfetch_new_chat_message_cap/2for WhatsApp account-limit checks.- Reachout timelock and new-chat-limit events from MEX notifications.
- Trusted-contact token persistence, post-send issuance, identity-change reissue, expiry cleanup, and sender timestamp preservation.
- Username lookup support in USync results.
- Album message sending.
- Group
@allmentions. - Group participant usernames and group online counts in parsed events.
- Device-list notification handling for add, remove, and update changes.
- Newsletter v2 join/leave support and multi-child newsletter notification handling.
Changed
- Updated the compatibility target from Baileys v7 rc9 behavior to
v7.0.0-rc13. - Default WhatsApp Web version and linked-device QR pairing output now match Baileys rc13.
- Direct 1:1 sends now follow Baileys' trusted-contact-token rules: existing tokens are attached only for eligible user messages, peer/AppStateSync messages are excluded, and fresh tokens are issued after eligible sends.
- App-state sync is more resilient after reconnects and key rotation: missing keys retry with a snapshot before parking, parked collections retry when a new app-state key arrives, and corrupted individual sync records no longer abort the whole sync pass.
- Incoming unavailable-message placeholders now use the Baileys rc10 resend behavior, including phone-device requests for missing messages and safety skips for bot, hosted, view-once, and old unavailable stanzas.
- Retry and bad-ack handling now preserves Baileys error semantics, including unknown retry codes and 463 account-restriction updates.
- Pre-key uploads no longer use a default throttle, matching the Baileys rc10 send path.
- Media downloads now fall back across direct-path hosts when WhatsApp returns a CDN URL that cannot be fetched directly.
- Offline notifications are processed in Baileys-compatible FIFO batches with buffered event flushing, reducing event churn during reconnect catch-up.
Fixed
- Linked-device sync messages routed by WhatsApp as outgoing self stanzas are
now treated as
from_me, even when the stanza omits an explicitrecipient. This prevents valid history sync, app-state key-share, LID mapping, and peer-data operation responses from being skipped after reconnects or companion sync flows. - Self-only protocol sync messages are ignored when they arrive from another sender, preventing peer-originated stanzas from mutating local sync state.
- Privacy-token notifications no longer drop the stored sender timestamp used to avoid duplicate trusted-contact token issuance.
- Direct peer messages no longer include
tctokennodes that WhatsApp rejects. - Protocol message parsing now handles WhatsApp's newer peer-routed self-stanza shape without dropping legitimate self sync messages.
[0.1.0-alpha.8] - 2026-05-22
Library-guideline cleanup.
Changed
- Removed the unused
BaileysEx.Applicationcallback and global singleton supervisors; connection runtimes are now only caller-owned per-connection supervisors - File persistence convenience defaults now use literal cwd-based paths instead of
Application.get_env/2
[0.1.0-alpha.7] - 2026-03-21
DRY audit and bug-fix pass. Duplicated transport wrappers across feature and media modules had diverged silently, producing a runtime crash path.
Added
Connection.TransportAdapter— shared transport dispatch replacing diverged copies across 12 modulesSignal.Store.wrap_running/1— centralized signal store resolution
Fixed
Media.Uploadcrash when given{module, pid}queryable tuples from runtime APIsStore.put/3withnilsilently preserving old values instead of deleting- Stale LTHash state on Syncd retry-from-scratch due to nil writes being dropped
- EventEmitter silently losing events after dispatcher process death
Changed
- EventEmitter dispatch hardened with queue-based delivery, monitor/restart, and
throw/exit/raiseisolation
[0.1.0-alpha.6] - 2026-03-20
Eliminates the last JS-shaped design pattern in the codebase. Signal store
transactions previously used a zero-argument closure with hidden state in
the process dictionary — a literal port of Baileys' keys.transaction(async () => ...). Transactions now pass an explicit handle through the closure,
matching the Ecto Repo.transaction(fn repo -> ... end) convention. This
makes transaction state visible, testable, and composable without hidden
coupling to the calling process.
Added
Signal.Store.transaction/3now passes explicit transaction handlesTransactionBuffermodule extracts reusable ETS-based transaction caching
Changed
- Signal store internals redesigned: all consumers receive
tx_storeexplicitly through closures
Fixed
- Weak test assertions (
assert %{} =) replaced with strict equality checks
[0.1.0-alpha.5] - 2026-03-20
Post-merge hardening of the persistence architecture from alpha.4. Shared write primitives extracted, exception-driven JSON parsing replaced with explicit error handling, and migration edge cases closed.
Changed
- Extracted shared crash-safe file IO into
PersistenceIOand key-index merge intoPersistenceHelpers - Replaced exception-driven
JSON.decode!with explicitJSON.decodein compatibility backend
Fixed
- Migration publish now uses backup-and-swap for both empty and existing targets
- Nil propagation in compatibility JSON decoders for malformed input
- Credo nesting depth violation in
read_data
[0.1.0-alpha.4] - 2026-03-19
Major persistence architecture overhaul. The library previously used a generic Elixir term serializer on top of JSON — encoding atoms, structs, and tuples with custom tags — which caused fresh-VM crashes, atom table exhaustion risks, and ongoing allowlist maintenance. This release separates persistence into two backends: a durable ETF-based native backend (recommended) and a Baileys-compatible JSON backend rewritten with explicit codecs. Also fixes several Elixir antipatterns across the codebase.
Added
NativeFilePersistence— durable ETF-based file backend with crash-safe writes, recommended for Elixir-first deploymentsPersistenceMigration— staged atomic migration from compatibility JSON to native formatPersistenceIO— shared crash-safe file write primitives (temp + fsync + rename + dir fsync)- Format versioning and manifest support for both persistence backends
- Cross-backend contract tests and fresh-VM regression tests for persistence decoding
Auth.Persistencebehaviour extended with context-aware optional callbacks
Changed
FilePersistencerewritten with explicit Baileys-shaped JSON codecs — no more generic tagged Elixir term serialization- Docs and README recommend
NativeFilePersistenceas default for Elixir apps
Fixed
- Atom table exhaustion risk from
String.to_atomon untrusted disk data - Flaky CI test from PBKDF2 timing — iteration count now injectable at socket startup
- Quadratic list appending in protobuf decoder, history sync, message sender, and other hot paths
- Nil-punning (
value && value.field) replaced with pattern matching across feature modules - Dialyzer and Credo strict warnings resolved
[0.1.0-alpha.3] - 2026-03-19
Changed
- Event emission no longer blocks callers on slow subscribers
- Protocol and connection logging demoted from warning to debug level
- Improved binary node encoding and decoding performance
Fixed
- Programmer errors in Noise protocol functions are no longer silently swallowed
- Rust NIF error handling hardened to eliminate panic paths
[0.1.0-alpha.2] - 2026-03-19
Initial alpha release.
Added
- Connect to WhatsApp Web via the multi-device protocol with QR code or phone number pairing
- End-to-end encrypt all messages via a pure Elixir Signal Protocol implementation
- Send and receive 27+ message types: text, images, video, audio, documents, stickers, contacts, location, polls, reactions, forwards, edits, deletes, and more
- Upload and download encrypted media with AES-256-CBC and HKDF-derived keys
- Manage groups and communities: create, update, leave, add/remove/promote/demote participants, invite flows
- Subscribe to and manage newsletters
- Send presence updates and subscribe to contact presence
- Sync app state (archive, mute, pin, star, read) across linked devices via the Syncd protocol with LTHash integrity verification
- Fetch and manage business profiles, catalogs, collections, and orders
- Reject calls and create call links
- Manage privacy settings and blocklists
- Persist credentials to disk via
FilePersistencewith automatic reconnection - Encode and send WAM analytics buffers for Baileys wire parity
- Emit telemetry events under the
[:baileys_ex]prefix for connection, messaging, media, and NIF operations - Noise Protocol transport encryption via
snowRust NIF - XEdDSA signing via
curve25519-dalekRust NIF :gen_statemconnection state machine with automatic reconnection- ETS-backed concurrent signal key store
- Supervised process tree with
:rest_for_onestrategy