inboundMessageIds was only ever cleared whole (on disconnect), so it grew
without bound proportional to total inbound message volume over a
connection's lifetime. Now capped at 5000 entries, evicting the oldest
(Set preserves insertion order) once exceeded.
withTimeout's internal setTimeout wasn't unref'd, unlike every other timer
in this file (qrTimer, reconnectTimer, the lease timer) — a pending
lookup/send timeout could keep the event loop alive if the process ever
tried to exit gracefully without an explicit process.exit().
Found via a full-project audit.
Tracks the app that was already in place (capture, treatment, outreach,
WhatsApp integration, server, frontend, tests, docs) so future feature
work can branch and use isolated worktrees.