feat: integrate tctoken lifecycle with expiration, pruning and re-issuance (PR #2339)

Surgical integration of WhiskeySockets/Baileys PR #2339 preserving all
InfiniteAPI customizations (biz nodes, DSM skip, carousel, Prometheus,
circuit breaker, LID mapping, CTWA recovery, identity debounce).

Changes:
- tc-token-utils.ts: rolling bucket expiration (28d/4 buckets), LID
  resolution, monotonicity guard, storeTcTokensFromIqResult parser
- messages-send.ts: proactive fetch if missing/expired, fire-and-forget
  re-issuance on bucket boundary, getPrivacyTokens timestamp param
- messages-recv.ts: persistent JID index for cross-session pruning,
  pruneExpiredTcTokens on connect (max 1x/24h), session_refreshed
  re-issuance, error 463/479 handling in handleBadAck
- chats.ts: self-detection in profilePictureUrl, LID resolver in
  presenceSubscribe
- socket.ts: granular stream error logging (device_removed, xml, ack)
- Auth.ts: senderTimestamp field on tctoken type
- Types/index.ts: sessionInvalidated = 516 disconnect reason
- decode-wa-message.ts: SERVER_ERROR_CODES constant (463, 479, 421, 475)
- generics.ts: enhanced getErrorCodeFromStreamError with device_removed
- baileys-logger.ts: logTcToken function following [BAILEYS] prefix pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Renato Alcara
2026-02-15 20:53:27 -03:00
parent 938c6aaa49
commit 08793904e2
10 changed files with 506 additions and 55 deletions
+60
View File
@@ -947,4 +947,64 @@ export function logLidMapping(
}
}
/**
* Log tctoken lifecycle events
*
* @example
* logTcToken('fetch', { jid: '5511999999999@s.whatsapp.net' })
* // Output: [BAILEYS] 🔑 TcToken fetch → 5511999999999@s.whatsapp.net
*
* logTcToken('expired', { jid: '5511999999999@s.whatsapp.net', age: '32d' })
* // Output: [BAILEYS] 🔑 TcToken expired → 5511999999999@s.whatsapp.net { age: 32d }
*/
export function logTcToken(
event: 'stored' | 'expired' | 'fetch' | 'fetched' | 'reissue' | 'reissue_ok' | 'reissue_fail' | 'prune' | 'error_463' | 'error_479' | 'attached',
data?: Record<string, unknown>,
sessionName?: string
): void {
if (!isBaileysLogEnabled()) return
const prefix = sessionName ? `[BAILEYS] [${sessionName}]` : '[BAILEYS]'
const jid = data?.jid ? `${data.jid}` : ''
const rest = data ? { ...data } : undefined
if (rest) delete rest.jid
const extraStr = rest && Object.keys(rest).length > 0 ? ' ' + formatLogData(rest) : ''
switch (event) {
case 'stored':
console.log(`${prefix} 🔑 TcToken stored${jid}${extraStr}`)
break
case 'expired':
console.log(`${prefix} 🔑 TcToken expired${jid}${extraStr}`)
break
case 'fetch':
console.log(`${prefix} 🔑 TcToken fetch${jid}${extraStr}`)
break
case 'fetched':
console.log(`${prefix} 🔑 TcToken fetched${jid}${extraStr}`)
break
case 'reissue':
console.log(`${prefix} 🔑 TcToken reissue${jid}${extraStr}`)
break
case 'reissue_ok':
console.log(`${prefix} 🔑 TcToken reissue OK${jid}${extraStr}`)
break
case 'reissue_fail':
console.log(`${prefix} 🔑 TcToken reissue failed${jid}${extraStr}`)
break
case 'prune':
console.log(`${prefix} 🔑 TcToken prune${extraStr}`)
break
case 'attached':
console.log(`${prefix} 🔑 TcToken attached${jid}${extraStr}`)
break
case 'error_463':
console.log(`${prefix} ⚠️ TcToken missing (463)${jid}${extraStr}`)
break
case 'error_479':
console.log(`${prefix} ⚠️ TcToken smax-invalid (479)${jid}${extraStr}`)
break
}
}
export default BaileysLogger