e1e3d88a1c
* feat: centralized LID→PN normalization for all emitted events WhatsApp's server increasingly uses LID (Linked ID) as the primary addressing format. Consumers expect phone numbers (PN), not opaque LID identifiers. This adds comprehensive LID→PN resolution across all ev.emit() paths so downstream consumers always receive PN. Key changes: - Add resolveLidToPn() and normalizeKeyLidToPn() centralized helpers in process-message.ts for consistent LID→PN resolution - normalizeMessageJids() fast path: use alt JID directly from stanza attributes (zero I/O, eliminates race condition with LIDMappingStore) - Await storeLIDPNMappings() before normalization in message receipt flow (was fire-and-forget, could race with subsequent getPNForLID) - Normalize LID→PN in all event emission points: * messages.upsert (keys, nested reaction/poll keys, participantAlt) * presence.update (jid + participant) * message-receipt.update (key + userJid) * contacts.update (picture notifications) * blocklist.update (blocklist JIDs) * call events (chatId, from) * group metadata (participants, owner, subjectOwner) * group notifications (acting participant, add/remove/promote/demote) * newsletter notifications (author, user JIDs) * sync actions (mutation index normalization) - Make handlePresenceUpdate and handleGroupNotification async to support await on LID resolution - Add normalizeGroupMetadata() helper in groups.ts for all extractGroupMetadata call sites Performance: ~0.01ms per message (LRU cache hit). No impact on message sending. First-contact resolution ~2-5ms (one-time per contact). * fix: normalize LID→PN in handleBadAck, media retry, and PDO recovery Additional leak points found during final audit: - handleBadAck: key.remoteJid from ack stanza could be LID - messages.media-update: media retry key JIDs not normalized - CTWA PDO recovery: webMessageInfo.key from phone response not normalized * fix: address PR review — parallelize LID resolution, use helper consistently - normalizeGroupMetadata: resolve participant LIDs with Promise.all instead of sequential loop (perf on large groups) - handleCall: resolve participant JIDs with Promise.all - handleBadAck: use normalizeKeyLidToPn() helper instead of manual resolveLidToPn + assignment (consistency with other code paths) - CB:relay: resolve callCreator LID→PN before emitting