225b692b7c
Backports the 4 critical/major gaps the audit identified vs Baileys PR #2339, surgically and without touching carousel, buttons, lists, LID/PN normalization, Bad MAC handling or app-state-sync code. TIER 1 — eliminates production error 463 in two scenarios: - onBeforeSessionRefresh callback (identity-change-handler.ts): invoked BEFORE assertSessions for an existing-session identity change. Skipped for self / companion / debounced / offline paths. - reissueTcTokenAfterIdentityChange (messages-recv.ts): fire-and- forget, runs IN PARALLEL with the session refresh (not after) and preserves the existing senderTimestamp so the contact gets a fresh token in the same bucket window. Replaces the fork's previous post-refresh reissue, which raced with the next outbound send. - storeTcTokensFromHistorySync (process-message.ts): extracts tcToken / tcTokenTimestamp / tcTokenSenderTimestamp from history- sync chats and persists them BEFORE messaging-history.set fires, so multi-device login doesn't lose tokens. Strict > monotonicity (matches upstream). TIER 2 — server AB-prop gating: - serverProps in chats.ts: parses 10518 (privacy_token_sending_on_ all_1_on_1_messages), 9666 (profile_scraping_privacy_token_in_ photo_iq), 14303 (lid_trusted_token_issue_to_lid). Defaults match WA Web (true / true / false). Exported in the socket return so messages-send/messages-recv can read it. - profilePictureUrl gates inclusion on serverProps.profilePicPrivacyToken. - 1:1 send gates attach on serverProps.privacyTokenOn1to1. - resolveIssuanceJid (tc-token-utils.ts): routes issuance to LID vs PN based on AB prop 14303. Used by both the post-send fire- and-forget and the identity-change reissue. TIER 3 — defensive hardening: - isRegularUser (tc-token-utils.ts): Wid.isRegularUser() port that rejects PSA WID '0', bot phone patterns (1313555XXXX / 131655500XX) and MetaAI (@bot). storeTcTokensFromIqResult drops malformed notifications before writing. Send-side issuance also gates on PSA / bot / protocol-message exclusions (matches WA Web's TcTokenChatAction). - inFlightTcTokenIssuance Set (messages-send.ts): dedupes fire-and-forget issuance when several rapid sends to the same contact happen before senderTimestamp persists. Distinct from the existing tcTokenFetchingJids (which dedupes inbound fetches). - TC_TOKEN_INDEX_KEY exported from tc-token-utils.ts and re-used in messages-recv.ts (was previously inlined as a separate local const — risk of divergence on rename). Same value '__index'. - readTcTokenIndex / buildMergedTcTokenIndexWrite: cross-session prune index helpers so issuance / history-sync / pruner all merge with the persisted set instead of clobbering each other. Audit findings explicitly addressed: - TC_TOKEN_INDEX_KEY duplication: unified via import. - Index write race (prune vs issuance): documented; worst case is a one-cycle delay of pruning, no data loss. - Identity-change reissue + post-send issuance double-fire: bounded by bucket coalescing — both use the same senderTimestamp window so even if both IQs go out, the persisted state converges. Tests: - identity-change-handling: 2 new cases covering onBeforeSessionRefresh ordering (fires BEFORE assertSessions) and skip behavior on no_identity / offline / self. - tc-token: 32 new cases across isRegularUser (PSA / bot / MetaAI / hosted), resolveIssuanceJid (AB prop 14303 ON/OFF, missing mappings), TC_TOKEN_INDEX_KEY ('__index' frozen), readTcTokenIndex (corruption / empty / sentinel filter), buildMergedTcTokenIndexWrite (merge / sentinel drop / empty), storeTcTokensFromIqResult gating (PSA / bot / MetaAI rejection, fallbackJid storage routing, monotonicity). Suite: 35/35, 821/821 passing (+115 vs baseline 706). Customizations untouched: zero diff in src/Utils/messages.ts (carousel generators), src/Socket/groups.ts, WAProto/*. Confirmed via grep for carousel/button/interactive/nativeFlow/list/biz/album in the modified files — no matches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>