The ingester now starts on demand when a WhatsApp inbox exists, so an
install without WhatsApp boots even if Redis is down. Sends retry on 429
and 5xx, oversized media stores a placeholder, and inbox lookup failures
no longer read as "no inbox".
Meta accepts only one media per message and sends one status webhook per
message id, so a reply with 3 files is now sent as 3 requests from the reply
box instead of one message that half-succeeded. Drops the partial-send
tracking, markers and retry-attachments button that existed to paper over it.
Status events arriving before their message were silently dropped. Contacts with no email/ext_id could accumulate orphan rows on retry. Corrupt inbox configs were skipped without logging.
Move WhatsApp inbound off the in-memory worker pool onto a new Redis Streams queue (internal/streamqueue): at-least-once, reclaim of orphaned entries, dead-letter for poison entries, panic-safe. The webhook verifies the signature from the in-memory inbox and 200-ACKs only after a successful enqueue, so a DB blip or restart no longer drops messages. The worker honors context cancellation for fast shutdown, dedups before downloading media, and routes template status updates by WABA.