A reliability and correctness patch. Engine: Baileys reconnect no longer leaks its socket, and a session
keeps its operator config even if the engine plugin fails to enable before onLoad. Templates: names are now
unique per session (deterministic resolve, 409 on duplicate, with a lossless de-duplicating migration).
Tooling: the migration CLI can manage the main (auth/audit) connection, and the Docker image ships procps
so a missing-ps cleanup path can't crash the container. One behavior change to note: PUT /settings
now returns 501 — settings are environment-derived and read-only at runtime — instead of a misleading 200
(no dashboard flow uses the write).
Added
- CLI migration commands for the main (auth/audit) connection. The app runs the main connection as a separate
always-SQLite connection, but the migration CLI only managed the data connection. Newmigration:run:main,
migration:generate:main,migration:show:main, andmigration:revert:mainscripts (plus:prodvariants) manage
it — needed whenMAIN_DATABASE_SYNCHRONIZE=falsedisables boot auto-migration. Purely additive. (#364)
Changed
PUT /settingsnow returns501 Not Implementedinstead of a misleading200. Settings are derived from
environment variables and consumed at boot (andConfigServiceis immutable at runtime), so the previous handler
mutated an in-memory copy and reported success while persisting and applying nothing. The endpoint is now honest
about being read-only;GET /settingsand the ADMIN guard are unchanged, and no dashboard flow uses the write. (#364)
Fixed
- Baileys reconnect no longer leaks the previous socket. An internal (transient-drop) reconnect overwrote the live
socket without tearing the old one down, leaking its WebSocket and event listeners on every reconnect. The previous
socket is now detached and ended before its replacement is created. (#364) - Engine sessions keep operator config when the engine plugin fails to enable. The engine config blob is now also
supplied at plugin construction, sosessionDataPath/executablePath/authDirstill apply if a plugin fails to
enable before itsonLoadruns (they previously dropped silently to defaults). The healthy path is unchanged. (#364) - Template names are unique per session. A composite unique index makes resolve-by-name deterministic and rejects
duplicate names with409 Conflict; a migration losslessly de-duplicates any pre-existing collisions (keeps the
earliest, renames the rest) before adding the index. The{{var}}/{var}template-syntax split is unchanged and
still tracked in #69. (#364) - Container no longer crashes on browser-cleanup paths when
psis missing. The production image is based on
node:22-slim, which omits thepsbinary; cleanup code that shells out tops(e.g. process-tree kills) fails
withspawn ps ENOENT, and that unhandled child-process error can take down the whole Node runtime. The image now
installsprocps. This does not change the underlying browser-init timeout — it only prevents the missing-ps
cleanup failure from being fatal. (#359)
Documentation
- Documented chat-history limits. A new guide explains the difference between the local message-history
endpoint (GET /sessions/:id/messages, reads OpenWA's database) and the bounded live-history endpoint
(GET /sessions/:id/messages/:chatId/history, asks the engine): live history defaults tolimit=50and is
clamped to[1, 100](solimit=999returns 100, not the full account history), and is a recent-history
helper rather than a complete server-side import. (#356)