When the relay is running, `warelay send` and `warelay heartbeat` now
communicate via Unix socket IPC (~/.warelay/relay.sock) to send messages
through the relay's existing WhatsApp connection.
Previously, these commands created new Baileys sockets that wrote to the
same auth state files, corrupting the Signal session ratchet and causing
the relay's subsequent sends to fail silently.
Changes:
- Add src/web/ipc.ts with Unix socket server/client
- Relay starts IPC server after connecting
- send command tries IPC first, falls back to direct
- heartbeat uses sendWithIpcFallback helper
- inbound.ts exposes sendMessage on listener object
- Messages sent via IPC are added to echo detection set
Bug fixes:
- Empty result field handling: Changed truthy check to explicit type
check (`typeof parsed?.text === "string"`) in command-reply.ts.
Previously, Claude CLI returning `result: ""` would cause raw JSON
to be sent to WhatsApp.
- Response prefix on heartbeat: Apply `responsePrefix` to heartbeat
alert messages in runReplyHeartbeat, matching behavior of regular
message handler.
Changed from 10 to 30 minutes to avoid false positives when
heartbeatMinutes is set to 10. The watchdog should be significantly
longer than the heartbeat interval to account for:
- Network latency
- Slow command responses
- Brief connection hiccups
With heartbeatMinutes=10, a 30-minute watchdog gives 3x buffer before
triggering auto-restart.
Fixes issue where unauthorized messages from +212652169245 (5elements spa)
triggered Bad MAC errors and silently killed the event emitter, preventing
all future message processing.
Changes:
1. Early allowFrom filtering in inbound.ts - blocks unauthorized senders
before they trigger encryption errors
2. Message timeout watchdog - auto-restarts connection if no messages
received for 10 minutes
3. Health monitoring in heartbeat - warns if >30 min without messages
4. Mock loadConfig in tests to handle new dependency
Root cause: Event emitter stopped firing after Bad MAC errors from
decryption attempts on messages from unauthorized senders. Connection
stayed alive but all subsequent messages.upsert events silently failed.