Changed
- CI now runs the dashboard unit tests, and re-runs the client-SDK suites when a server DTO or the engine interface changes (not only on SDK edits), so contract drift is caught at its source. (#478)
- The Postgres connection pool now applies query/connection timeouts (
statement_timeout,idleTimeoutMillis,connectionTimeoutMillis) on the runtime connection, so a stuck query or a saturated pool fails fast instead of hanging requests. The migration connection keeps idle/connection timeouts but neverstatement_timeout, so a longCREATE INDEXis not aborted. Env-tunable (DATABASE_STATEMENT_TIMEOUT_MS,DATABASE_IDLE_TIMEOUT_MS,DATABASE_CONNECTION_TIMEOUT_MS), conservative defaults,0disables; SQLite is unaffected. (#480)
Fixed
- A plugin whose enable failed after it had already subscribed hooks no longer leaves stale hook registrations behind; a later successful enable could otherwise dispatch each event to the plugin more than once. (#477)
- The WebSocket
message.ackevent now carries the same{ id, messageId, status, ack }shape over the socket as the matching webhook does — the socket previously omittedidand the legacyack. (#477) - Reconnect timers are no longer stacked when two disconnects arrive back-to-back, and a terminal engine failure now cancels any pending reconnect so a
FAILEDsession cannot be resurrected by a stale timer. (#477) - The dashboard recovers from a stale lazy-loaded chunk after a redeploy with a single guarded reload instead of replacing the whole UI with the error screen; the Content-Security-Policy
img-srcnow allowsblob:so the outgoing image-attachment preview renders. (#477) - The Baileys engine's number-check (
GET /sessions/:id/contacts/check/:number) now returns a neutral<phone>@c.usid, matching the whatsapp-web.js engine, instead of a raw@s.whatsapp.netid. (#477) - The data export/import now includes the
lid_mappingsresolution cache, so a backup/restore or a SQLite↔PostgreSQL migration no longer drops it. (#477) - The JavaScript client SDK applies the JSON
Content-TypeandX-API-Keyafter caller-supplied headers, so they can no longer be overridden bydefaultHeaders(matching the Python and PHP SDKs); an unfollowed redirect (HTTP status0) now raises a clear error instead ofOpenWA API 0. (#478) - The infrastructure status endpoint reports the active S3 bucket when storage is in S3 mode, instead of only the unused local media path. (#478)
- The migration CLI now honors the dashboard-written
data/.env.generated, somigration:run:prodtargets the configured database (e.g. PostgreSQL) instead of silently defaulting to SQLite. (#479) - The first-run generated config writes
STORAGE_LOCAL_PATH(the key the backend reads) instead of the deadSTORAGE_PATH. (#479) - The Sessions page now keeps the shared dashboard cache in sync, so creating/stopping/deleting a session no longer leaves the Dashboard showing stale session counts or status until a refresh. (#479)
Security
- The startup banner prints the full admin API key only when it is first created; on subsequent boots the key is masked, so the live credential is not re-written to the log pipeline on every restart. (#478)
- The production secret guard now rejects a placeholder
REDIS_PASSWORD(e.g.changeme); an empty/unset password is still allowed so passwordless private-network Redis continues to boot. (#478) - The published PHP SDK package no longer ships its test suite, PHPUnit config, or
composer.lock. (#478) - The production weak-secret guard now also rejects the common defaults
123456,qwerty,root,test, anddemo. Matching stays an exact full-value comparison, so a strong secret that merely contains one of these words is not blocked. (#480) - The gateway now logs a startup warning when
API_KEY_PEPPERis unset in production (stored API-key hashes then use plain SHA-256). Advisory only — enabling a pepper invalidates existing key hashes, so it stays opt-in and is never enforced. (#480)