Commit Graph

2736 Commits

Author SHA1 Message Date
Renato Alcara 6003c2a8bc fix(signal): critical fixes for identity key detection based on code review
fix(signal): critical fixes for identity key detection based on code review
2026-01-30 10:00:16 -03:00
Claude 9ef56cc59d docs(signal): improved documentation and comments - batch 3
Low Priority Fixes based on Copilot code review:

1. Clarified IdentitySaveResult.changed comment
   - Explicitly documents that false means "new OR unchanged"
   - Explains to use isNew to distinguish between cases
   - Documents that previousFingerprint only present when changed

2. Improved fingerprint documentation
   - Documents that fingerprint is 64 hex characters (full SHA-256)

3. Added comments to varint parsing
   - Documents that varint too long could indicate malformed/malicious message
   - Added comment for incomplete varint case

https://claude.ai/code/session_01SWAcNuGZQmEKyBPYkBhVHg
2026-01-30 12:34:14 +00:00
Claude 81cf601250 fix(signal): improved security and robustness - batch 2
Medium Priority Fixes based on Copilot code review:

1. Use full SHA-256 fingerprint (64 characters)
   - Previously truncated to 32 characters (128 bits)
   - Now uses full 256-bit hash for cryptographic consistency
   - Aligns with standard security practices

2. Add bounds checking in protobuf parsing
   - Added bounds check after offset += length for length-delimited fields
   - Added bounds check for 64-bit and 32-bit fixed fields
   - Prevents reading beyond buffer bounds with malformed messages
   - Defense in depth against malformed/malicious PreKeyWhisperMessages

https://claude.ai/code/session_01SWAcNuGZQmEKyBPYkBhVHg
2026-01-30 12:33:33 +00:00
Claude 3dcdc7be69 fix(signal): critical fixes for identity key detection - batch 1
High Priority Fixes based on Copilot/Codex code review:

1. Propagate errorCode to shouldRecreateSession (CRITICAL)
   - Extract error attribute from retry node
   - Pass errorCode to shouldRecreateSession in both sendRetryRequest and sendMessagesAgain
   - Without this fix, MAC error detection was NOT working
   - Now immediate session recreation works for MAC errors

2. Use .unref() on metrics interval
   - Prevents blocking process exit in short-lived scripts/tests
   - Interval no longer keeps event loop alive unnecessarily

3. Reset circuit breaker regardless of state
   - Previously only reset when isOpen()
   - Now resets in any state (open, half-open, or closed with accumulated failures)
   - Ensures clean slate after identity change detection

https://claude.ai/code/session_01SWAcNuGZQmEKyBPYkBhVHg
2026-01-30 12:32:56 +00:00
Renato Alcara c8eaae4b64 feat: implement identity key change detection for Signal protocol
feat: implement identity key change detection for Signal protocol
2026-01-30 09:30:11 -03:00
Claude 164c7fbe93 feat: implement identity key change detection for Signal protocol
This implements the functionality from WhiskeySockets/Baileys PR #2307
with enhanced improvements:

## Core Features
- Extract identity key from PreKeyWhisperMessage before decryption
- Detect when a contact reinstalls WhatsApp (identity key changes)
- Automatically delete old session and recreate on identity change
- Trust On First Use (TOFU) for new contacts

## Improvements over original PR
- LRU cache for identity keys (1000 keys, 30min TTL)
- Integration with existing Circuit Breaker (reset on identity change)
- New Prometheus metrics for observability:
  - signal_identity_changes_total (new/changed)
  - signal_mac_errors_total
  - signal_session_recreations_total
  - signal_identity_key_cache_hits/misses
  - signal_identity_key_operations_ms (histogram)
- New 'identity.changed' event for applications to notify users
- RetryReason enum with MAC_ERROR_CODES and SESSION_ERROR_CODES
- Robust protobuf parsing with validation
- Structured logging with fingerprints

## Technical Details
- Manual protobuf parsing (compatible with any Signal implementation)
- SHA-256 fingerprints for key identification
- Atomic session deletion + identity key save
- Best-effort identity tracking (doesn't fail decryption on errors)

Resolves permanent MAC errors when contacts reinstall WhatsApp.

https://claude.ai/code/session_01SWAcNuGZQmEKyBPYkBhVHg
2026-01-30 03:35:18 +00:00
Renato Alcara 228ea998bd feat: add biz node injection for catalog messages
feat: add biz node injection for catalog messages
2026-01-27 22:01:34 -03:00
Renato Alcara e21c54822a feat: add biz node injection for catalog messages
- Catalog messages now receive biz node injection (previously skipped)
- Catalog messages skip bot node (like carousels)
- Added debug logging for catalog message handling
- Testing if biz node helps catalog products render properly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 21:59:42 -03:00
Renato Alcara ee1a93d095 fix: não injetar biz node para mensagens de catálogo
fix: não injetar biz node para mensagens de catálogo
2026-01-27 21:16:50 -03:00
Renato Alcara 019ac36a78 fix: não injetar biz node para mensagens de catálogo
Adicionada função isCatalogMessage() para detectar mensagens de
catálogo (catalog_message, single_product, product_list).

Mensagens de catálogo funcionam apenas com o formato proto
viewOnceMessage > interactiveMessage > nativeFlowMessage,
sem necessidade de injeção de biz node.

Isso corrige o error 405 ao enviar lista de produtos.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 21:14:38 -03:00
Renato Alcara 2aaa4486ad fix: não injetar biz node para productList do catálogo
fix: não injetar biz node para productList do catálogo
2026-01-27 19:53:39 -03:00
Renato Alcara df924dae40 fix: não injetar biz node para productList do catálogo
Mensagens de lista de produtos do catálogo WhatsApp Business (PRODUCT_LIST)
não precisam de injeção de biz node. O biz node estava causando erro 405.

- Retorna undefined em vez de 'native_flow' para PRODUCT_LIST
- Afeta apenas productList, não afeta carrossel de mídia

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 19:36:26 -03:00
Renato Alcara 87fcc247be debug: log full buttonParamsJson for diagnosing list menu issue
Added detailed logging to capture the full button structure including
parsed buttonParamsJson to help diagnose why list menus don't open.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 10:16:42 -03:00
Renato Alcara c084f138f2 fix: use native_flow for all interactive messages to avoid error 479
Testing showed that using type='list' for list messages (even those
using nativeFlowMessage with single_select) causes error 479 rejection.

All interactive message types (buttons, lists, carousels) now use
type='native_flow' in the biz node structure.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 10:13:20 -03:00
Renato Alcara f61084a46b debug: add logging for interactive message structure
Add detailed logging to diagnose list message detection issues.
Shows buttonType, hasListMessage, hasNativeFlow, and button names.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 10:00:49 -03:00
Renato Alcara 2532e8b7a4 fix: detect list-type nativeFlowMessage for correct biz node
Lists sent as nativeFlowMessage (with single_select/multi_select buttons)
still need type='list' in the biz node to work properly.

Added isListNativeFlow() function to detect list-type messages by checking
for single_select or multi_select button names.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 09:58:37 -03:00
Renato Alcara e1f744032a fix: use correct interactive type for list messages
For list messages, use type='list' instead of 'native_flow' in the
biz node structure. This allows the list button to open properly.

- native_flow messages: biz > interactive(type=native_flow) > native_flow
- list messages: biz > interactive(type=list) > list

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 09:40:04 -03:00
Renato Alcara 832a5c6e11 fix: use correct nested biz node structure for interactive messages
Changes the biz node from flat structure (biz > native_flow) to nested
structure (biz > interactive > native_flow) as used by Pastorini/Astra-Api.

Structure:
- biz: {}
  - interactive: { type: 'native_flow', v: '1' }
    - native_flow: { v: '9', name: 'mixed' }

This fixes error 479 that was breaking all interactive messages.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 09:26:54 -03:00
Renato Alcara 345c1b649a fix: remove bot node for carousels and restore ProductCarousel
fix: remove bot node for carousels and restore ProductCarousel
2026-01-27 00:56:40 -03:00
Renato Alcara a162caeff2 fix: remove bot node for carousels and restore ProductCarousel
- Fix carousel detection in getButtonType to return native_flow
- Add isCarouselMessage helper function
- Skip bot node injection for carousel messages (fixes error 479)
- Restore ProductCarouselCard and ProductCarouselMessageOptions types
- Restore generateProductCarouselMessage function
- Add productCarousel handler in generateWAMessageContent

The bot node with biz_bot='1' was causing error 479 for media carousels
because carousels are regular interactive messages, not bot messages.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 00:54:23 -03:00
Renato Alcara 148674ae4a Feature/product carousel
Feature/product carousel
2026-01-27 00:37:54 -03:00
Renato Alcara c20193041e style: fix indentation in imports and comments
- Fix ProductCarouselMessageOptions import indentation
- Fix productList comment indentation to align with else-if chain

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 22:16:50 -03:00
Renato Alcara 0d569752af fix(product-carousel): address PR review comments
- Replace catalogId with businessOwnerJid (required for catalog reference)
- Fix cards structure to use proper IInteractiveMessage[] format
- Each card now uses collectionMessage with bizJid and id
- Fix body reading from productCarousel.body (was reading from message.body)
- Remove 'as any' type casting by using correct proto types
- Update examples in types and function documentation

Addresses:
- Schema mismatch in carousel cards
- Body text being silently ignored when nested in productCarousel
- Improper type casting masking validation errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 18:32:45 -03:00
Renato Alcara 3d4fa3e007 feat: add Product Carousel message support
- Add ProductCarouselCard and ProductCarouselMessageOptions types
- Add productCarousel to AnyRegularMessageContent union type
- Create generateProductCarouselMessage function with validation
- Add productCarousel support in generateWAMessageContent
- Uses viewOnceMessage wrapper for iOS/Android compatibility
- Requires WhatsApp Business account with configured catalog

Usage:
await sock.sendMessage(jid, {
  productCarousel: {
    catalogId: '123456789',
    products: [
      { productId: 'produto_001' },
      { productId: 'produto_002' }
    ]
  },
  body: 'Confira nossos produtos!'
})

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 17:54:58 -03:00
Renato Alcara 8c8e228525 feat(messages): complete binary node wrappers for interactive messages
feat(messages): complete binary node wrappers for interactive messages
2026-01-26 12:51:55 -03:00
Renato Alcara d66fd14775 fix(messages): use precise check for private chats when injecting bot node
The previous condition `!isJidGroup()` was too broad and would incorrectly
inject bot nodes for status broadcasts, newsletters, and Meta AI bots.

Now uses explicit checks for private 1:1 user conversations:
- isPnUser() for @s.whatsapp.net JIDs
- isLidUser() for @lid JIDs
- @c.us suffix for legacy format
- Excludes bot JIDs with isJidBot()

This prevents potential issues with message delivery to non-user destinations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 11:49:12 -03:00
Renato Alcara 2b4685944a feat(messages): complete binary node wrappers for interactive messages
- Update getButtonType() to return 'native_flow' for modern nativeFlowMessage format
- Add product list detection (PRODUCT_LIST type returns native_flow)
- Implement getButtonArgs() with proper v:4 attributes for native_flow
- Add special attribute handling for payment flows (review_and_pay, mpm, review_order)
- Add bot node injection for private chats (required for interactive messages to render)
- Based on Itsukichan/Baileys and baileys_helpers implementation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 03:47:42 -03:00
Renato Alcara 75e1f8b466 feat(messages): add multi-product message support
feat(messages): add multi-product message support
2026-01-26 02:55:57 -03:00
Renato Alcara dbba298249 fix(messages): address PR #51 review comments
Fixes based on code review:

1. Fix sections vs productSections mismatch
   - Changed `productMsg.productList.sections` to `productMsg.productList.productSections`
   - Ensures consistency with ProductListMessageOptions type

2. Add section title validation
   - Each section must have a non-empty title string

3. Add productId validation for each product
   - Each product in a section must have a non-empty productId string

4. Add headerImage.productId validation
   - When headerImage is provided, productId must be a non-empty string

5. Remove fallback values (|| '')
   - Removed fallbacks for title and description
   - Let generateProductListMessage handle validation consistently

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 02:53:16 -03:00
Renato Alcara 6513f0c129 fix(messages): detect interactive messages inside viewOnceMessage
fix(messages): detect interactive messages inside viewOnceMessage
2026-01-26 02:50:56 -03:00
Renato Alcara d081afe02b fix(messages): check all 7 message types inside viewOnceMessage wrapper
Address PR review comment: the viewOnceMessage detection now checks
all 7 message types for consistency with direct message detection:
- buttonsMessage
- templateMessage
- listMessage
- buttonsResponseMessage
- listResponseMessage
- templateButtonReplyMessage
- interactiveMessage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 02:49:21 -03:00
Renato Alcara b5c5989ed8 fix(messages): detect interactive messages inside viewOnceMessage wrapper
The getButtonType function was not detecting interactive messages
when wrapped inside viewOnceMessage (the modern nativeFlowMessage format).

This fix adds detection for:
- viewOnceMessage > interactiveMessage
- viewOnceMessage > listMessage
- viewOnceMessage > buttonsMessage

When enableInteractiveMessages is true, the 'biz' node will now be
correctly injected for messages using the viewOnceMessage wrapper.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 02:27:22 -03:00
Renato Alcara 15a4cc2962 feat(messages): add multi-product message support
Add generateProductListMessage function for sending multiple products
from the WhatsApp Business catalog in a single message.

Features:
- ProductListMessageOptions type with full validation
- Support for product sections (categories)
- Optional header image from catalog
- Integration with sendMessage via 'productList' property
- Maximum 30 products limit per WhatsApp specs

Usage:
```typescript
const msg = generateProductListMessage({
  title: 'Our Best Sellers',
  description: 'Check out our products!',
  buttonText: 'View Products',
  businessOwnerJid: '5511999999999@s.whatsapp.net',
  productSections: [
    { title: 'Electronics', products: [{ productId: 'prod_001' }] }
  ]
})
await sock.sendMessage(jid, msg)
```

Note: Requires WhatsApp Business account with catalog configured.
Does NOT require Meta Business Manager integration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 02:02:54 -03:00
Renato Alcara 4faef75104 feat(buttons): add Native Flow buttons and carousel with viewOnceMess…
feat(buttons): add Native Flow buttons and carousel with viewOnceMess…
2026-01-26 00:03:15 -03:00
Renato Alcara 2ccdd0df01 fix(buttons): address all PR review comments
Fixes all 9 issues identified in PR #49 review:

## 1. Input Validation (formatNativeFlowButton)
- Added validateNonEmptyString helper function
- Validates required fields: text, url, copyText, id, phoneNumber
- Throws Boom error with descriptive message for empty/whitespace values

## 2-3. Async Media Processing (generateButtonMessage)
- Function is now async, returns Promise<WAMessageContent>
- Accepts optional MessageContentGenerationOptions parameter
- Calls prepareWAMessageMedia() for headerImage/headerVideo
- Throws error if media provided without mediaOptions

## 4-7. Async Media Processing (generateCarouselMessage)
- Function is now async, returns Promise<WAMessageContent>
- Uses Promise.all to process all card media in parallel
- Properly converts WAMediaUpload to IImageMessage/IVideoMessage

## 5. Mutual Exclusivity Validation
- generateButtonMessage: Throws if both headerImage AND headerVideo provided
- generateCarouselMessage: Throws if card has both image AND video

## 6. Empty Button Array Validation
- Each carousel card must have at least one button
- Throws descriptive error with card index

## 8. Updated Async Calls
- generateWAMessageContent now awaits generateButtonMessage
- generateWAMessageContent now awaits generateCarouselMessage
- Both pass MessageContentGenerationOptions for media processing

## 9. Type Support
- Functions accept MessageContentGenerationOptions as optional param
- Enables access to upload, mediaCache, logger options

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 23:57:07 -03:00
Renato Alcara e534202c6c feat(buttons): add call button, list messages and legacy functions
Extends the Native Flow implementation with additional features:

## New Button Type
- `CallButton` - `cta_call` type for initiating phone calls
  ```typescript
  { type: 'call', text: 'Call Us', phoneNumber: '+5511999999999' }
  ```

## New List Message Support
- `generateListMessage()` - Creates interactive list with single_select
- `nativeList` type for sendMessage integration
  ```typescript
  await sock.sendMessage(jid, {
    text: 'Choose:',
    nativeList: {
      buttonText: 'View Options',
      sections: [{ title: 'Section', rows: [...] }]
    }
  })
  ```

## Legacy Functions (for backward compatibility)
- `generateButtonMessageLegacy()` - Old buttonsMessage format
- `generateListMessageLegacy()` - Old listMessage format
⚠️ These are deprecated and may not work on all devices

## Other Improvements
- Added `merchantUrl` support for URL buttons
- Added `messageVersion` parameter (default: 2)
- Added `messageParamsJson` to nativeFlowMessage
- Created `NativeListSection` type to avoid conflict with legacy `ListSection`

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 23:47:58 -03:00
Renato Alcara 5d84974088 feat(buttons): add Native Flow buttons and carousel with viewOnceMessage wrapper
Implements modern WhatsApp button messages using the nativeFlowMessage format
wrapped in viewOnceMessage for better iOS/Android compatibility.

## New Types (Message.ts)

- `NativeButton` - Union type for all button types:
  - `UrlButton` - Opens a URL (cta_url)
  - `CopyButton` - Copies text to clipboard (cta_copy)
  - `QuickReplyButton` - Sends a quick reply (quick_reply)
- `ButtonMessageOptions` - Options for generateButtonMessage
- `CarouselCardInput` - Card definition for carousel
- `CarouselMessageOptions` - Options for generateCarouselMessage

## New Functions (messages.ts)

- `formatNativeFlowButton()` - Converts NativeButton to WhatsApp format
- `generateButtonMessage()` - Creates button message with viewOnceMessage wrapper
- `generateCarouselMessage()` - Creates carousel message with viewOnceMessage wrapper

## Usage via sendMessage

```typescript
// Native Flow Buttons
await sock.sendMessage(jid, {
  text: 'Choose an option:',
  nativeButtons: [
    { type: 'url', text: 'Visit Site', url: 'https://example.com' },
    { type: 'copy', text: 'Copy Code', copyText: 'ABC123' },
    { type: 'reply', text: 'Support', id: 'btn_support' }
  ],
  footer: 'Powered by InfiniteAPI'
})

// Native Carousel
await sock.sendMessage(jid, {
  text: 'Our Products',
  nativeCarousel: {
    cards: [
      { title: 'Item 1', body: 'Description', buttons: [...] },
      { title: 'Item 2', body: 'Description', buttons: [...] }
    ]
  }
})
```

## Direct Function Usage

```typescript
import { generateButtonMessage, generateCarouselMessage } from '@whiskeysockets/baileys'

const msg = generateButtonMessage({ buttons: [...], text: '...' })
await sock.sendMessage(jid, msg)
```

## Changes to Existing Code

- Carousel messages in generateWAMessageContent now use viewOnceMessage wrapper
- Added nativeButtons and nativeCarousel checks before legacy button handling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 23:24:50 -03:00
Ahmed Alwahib ffc019fb51 fix: align noise-handler buffer types for Baileys build (#2284)
* fix: align noise-handler buffer types for Baileys build

* Align noise handler buffer types

* Clarify noise handler buffer typing
2026-01-25 01:52:36 +02:00
Matheus Filype d514764686 feat: send unified session (#2294)
* fix: improve message resend logic by adding checks for message IDs

* Revert "fix: improve message resend logic by adding checks for message IDs"

This reverts commit c03f9d8e6fc6cbfbb9d1f8f67c169700e704213d.

* feat: add unified session handling and time constants

* refactor: improve socket variable destructuring and presence update logic

* fix: remove unnecessary semicolons in socket and time constants definitions

* fix: handle invalid server time offset parsing in makeSocket function
2026-01-25 01:51:47 +02:00
Renato Alcara f76bfbc0df fix(unified-session): resolve circular dependency with TimeMs
fix(unified-session): resolve circular dependency with TimeMs
2026-01-24 17:46:01 -03:00
Claude 7cb1df6d95 fix(unified-session): resolve circular dependency with TimeMs
The import of TimeMs from Defaults/index.ts caused a circular
dependency error in ESM:
"ReferenceError: Cannot access 'TimeMs' before initialization"

Solution: Define TimeMs constants locally in unified-session.ts
instead of importing from Defaults. This avoids the ESM module
initialization order issue.
2026-01-24 20:42:32 +00:00
Renato Alcara 49711891d0 fix: add isJidUser alias for compatibility
fix: add isJidUser alias for compatibility
2026-01-24 17:37:13 -03:00
Claude 6f9fd27321 fix: add isJidUser alias for zpro.io compatibility
Adds backward compatibility alias:
- isJidUser -> isPersonJid

This allows zpro.io and other consumers that depend on the old
isJidUser function name to continue working without changes.
2026-01-24 20:31:49 +00:00
Renato Alcara 050aea38c1 feat(telemetry): add unified_session to reduce unofficial client detection
feat(telemetry): add unified_session to reduce unofficial client detection
2026-01-24 17:24:11 -03:00
Claude d132e1cfd8 fix: address code review feedback (batch 2)
1. Add logger to writeCacheFile (version-cache.ts)
   - Now logs warnings when file write fails
   - Helps debugging in production environments

2. Sanitize logging in parseGroupResult (communities.ts)
   - Changed from info to debug level
   - Removed full node/groupNode dumps (sensitive data)
   - Now only logs nodeTag and groupId

3. Add input validation in parseNewsletterCreateResponse (newsletter.ts)
   - Validates response structure before destructuring
   - Adds fallback values for parseInt (prevents NaN)
   - Adds null checks for optional fields

4. Add health-status.ts module
   - getHealthStatus(): Full health check with circuit breakers, cache, memory
   - isHealthy(): Simple boolean for liveness probes
   - getSimpleHealthStatus(): Returns 'ok', 'degraded', or 'error'
   - Useful for k8s probes and monitoring dashboards
2026-01-24 20:04:53 +00:00
Claude 22eda03eb2 fix(unified-session): address code review feedback
Fixes 3 issues identified in code review:

1. ENV VAR PRECEDENCE: Changed DEFAULT_CONNECTION_CONFIG to use
   undefined for enableUnifiedSession, allowing env var
   BAILEYS_UNIFIED_SESSION_ENABLED to take precedence.
   Priority is now: explicit config > env var > default (true)

2. SINGLE INITIALIZATION: UnifiedSessionManager is now created
   only once, after sendNode is defined. This avoids:
   - Duplicate circuit breaker instances
   - State reinitialization
   - Unnecessary overhead and logs

3. CONTINUOUS TIME SYNC: serverTimeOffset is now updated on
   every received frame that contains a 't' attribute, not just
   on CB:success. This keeps the offset accurate even during
   long-running connections.
2026-01-24 19:14:02 +00:00
Claude 9f17567951 feat(telemetry): add unified_session telemetry to reduce detection
Implements WhatsApp's unified_session telemetry feature to reduce
detection of unofficial clients. This is an enterprise-grade implementation
inspired by whatsmeow PR #1057 and Baileys PR #2294.

Features:
- UnifiedSessionManager class with circuit breaker protection
- Server time synchronization for accurate session IDs
- Rate limiting to prevent spam (1 minute between sends)
- Prometheus metrics integration (unified_session_sent, errors)
- Structured logging for debugging
- Configurable via SocketConfig.enableUnifiedSession
- Environment variable support (BAILEYS_UNIFIED_SESSION_ENABLED)

Trigger points (matching official WhatsApp Web):
- After successful login (CB:success)
- After successful pairing (CB:iq,,pair-success)
- When sending 'available' presence

Implementation details:
- Session ID algorithm: (now + serverOffset + 3days) % 7days
- Time constants exported from Defaults/index.ts
- Full test coverage (31 tests)

References:
- https://github.com/tulir/whatsmeow/pull/1057
- https://github.com/WhiskeySockets/Baileys/pull/2294
- https://github.com/tulir/whatsmeow/issues/810
2026-01-24 18:56:08 +00:00
Renato Alcara a55055e55e fix(album): resolve TypeScript strict array access errors
fix(album): resolve TypeScript strict array access errors
2026-01-23 15:50:46 -03:00
Renato Alcara d95b2236c0 fix(album): resolve TypeScript strict array access errors
Fix TS2345 errors where array element access (medias[i]) was inferred as
`AlbumMediaItem | undefined` instead of `AlbumMediaItem`.

Changes:
- Add non-null assertion (!) after array access in for loops
- Add explicit cast to AnyMessageContent for hasNonNullishProperty calls

The non-null assertion is safe here because we iterate with `i < medias.length`,
guaranteeing the index is valid.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:48:09 -03:00
Renato Alcara 3345fc0225 feat(album): add album message sending with intelligent retry and ada…
feat(album): add album message sending with intelligent retry and ada…
2026-01-23 15:43:56 -03:00