fix(tctoken): address all 7 PR #386 review findings
All 7 inline review comments validated as real bugs (zero false positives). Fixes applied: #1 Codex P1 (CRITICAL) — process-message.ts: storeTcTokensFromHistorySync ran BEFORE storeLIDPNMappings. On a fresh device with empty mapping cache, resolveTcTokenJid(PN) returned null for every chat → tokens stored under PN keys → send path resolves PN→LID, misses them → error 463 on first multi-device send. Defeated the purpose of the whole TIER 1.3 backport. Reordered: mappings first, tctokens after. #3 Copilot (MAJOR) — messages-send.ts: PSA/bot gating relied on `destinationJid === PSA_WID` (which is '0@c.us') and isJidBot (also @c.us-only), but destinationJid arrives normalized to @s.whatsapp.net. Issuance was leaking to PSA/bot contacts. Replaced with `!isRegularUser(destinationJid)` — the same Wid. isRegularUser() port the store path already uses, which handles @c.us / @s.whatsapp.net / @hosted / @hosted.lid / @lid uniformly. #4 Copilot (MAJOR) — tc-token-utils.ts: resolveIssuanceJid used strict isLidUser() so hosted LIDs (@hosted.lid) skipped resolution, and passed un-normalized JIDs to getLIDForPN (which early-returns unless isAnyPnUser, breaking @c.us inputs). Fixed by normalizing upfront with jidNormalizedUser and using isAnyLidUser/isAnyPnUser. Added 3 new tests covering @c.us → normalize → resolve, hosted.lid passthrough on issueToLid=true, and hosted.lid → getPNForLID call on issueToLid=false. #6 Copilot (MAJOR) — messages-recv.ts: scheduleTcTokenIndexSave wrote the index from the in-memory tcTokenKnownJids set, OVERWRITING any JIDs added by cross-layer paths (messages-send issuance, process-message history sync) that wrote via buildMergedTcTokenIndexWrite without updating the in-memory set. Each debounced flush silently dropped those JIDs. Same bug in the connection.update flush path. Both now use buildMergedTcTokenIndexWrite so the persisted index is preserved. #7 CodeRabbit Minor — process-message.ts: storeTcTokensFromHistorySync's loop captured `existing` once before the loop, so when two candidates resolved to the same storageJid (PN+LID alias collision through resolveTcTokenJid, or duplicate chunks across syncs), the second iteration read the original persisted entry instead of the in-progress entries[storageJid] from iter 1. A lower-ts entry could overwrite a higher-ts one. Fixed with `entries[c.storageJid] ?? existing[c.storageJid]`. #5 Copilot (DEFENSIVE) — identity-change-handler.ts: onBeforeSessionRefresh was called outside the try/catch around assertSessions. A throwing consumer callback would abort identity-change recovery and prevent the session refresh entirely. Wrapped in try/catch with warn-log; assertSessions still runs. #2 Copilot (TYPO) — messages-recv.ts: 'racets' → 'races' in the reissueTcTokenAfterIdentityChange docstring. Tests: 35/35 suites, 824/824 (+3 new for resolveIssuanceJid normalization). Zero diff in src/Utils/messages.ts (carousel/buttons/lists), src/Socket/groups.ts, WAProto/* — customizations untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,8 @@ import type { BinaryNode } from '../WABinary'
|
||||
import {
|
||||
getBinaryNodeChild,
|
||||
getBinaryNodeChildren,
|
||||
isAnyLidUser,
|
||||
isAnyPnUser,
|
||||
isHostedLidUser,
|
||||
isHostedPnUser,
|
||||
isJidMetaAI,
|
||||
@@ -141,6 +143,11 @@ export async function resolveTcTokenJid(
|
||||
* the LID; when off, it goes to the PN. Returns the original JID if no
|
||||
* mapping is found in either direction.
|
||||
*
|
||||
* Normalizes the JID upfront and uses the `isAny*` helpers so callers can pass
|
||||
* `@c.us`, `@s.whatsapp.net`, `@hosted`, `@hosted.lid`, `@lid` or device-specific
|
||||
* forms — `LIDMappingStore.getLIDForPN` early-returns unless `isAnyPnUser`,
|
||||
* so unnormalized inputs would silently bypass routing.
|
||||
*
|
||||
* Reference: WAWebTrustedContactsManager.issuePrivacyTokens
|
||||
*/
|
||||
export async function resolveIssuanceJid(
|
||||
@@ -149,19 +156,22 @@ export async function resolveIssuanceJid(
|
||||
getLIDForPN: (pn: string) => Promise<string | null>,
|
||||
getPNForLID?: (lid: string) => Promise<string | null>
|
||||
): Promise<string> {
|
||||
const normalized = jidNormalizedUser(jid)
|
||||
|
||||
if (issueToLid) {
|
||||
if (isLidUser(jid)) return jid
|
||||
const lid = await getLIDForPN(jid)
|
||||
return lid ?? jid
|
||||
if (isAnyLidUser(normalized)) return normalized
|
||||
if (!isAnyPnUser(normalized)) return normalized
|
||||
const lid = await getLIDForPN(normalized)
|
||||
return lid ?? normalized
|
||||
}
|
||||
|
||||
if (!isLidUser(jid)) return jid
|
||||
if (!isAnyLidUser(normalized)) return normalized
|
||||
if (getPNForLID) {
|
||||
const pn = await getPNForLID(jid)
|
||||
return pn ?? jid
|
||||
const pn = await getPNForLID(normalized)
|
||||
return pn ?? normalized
|
||||
}
|
||||
|
||||
return jid
|
||||
return normalized
|
||||
}
|
||||
|
||||
type TcTokenParams = {
|
||||
|
||||
Reference in New Issue
Block a user