What's Fixed
Now Playing Row Not Always Showing Active Transmission
The Now Playing row would go blank between transmissions — sometimes for 1–2+ seconds — even when the next call was already queued and ready to play. The emit that updates the UI was only fired after decodeAudioData completed (async), on top of the existing 1-second inter-call gap timer. The call event is now emitted immediately when the next call is dequeued, before decryption and decoding begin, so the metadata row populates with no visible blank period.
Duplicate Alerts for the Same Call
Multiple alert cards were appearing for the same incident. The server-side deduplication check included the exact keyword set (keywordsMatched), so ["FIRE"] and ["FIRE","MEDICAL","BREATHING"] both inserted as separate rows. The check now matches by callId only — if an alert exists for that call, the keywords are merged and the existing row is updated instead of inserting a new one. The web client also deduplicates the Recent Alerts embed by callId as a safety net for any existing duplicate rows.