Two issues in the campaign worker path:
1. runCampaignQueue had none of the safety rails run.mjs's automatic sender
has: no outreach.ativo gate, no business-hours window, no jitter between
sends. A campaign left "rodando" would send around the clock even with
outreach disabled or outside business hours, and would hammer the same
WhatsApp number back-to-back. Added the same outreach.ativo/horaInicio/
horaFim checks (duplicated, not imported, to keep the modules
independent) plus a randomized 3-8s jitter between real send attempts.
Sleep delay is injectable via an optional sleepMs param so tests can
pass sleepMs: 0.
2. evaluateCampaignHealth mutated state (via applyPause) on every call,
including from the read-only GET /api/campaigns/:id/saude route -- so
simply opening the campaign detail panel in the UI could silently pause
a healthy-looking campaign. Split it into a pure evaluateCampaignHealth
(computes {pause, reason}, never writes) and a new applyCampaignHealth
(evaluates, then persists the pause if warranted). The worker now calls
applyCampaignHealth; the GET /saude route keeps calling the pure
evaluateCampaignHealth.
Tests: worker sends nothing with outreach.ativo=false or outside business
hours; evaluateCampaignHealth confirmed not to mutate status even when it
would return pause:true; existing mutation assertions moved onto
applyCampaignHealth.