Commit Graph

1556 Commits

Author SHA1 Message Date
Aguinaldo Tupy
78ebdbbbd8
fix: Normalize URLs with spaces in WhatsApp template parameters (#12594)
This PR fixes URL parsing errors when WhatsApp template parameters
contain URLs with spaces or special characters. The solution adds proper
URL normalization using Addressable::URI before validation, which
automatically handles space encoding and special character
normalization.

Related with https://github.com/chatwoot/chatwoot/pull/12462

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-08 15:33:06 +05:30
Shivam Mishra
978f4c431a
feat: Add relay state for SAML SSO (#12597)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-10-07 20:32:29 +05:30
Pranav
829142c808
fix: Update max_turns config (#12604)
Pass max_turns in the run config than during the initialization.

---------

Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2025-10-07 11:21:18 +05:30
Shivam Mishra
3a71829b46
feat: Improve captain conversation handling (#12599)
Co-authored-by: Pranav <pranavrajs@gmail.com>
2025-10-06 10:51:58 -07:00
Sivin Varghese
0974aea300
chore: Increase custom filter limit from 50 to 1000 per user (#12603)
# Pull Request Template

## Description

This PR increases the custom filter limit from 50 to 1000 per user

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

### Screenshot

<img width="1264" height="71" alt="image"
src="https://github.com/user-attachments/assets/e12667bb-147c-4115-b8a8-9113fca471db"
/>



## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
2025-10-06 10:41:26 -07:00
Shivam Mishra
9fb0dfa4a7
feat: Add UI for custom tools (#12585)
### Tools list

<img width="2316" height="666" alt="CleanShot 2025-10-03 at 20 42 41@2x"
src="https://github.com/user-attachments/assets/ccbffd16-804d-4eb8-9c64-2d1cfd407e4e"
/>

### Tools form 

<img width="2294" height="2202" alt="CleanShot 2025-10-03 at 20 43
05@2x"
src="https://github.com/user-attachments/assets/9f49aa09-75a1-4585-a09d-837ca64139b8"
/>

## Response

<img width="800" height="2144" alt="CleanShot 2025-10-03 at 20 45 56@2x"
src="https://github.com/user-attachments/assets/b0c3c899-6050-4c51-baed-c8fbec5aae61"
/>

---------

Co-authored-by: Pranav <pranavrajs@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2025-10-06 09:05:54 -07:00
Shivam Mishra
8bbb8ba5a4
feat(ee): Captain custom http tools (#12584)
To test this out, use the following PR:
https://github.com/chatwoot/chatwoot/pull/12585

---------

Co-authored-by: Pranav <pranavrajs@gmail.com>
2025-10-06 07:53:15 -07:00
Muhsin Keloth
66cfef9298
feat: Add WhatsApp health monitoring and self-service registration completion (#12556)
Fixes
https://linear.app/chatwoot/issue/CW-5692/whatsapp-es-numbers-stuck-in-pending-due-to-premature-registration


###  Problem  
Multiple customers reported that their WhatsApp numbers remain stuck in
**Pending** in WhatsApp Manager even after successful onboarding.

- Our system triggers a **registration call**
(`/<PHONE_NUMBER_ID>/register`) as soon as the number is OTP verified.
- In many cases, Meta hasn’t finished **display name
review/provisioning**, so the call fails with:

  ```
  code: 100, error_subcode: 2388001
  error_user_title: "Cannot Create Certificate"
error_user_msg: "Your display name could not be processed. Please edit
your display name and try again."
  ```

- This leaves the number stuck in Pending, no messaging can start until
we manually retry registration.
- Some customers have reported being stuck in this state for **7+
days**.

###  Root cause  
- We only check `code_verification_status = VERIFIED` before attempting
registration.
- We **don’t wait** for display name provisioning (`name_status` /
`platform_type`) to be complete.
- As a result, registration fails prematurely and the number never
transitions out of Pending.

### Solution  

#### 1. Health Status Monitoring  
- Build a backend service to fetch **real-time health data** from Graph
API:
  - `code_verification_status`  
  - `name_status` / `display_name_status`  
  - `platform_type`  
  - `throughput.level`  
  - `messaging_limit_tier`  
  - `quality_rating`  
- Expose health data via API
(`/api/v1/accounts/:account_id/inboxes/:id/health`).
- Display this in the UI as an **Account Health tab** with clear badges
and direct links to WhatsApp Manager.

#### 2. Smarter Registration Logic  
- Update `WebhookSetupService` to include a **dual-condition check**:  
  - Register if:  
    1. Phone is **not verified**, OR  
2. Phone is **verified but provisioning incomplete** (`platform_type =
NOT_APPLICABLE`, `throughput.level = NOT_APPLICABLE`).
- Skip registration if number is already provisioned.  
- Retry registration automatically when stuck.  
- Provide a UI banner with complete registration button so customers can
retry without manual support.

### Screenshot
<img width="2292" height="1344" alt="CleanShot 2025-09-30 at 16 01
03@2x"
src="https://github.com/user-attachments/assets/1c417d2a-b11c-475e-b092-3c5671ee59a7"
/>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2025-10-02 11:25:48 +05:30
Sivin Varghese
109aaa2341
fix: Display proper conversation ID with click-to-open in SLA reports (#12570) 2025-10-02 08:18:54 +05:30
Phuong Nguyen
fcb91ab88a
fix: Auto resolution flaky spec (#11964)
The test was failing because Current.contact was not being cleared when
testing system auto-resolution. Added Current.contact = nil to ensure
the system auto-resolution message is triggered instead of contact
resolution.

🤖 Generated with [Claude Code](https://claude.ai/code)

# Pull Request Template

## Description

Please include a summary of the change and issue(s) fixed. Also, mention
relevant motivation, context, and any dependencies that this change
requires.
Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.


## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-25 19:36:38 +05:30
Shivam Mishra
b75ea7a762
feat: Use resolved contacts as base relation for filtering (#12520)
This PR has two changes to speed up contact filtering

### Updated Base Relation

Update the `base_relation` to use resolved contacts scope to improve
perf when filtering conversations. This narrows the search space
drastically, and what is usually a sequential scan becomes a index scan
for that `account_id`

ref: https://github.com/chatwoot/chatwoot/pull/9347
ref: https://github.com/chatwoot/chatwoot/pull/7175/

Result: https://explain.dalibo.com/plan/c8a8gb17f0275fgf#plan


## Selective filtering in Compose New Conversation

We also cost of filtering in compose new conversation dialog by reducing
the search space based on the search candidate. For instance, a search
term that obviously can’t be a phone, we exclude that from the filter.
Similarly we skip name lookups for email-shaped queries.

Removing the phone number took the query times from 50 seconds to under
1 seconds

### Comparison

1. Only Email: https://explain.dalibo.com/plan/h91a6844a4438a6a 
2. Email + Name: https://explain.dalibo.com/plan/beg3aah05ch9ade0
3. Email + Name + Phone:
https://explain.dalibo.com/plan/c8a8gb17f0275fgf
2025-09-25 15:26:44 +05:30
Pranav
47bdb6d2bb
feat: Clean up email configuration for from and reply to emails (#12453)
We first added conversation continuity for the live chat widget, and
then carried the same logic over to email channels.

The problem was that this added a reply+conversationUUID@domain.com as
the reply-to for emails, which was unnecessary. For email channels, the
reply-to can just be the channel’s own email address.

That extra layer made things more complex than it needed to be. In this
PR, I’ve cleaned up the config so it’s simpler. The table below shows
how it’ll work going forward.

---

| Type | From Email | Reply To Email |
| -- | -- | -- |
| Standard IMAP, SMTP email channel | channel.email | channel.email |
| Google OAuth Email channel | channel.email | channel.email |
| Microsoft OAuth Email channel | channel.email | channel.email |
| Email forwarded to Chatwoot, brought their own SMTP | channel.email |
channel.email |
| Imap to fetch email, Use Chatwoot's SMTP | channel.email if verified
with Chatwoot's SMTP provider. Otherwise account support email |
channel.email |
| Email forwarded to Chatwoot, Use Chatwoot's SMTP | channel.email if
verified with Chatwoot's SMTP provider. Otherwise account support email
| channel.email |
| -- | --  | -- |
| Website Live Chat - Conversation Continuity Inbound Emails enabled|
Account Support Email | reply+{conversation-uuid}@{account_domain} |
| Website Live Chat - Conversation Continuity Inbound Emails disabled|
Account Support Email | Account Support Email |

Fixes https://github.com/chatwoot/chatwoot/issues/10614
Fixes https://github.com/chatwoot/chatwoot/issues/10521
Fixes https://github.com/chatwoot/chatwoot/issues/10300
Fixes https://github.com/chatwoot/chatwoot/issues/10091
Fixes https://github.com/chatwoot/chatwoot/issues/4890
Fixes https://github.com/chatwoot/chatwoot/issues/10676
Fixes https://github.com/chatwoot/chatwoot/issues/10756
Fixes https://github.com/chatwoot/chatwoot/issues/11515
Fixes https://github.com/chatwoot/chatwoot/issues/9471

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-24 11:36:53 -07:00
Shivam Mishra
d3cd647e49
feat: SAML feedback changes [CW-5666] (#12511) 2025-09-24 16:07:07 +05:30
Pranav
eadbddaa9f
feat: Separate indexing with the search feature (#12503)
With this change, the indexing would be separate from the search, so you
need to enable indexing on the cloud and run it. It should start
indexing the messages to ElasticSearch/OpenSearch. Once indexing is
completed, we can turn on the feature for the customer.


Make sure that the following is done when you deploy.
Set POSTGRES_STATEMENT_TIMEOUT=600s before you run the indexing.

1. Make sure that the account with advanced_search has
advanced_search_indexing enabled
```rb
Account.feature_advanced_search.each do |account|
  account.enable_features(:advanced_search_indexing)
  account.save!
end
```

2. Enable indexing for all accounts with paid subscription.
```rb
Account.where("custom_attributes ->> 'plan_name' IN (?)", ['Enterprise', 'Startups', 'Business']).each do |account|
account.enable_features(:advanced_search_indexing)
  account.save!
end
```

3. Run indexing for all the messages.
```rb
Message.reindex
```

Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-24 14:11:15 +05:30
Macoly Melo
e68522318b
feat: Enable lock to single thread settings for Telegram (#12367)
This PR implements the **"Lock to Single Conversation"** option for
Telegram inboxes, bringing it to parity with WhatsApp, SMS, and other
channels.

- When **enabled**: resolved conversations can be reopened (single
thread).
- When **disabled**: new messages from a resolved conversation create a
**new conversation**.
- Added **agent name display** in outgoing Telegram messages (formatted
as `Agent Name: message`).
- Updated frontend to display agent name above messages in the dashboard
(consistent with WhatsApp behavior).

This fixes [#8046](https://github.com/chatwoot/chatwoot/issues/8046).

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

- Unit tests added in
`spec/services/telegram/incoming_message_service_spec.rb`
- Scenarios covered:
  - Lock enabled → reopens resolved conversation
  - Lock disabled → creates new conversation if resolved
  - Lock disabled → appends to last open conversation
- Manual tests:
  1. Create a Telegram conversation
  2. Mark it as resolved
  3. Send a new message from same user
  4.  Expected: new conversation created (if lock disabled)


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

## Additional Documentation

For full technical details of this implementation, please refer to:  

[TELEGRAM_LOCK_TO_SINGLE_CONVERSATION_IMPLEMENTATION_EN.md](./TELEGRAM_LOCK_TO_SINGLE_CONVERSATION_IMPLEMENTATION_EN.md)

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-24 11:35:14 +05:30
Muhsin Keloth
44fab70048
feat: Add support for grouped file uploads in Slack (#12454)
Fixes
https://linear.app/chatwoot/issue/CW-5646/add-support-for-grouped-file-uploads-in-slack

Previously, when sending multiple attachments to Slack, we uploaded them
one by one. For example, sending 5 images would result in 5 separate
Slack messages. This created clutter and a poor user experience, since
Slack displayed each file as an individual message.
This PR updates the implementation to group all attachments from a
message and send them as a single Slack message. As a result,
attachments now appear together in one grouped block, providing a much
cleaner and more intuitive experience for users.

**Before:** 
Each file uploaded as a separate Slack message.
<img width="400" height="800" alt="before"
src="https://github.com/user-attachments/assets/c8c7f666-549b-428f-bd19-c94e39ed2513"
/>

**After:** 
All files from a single message grouped and displayed together in one
Slack message (similar to how Slack natively handles grouped uploads).
<img width="400" height="800" alt="after"
src="https://github.com/user-attachments/assets/0b1f22d5-4d37-4b84-905a-15e742317e72"
/>

**Changes**

- Upgraded Slack file upload implementation to use the new multiple
attachments API available in slack-ruby-client `v2.7.0`.
- Updated attachment handling to upload all files from a message in a
single API call.
- Enabled proper attachment grouping in Slack, ensuring related files
are presented together.
2025-09-24 11:31:06 +05:30
Sojan Jose
114c25cae8
feat: Auto confirm user email when super admin make changes (#12418)
- If super admin updates a user email from super admin panel , it will
be confirmed automatically if confirmed at is present
- Also unconfirmed emails will be visible for super admins on dashboard

fixes: https://github.com/chatwoot/chatwoot/issues/8958
2025-09-23 20:14:02 +05:30
Tanmay Deep Sharma
36cbd5745e
fix: Session controller to not generate auth tokens before mfa verification (#12487)
This PR is the fix for MFA changes, to not generate auth tokens without
MFA verification in case MFA is enabled for the account

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-23 19:13:47 +05:30
Shivam Mishra
2e108653ae
feat: allow SP initiated SAML (#12447)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-23 18:29:16 +05:30
Eduardo Policarpo
46b75e1b03
feat(whatsapp): add optional phone_number_id parameter to media retrieval API (#11823)
## Description

This pull request introduces an optional parameter, `phone_number_id`,
to the WhatsApp API call responsible for retrieving media. The addition
of this parameter allows for greater flexibility when interacting with
the WhatsApp API, as it can now accommodate scenarios where specifying a
particular phone number ID is necessary. This change is backward
compatible and does not affect existing functionality if the parameter
is not provided.

Fixes # (issue)

## Type of change

- [x] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

The changes were tested locally by invoking the WhatsApp media retrieval
API with and without the `phone_number_id` parameter. Both scenarios
were verified to ensure that:

- When `phone_number_id` is provided, the API call includes the
parameter and functions as expected.
- When `phone_number_id` is omitted, the API call continues to work as
before, maintaining backward compatibility.

No errors or warnings were observed during testing, and all relevant
unit tests passed successfully.

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-23 09:16:59 +05:30
Honza Sterba
8162473eb6
fix: Contact search by phone number (#10386)
# Pull Request Template

## Description

when filtering contacts by phone number a + is always added to the
begining of the query, this means that the filtering breaks if the
complete phone number with international code and + is entered

## Type of change

Please delete options that are not relevant.

- [X] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

Updated automated tests
Tested manually with contact filtering UI

## Checklist:

- [X] My code follows the style guidelines of this project
- [X] I have performed a self-review of my code
- [X] I have commented on my code, particularly in hard-to-understand
areas
- [X] I have made corresponding changes to the documentation
- [X] My changes generate no new warnings
- [X] I have added tests that prove my fix is effective or that my
feature works
- [X] New and existing unit tests pass locally with my changes
- [X] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-22 18:59:30 +05:30
Shivam Mishra
8764ade161
feat: add SKIP_INCOMING_BCC_PROCESSING as internal config (#12484)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-22 17:52:56 +05:30
mix5003
0e41263f9c
fix: Ensure messages go to correct conversation when receive multi user in 1 LINE webhook (#12322)
# Pull Request Template

## Description
Ensure messages go to correct conversation when receive multi user in 1
LINE webhook.
base on
[document](https://developers.line.biz/en/reference/messaging-api/#webhook-event-objects:~:text=There%20is%20not%20necessarily%20one%20user%20per%20webhook).
it said
```
There is not necessarily one user per webhook. 
A message event from person A and a follow event from person B may be in the same webhook.
```

this PR has 1 break changes.
In old version. when receive
[follow](https://developers.line.biz/en/reference/messaging-api/#follow-event)
event, it will create conversation with no messages.
After this PR. when receive follow event, it will not create
conversation, contact and messages

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?
add test case.
and follow event test by delete conversation, and block and unblock line
account

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: mix5003 <mix5003@debian.debian>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-22 17:05:25 +05:30
Niranjan Patil
b28c08059f
fix: Incorrect contact access in conversations listing (#11797)
# Pull Request Template

## Description

This PR fixes the incorrect contact access in conversations listing API.
Cause:

- `undefined method 'conversations' for nil` error because `@contact` is
not initialized

Solution:
- Using `@contact_inbox` to access `@contact`
- `@contact_inbox` is properly set in the parent controller's
`set_contact_inbox` method

Fixes
https://linear.app/chatwoot/issue/CW-4185/incorrect-contact-access-pattern-in

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-22 17:05:11 +05:30
mix5003
b5deecc9f9
feat: Accept file attachment in line channel (#12321)
# Pull Request Template

## Description
This pull request allow LINE to receive files. 

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?
add testcase. and test manually by myself.
in case you want to test in android, use native share method to share
files to LINE.
you can share more file types to LINE (native line share only send
image,video and audio).


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: mix5003 <mix5003@debian.debian>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-22 15:06:28 +05:30
gabrieljablonski
24620a0baf chore: apply rubocop 2025-09-19 19:44:02 -03:00
gabrieljablonski
18c672c204 Merge branch 'main' into chore/merge-upstream-4.6.0 2025-09-19 19:37:28 -03:00
Sojan Jose
98f4a6f797
chore: Ensure admin notification mailer specs are order agnostic (#12472)
## Summary
- update the admin notification base mailer spec to ignore ordering when
verifying administrator email addresses
- extend the channel and integrations admin notification mailer specs to
cover multiple administrators without relying on recipient order

------
https://chatgpt.com/codex/tasks/task_e_68cc7457cf788326a765f116ceab1732

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-19 16:37:57 +05:30
Tanmay Deep Sharma
239c4dcb91
feat: MFA (#12290)
## Linear:
- https://github.com/chatwoot/chatwoot/issues/486

## Description
This PR implements Multi-Factor Authentication (MFA) support for user
accounts, enhancing security by requiring a second form of verification
during login. The feature adds TOTP (Time-based One-Time Password)
authentication with QR code generation and backup codes for account
recovery.

## Type of change

- [ ] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

- Added comprehensive RSpec tests for MFA controller functionality
- Tested MFA setup flow with QR code generation
- Verified OTP validation and backup code generation
- Tested login flow with MFA enabled/disabled

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-18 20:19:24 +05:30
Shivam Mishra
8f4b252045
feat: allow searching captain responses [CW-5631] (#12463) 2025-09-18 14:44:56 +05:30
Vishnu Narayanan
9527ff6269
feat: Add support for labels in automations (#11658)
- Add support for using labels as an action event for automation
 - Fix duplicated conversation_updated event dispatch for labels
 

Fixes https://github.com/chatwoot/chatwoot/issues/8539 and multiple
issues around duplication related to label change events.
---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-18 14:17:54 +05:30
Sojan Jose
44dc9ba18e
feat: Allow detaching help center widget (#12459)
## Summary
- allow help center portals to clear their associated web widget


Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2025-09-17 22:27:50 +05:30
Shivam Mishra
7bc7ae5bc4
feat: setup invite to handle SAML enabled account [CW-5613] (#12439) 2025-09-17 19:33:38 +05:30
Pranav
cc21016e6d
feat: Add support for customizing expiry of widget token (#12446)
This PR is part of https://github.com/chatwoot/chatwoot/pull/12259. It
adds a default expiry of 180 days for tokens issued on the widget. The
expiry can be customized based on customer requests and internal
security requirements.

Co-authored-by: Balasaheb Dubale <bdubale@entrata.com>
2025-09-16 12:41:05 +05:30
Shivam Mishra
7a453f50f4
feat: update users on SAML setup and destroy [CW-2958][CW-5612] (#12346) 2025-09-15 21:20:22 +05:30
Muhsin Keloth
458ed1e26d
chore: Enable flexible whatsapp onboarding (Manual + Embedded Signup) options (#12344)
We recently introduced the WhatsApp Embedded Signup flow in Chatwoot to
simplify onboarding. However, we discovered two important limitations:
Some customers’ numbers are already linked to an Embedded Signup, which
blocks re-use. Tech providers cannot onboard their own numbers via
Embedded Signup.
As a result, we need to support both Manual and Embedded Signup flows to
cover all scenarios.

### Problem

- Current UI only offers the Embedded Signup option.
- Customers who need to reuse existing numbers (already connected to
WABA) or tech providers testing their own numbers get stuck.
- Manual flow exists but is no longer exposed in the UX

**Current Embedded Signup screen**
<img width="2564" height="1250" alt="CleanShot 2025-08-21 at 21 58
07@2x"
src="https://github.com/user-attachments/assets/c3de4cf1-cae6-4a0e-aa9c-5fa4e2249c0e"
/>

**Current Manual Setup screen**
<img width="2568" height="1422" alt="CleanShot 2025-08-21 at 22 00
25@2x"
src="https://github.com/user-attachments/assets/96408f97-3ffe-42d1-9019-a511e808f5ac"
/>


###  Solution

- Design a dual-path UX in the Create WhatsApp Inbox step that:
- Offers Embedded Signup (default/recommended) for new numbers and
businesses.
- Offers Manual Setup for advanced users, existing linked numbers, and
tech providers.

<img width="2030" height="1376" alt="CleanShot 2025-09-01 at 14 13
16@2x"
src="https://github.com/user-attachments/assets/6f17e5a2-a2fd-40fb-826a-c9ee778be795"
/>

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
2025-09-15 19:59:56 +05:30
Chatwoot Bot
3ad2c33220
chore: Update translations (#12371)
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Pranav <pranavrajs@gmail.com>
2025-09-12 14:33:40 -07:00
Pranav
16b98b6017
fix: Add account_id to the query to force using a better index (#12420)
I've added the account_id filter to the
`get_agent_ids_over_assignment_limit` method. This optimization will
help the query leverage the existing composite index
`conv_acid_inbid_stat_asgnid_idx (account_id, inbox_id, status,
assignee_id)` for better performance.

**Before:**
```sql
HashAggregate (cost=224238.12..224256.27 rows=484 width=4)
Group Key: assignee_id
Filter: (count(*) >= 10)
-> Index Scan using index_conversations_on_inbox_id on conversations (cost=0.44..223963.67 rows=54891 width=4)
Index Cond: (inbox_id = ???)
Filter: (status = 0)
```

**After:**
```sql
GroupAggregate (cost=0.44..5688.30 rows=476 width=4)
Group Key: assignee_id
Filter: (count(*) >= 10)
-> Index Only Scan using conv_acid_inbid_stat_asgnid_idx on conversations (cost=0.44..5640.81 rows=5928 width=4)
Index Cond: ((account_id = ??) AND (inbox_id = ??) AND (status = 0))
```
2025-09-11 22:27:38 -07:00
Sojan Jose
de5fb7a405
chore: remove unused telegram bot model (#12417)
## Summary
- remove unused TelegramBot model and its association
- drop obsolete telegram_bots table
2025-09-11 22:25:26 +05:30
Sojan Jose
55315089cf
fix(delete_object_job): pre-purge heavy associations before destroy to prevent timeout (#12408)
Deleting large Accounts/Inboxes with object.destroy! can time out and
create heavy destroy_async fan-out; this change adds a simple pre-purge
that batch-destroys heavy associations first .

```
Account: conversations, contacts
Inbox: conversations, contact_inboxes
```

We use find_in_batches(5000), then proceeds with destroy!, reducing DB
pressure and race conditions while preserving callbacks and leaving the
behavior for non heavy models unchanged. The change is also done in a
way to easily add additional objects or relations to the list.


fixes:
https://linear.app/chatwoot/issue/CW-3106/inbox-deletion-process-update-the-flow
2025-09-11 18:43:36 +05:30
Tanmay Deep Sharma
e5b8dc251f
fix: Assignment V2 controller fix (#12415) 2025-09-11 19:32:33 +07:00
Sojan Jose
81b401c998
fix: Add URL validation and rate limiting for contact avatar sync (#11979)
- Implement 1-minute rate limiting for contacts to prevent bombardment
- Add URL hash comparison to sync only when avatar URL changes
2025-09-10 20:08:06 +05:30
Shivam Mishra
79b93bed77
feat: SAML authentication controllers [CW-2958] (#12319) 2025-09-10 20:02:27 +05:30
Gabriel Jablonski
6cd0a3bf7f
feat(wa-cloud): reaction messages and meta is_record_audio for voice messages (#111)
* feat: add send_reaction_message method and corresponding tests

* chore: useless comment from previous PR

* feat(wa-cloud): set is_recorded_audio for voice message
2025-09-10 09:02:06 -03:00
Muhsin Keloth
7554156abe
chore: Account switching issue in newly added accounts (#12403)
The system determines a user’s active account by checking the
`active_at` field in the `account_users` table and selecting the most
recently active account:

```ruby
def active_account_user
  account_users.order(active_at: :desc)&.first
end
```

This works fine when all accounts have a valid active_at timestamp.

**Problem**

When a user is added to a new account, the `active_at` value is NULL
(because the account has never been explicitly activated). Ordering by
active_at DESC produces inconsistent results across databases, since
handling of NULL values differs (sometimes treated as high, sometimes
low).

As a result:

- Mobile apps (critical impact): `/profile` returns the wrong account.
The UI keeps showing the old account even after switching, and
restarting does not fix it.
- Web app (accidentally works): Appears correct because the active
account is inferred from the browser URL, but the backend API is still
wrong.

**Root Cause**

- The ordering logic did not account for NULL `active_at`.
- New accounts without active_at sometimes get incorrectly prioritized
as the “active” account.

**Solution**

Explicitly ensure that accounts with NULL active_at are sorted after
accounts with real timestamps by using NULLS LAST:

```ruby
def active_account_user
  account_users.order(Arel.sql('active_at DESC NULLS LAST, id DESC'))&.first
end
```

- Accounts with actual `active_at` values will always be prioritized.
- New accounts (with NULL active_at) will be placed at the bottom until
the user explicitly activates them.
- Adding id DESC as a secondary ordering ensures consistent tie-breaking
when multiple accounts have the same `active_at`.
2025-09-10 14:12:22 +05:30
micahmills
b989ca6397
feat: Agent language settings (#11222)
# Pull Request Template

## Description

This Pull Request will provide a language selector in the Profile
Settings for each user, and allows them to change the UI language per
agent, defaulting back to the account locale.

Fixes # #678 This does PR addresses the Dashboard view but does not
change the language of the agents emails

## Type of change

Please delete options that are not relevant.
- [X ] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

1. Go to an Agents Profile settings page
2. Select a language from the Language drop down
3. the UI will update to the new i18n locale
4. navigate through the UI to make sure the appropriate language is
being used
5. Refresh the page to test that the locale persists


270

- [X] My code follows the style guidelines of this project
- [X] I have performed a self-review of my code
- [X] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [X] My changes generate no new warnings
- [X] I have added tests that prove my fix is effective or that my
feature works
- [X] New and existing unit tests pass locally with my changes
- [X] Any dependent changes have been merged and published in downstream
modules
Checklist:.724.2708

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-09 14:27:36 +05:30
Sojan Jose
6bdd4f0670
feat(voice): Incoming voice calls [EE] (#12361)
This PR delivers the first slice of the voice channel: inbound call
handling. When a customer calls a configured voice
number, Chatwoot now creates a new conversation and shows a dedicated
call bubble in the UI. As the call progresses
(ringing, answered, completed), its status updates in real time in both
the conversation list and the call bubble, so
agents can instantly see what’s happening. This focuses on the inbound
flow and is part of breaking the larger voice
feature into smaller, functional, and testable units; further
enhancements will follow in subsequent PRs.

references: #11602 , #11481  

## Testing

- Configure a Voice inbox in Chatwoot with your Twilio number.
- Place a call to that number.
- Verify a new conversation appears in the Voice inbox for the call.
- Open it and confirm a dedicated voice call message bubble is shown.
- Watch status update live (ringing/answered); hang up and see it change
to completed in both the bubble and conversation
list.
- to test missed call status, make sure to hangup the call before the
please wait while we connect you to an agent message plays


## Screens

<img width="400" alt="Screenshot 2025-09-03 at 3 11 25 PM"
src="https://github.com/user-attachments/assets/d6a1d2ff-2ded-47b7-9144-a9d898beb380"
/>

<img width="700" alt="Screenshot 2025-09-03 at 3 11 33 PM"
src="https://github.com/user-attachments/assets/c25e6a1e-a885-47f7-b3d7-c3e15eef18c7"
/>

<img width="700" alt="Screenshot 2025-09-03 at 3 11 57 PM"
src="https://github.com/user-attachments/assets/29e7366d-b1d4-4add-a062-4646d2bff435"
/>



<img width="442" height="255" alt="Screenshot 2025-09-04 at 11 55 01 PM"
src="https://github.com/user-attachments/assets/703126f6-a448-49d9-9c02-daf3092cc7f9"
/>

---------

Co-authored-by: Muhsin <muhsinkeramam@gmail.com>
2025-09-08 22:35:23 +05:30
Gabriel Jablonski
3dac94e058
fix(article): enforce maximum length for content validation (#109)
* fix(article): enforce maximum length for content validation

* fix(article): update content length validation to allow up to 65535 characters
2025-09-04 21:45:29 -03:00
Shivam Mishra
76c110e60e
fix: resolution count does not have account scope (#12370) 2025-09-04 18:04:00 +05:30
Shivam Mishra
33058b5f3f
feat: add saml model & controller [CW-2958] (#12289)
This PR adds the foundation for account-level SAML SSO configuration in
Chatwoot Enterprise. It introduces a new `AccountSamlSettings` model and
management API that allows accounts to configure their own SAML identity
providers independently, this also includes the certificate generation
flow

The implementation includes a new controller
(`Api::V1::Accounts::SamlSettingsController`) that provides CRUD
operations for SAML configuration

The feature is properly gated behind the 'saml' feature flag and
includes administrator-only authorization via Pundit policies.
2025-09-03 13:30:42 -07:00
Gabriel Jablonski
0b6d943faf
fix(wa-cloud): send status read for typing indicator (#107)
* fix(wa-cloud): send status read for typing indicator

* test(wa-cloud): send status read for typing indicator
2025-09-03 13:36:20 -03:00
Shivam Mishra
ef4e287f0d
fix: wrong resolution count in timeseries reports (#12261)
There was a fundamental difference in how resolution counts were
calculated between the agent summary and timeseries reports, causing
confusion for users when the numbers didn't match.

The agent summary report counted all `conversation_resolved` events
within a time period by querying the `reporting_events` table directly.
However, the timeseries report had an additional constraint that
required the conversation to currently be in resolved status
(`conversations.status = 1`). This meant that if an agent resolved a
conversation that was later reopened, the resolution action would be
counted in the summary but not in the timeseries.

This fix aligns both reports to count resolution events rather than
conversations in resolved state. When an agent resolves a conversation,
they should receive credit for that action regardless of what happens to
the conversation afterward. The same logic now applies to bot
resolutions as well.

The change removes the `conversations: { status: :resolved }` condition
from both `scope_for_resolutions_count` and
`scope_for_bot_resolutions_count` methods in CountReportBuilder, and
updates the corresponding test expectations to reflect that all
resolution events are counted.


## About timezone

When a timezone is specified via `timezone_offset` parameter, the
reporting system:

1. Converts timestamps to the target timezone before grouping
2. Groups data by local day/week/month boundaries in that timezone, but
the primary boundaries are sent by the frontend and used as-is
3. Returns timestamps representing midnight in the target timezone

This means the same events can appear in different day buckets depending
on the timezone used. For summary reports, it works fine, since the user
only needs the total count between two timestamps and the frontend sends
the timestamps adjusted for timezone.

## Testing Locally

Run the following command, this will erase all data for that account and
put in 1000 conversations over last 3 months, parameters of this can be
tweaked in `Seeders::Reports::ReportDataSeeder`

I'd suggest updating the values to generate data over 30 days, with
10000 conversations, it will take it's sweet time to run but then the
data will be really rich, great for testing.

```
ACCOUNT_ID=2 ENABLE_ACCOUNT_SEEDING=true bundle exec rake db:seed:reports_data
```

Pro Tip: Don't run the app when the seeder is active, we manually create
the reporting events anyway. So once done just use `redis-cli FLUSHALL`
to clear all sidekiq jobs. Will be easier on the system

Use the following scripts to test it

- https://gist.github.com/scmmishra/1263a922f5efd24df8e448a816a06257
- https://gist.github.com/scmmishra/ca0b861fa0139e2cccdb72526ea844b2
- https://gist.github.com/scmmishra/5fe73d1f48f35422fd1fd142ea3498f3
- https://gist.github.com/scmmishra/3b7b1f9e2ff149007170e5c329432f45
- https://gist.github.com/scmmishra/f245fa2f44cd973e5d60aac64f979162

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-03 15:47:16 +05:30
Gabriel Jablonski
eaf2f99520
feat: whatsapp cloud service typing status and read messages (#106) 2025-09-02 15:20:13 -03:00
Pranav
e863a52262
chore: Update account deletion email copy (#12317)
Update the email copies for account deletion emails 

## Manual Deletion 

<img width="1378" height="678" alt="Screenshot 2025-08-29 at 2 41 40 PM"
src="https://github.com/user-attachments/assets/63d7ad97-ad51-4a8b-9ef3-d427fa467f8a"
/>

## Inactive Deletion

<img width="2946" height="1808" alt="image"
src="https://github.com/user-attachments/assets/bb50d08c-8701-4f93-af29-0b1d948a4009"
/>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2025-08-31 16:01:41 +02:00
Sojan Jose
0a9edd4c3b
ci(circleci): switch coverage reporting to Qlty orb (#12337) 2025-08-31 00:39:34 +05:30
Pranav
f4643116df
feat: Run assignment every 15 minutes (#12334)
Currently, auto-assignment runs only during conversation creation or
update events. If no agents are online when new conversations arrive,
those conversations remain unassigned.

With this change, unassigned conversations will be automatically
assigned once agents become available. The job runs every 15 minutes and
uses a fair distribution threshold of 100 to prevent a large number of
conversations from being assigned to a single available agent. This will
be customizable later.
2025-08-29 15:10:56 -07:00
Sojan Jose
9145658597
chore: Refactor UTM params to stay compliant with standards (#12312)
We were using UTM params on various branding urls which weren't
compliant to standard utm params and hence were ignored by analytics
tooling. this PR ensures that the params stays compliant with defined
standard

ref: https://en.wikipedia.org/wiki/UTM_parameters

## Changes 

- updated utm tags on widget and survey urls
- added utm on helpcenter branding

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-29 11:46:52 -07:00
Gabriel Jablonski
dbb41df67e
fix: update GitHub versions link and version fetching (#105)
* fix: update GitHub versions link and version fetching

* test: specs

* chore: use timeout and log error

* refactor: redundant helper method
2025-08-28 10:50:03 -03:00
Pranav
0c2ab7f5e7
feat(ee): Setup advanced, performant message search (#12193)
We now support searching within the actual message content, email
subject lines, and audio transcriptions. This enables a faster, more
accurate search experience going forward. Unlike the standard message
search, which is limited to the last 3 months, this search has no time
restrictions.

The search engine also accounts for small variations in queries. Minor
spelling mistakes, such as searching for slck instead of Slack, will
still return the correct results. It also ignores differences in accents
and diacritics, so searching for Deja vu will match content containing
Déjà vu.


We can also refine searches in the future by criteria such as:
- Searching within a specific inbox
- Filtering by sender or recipient
- Limiting to messages sent by an agent


Fixes https://github.com/chatwoot/chatwoot/issues/11656
Fixes https://github.com/chatwoot/chatwoot/issues/10669
Fixes https://github.com/chatwoot/chatwoot/issues/5910



---

Rake tasks to reindex all the messages. 

```sh
bundle exec rake search:all
```

Rake task to reindex messages from one account only
```sh
bundle exec rake search:account ACCOUNT_ID=1
```
2025-08-28 10:10:28 +05:30
Gabriel Jablonski
9f5c62c724
feat(baileys): add status method to fetch Baileys API version and availability (#104)
* feat(baileys): add status method to fetch Baileys API version and availability

* test: specs

* chore: raise error instead of returning error in version
2025-08-27 13:56:06 -03:00
Gabriel Coelho
d2a0d53fab
feat(whatsapp): get contact profile picture when using Baileys service (#98)
* feat(whatsapp): add profile picture fetching for Baileys provider

- Add `get_profile_pic` method to `WhatsappBaileysService` for fetching contact avatars
- Include `avatar_url` in contact attributes during contact creation
- Update `MessagesUpsert` handler to fetch and set profile pictures
- Add proper error handling and graceful degradation when avatar fetching fails

* test(whatsapp): add test coverage for Baileys profile picture fetching

- Add test suite for `get_profile_pic` method
- Include test scenarios for successful responses, missing avatars, and error handling
- Add profile picture HTTP stubbing and avatar job expectations to message processing tests

* feat(whatsapp): optimize Baileys avatar fetching and update avatar for existing inboxes

Previously, the profile picture was fetched on every incoming message and avatar updates were only attempted for new inboxes.

This change optimizes the process by:
- Only fetching the WhatsApp profile picture if the contact does not already have an avatar.
- Attempting to update the avatar for both new and existing inboxes.

This logic is based on Telegram's version (app/services/telegram/incoming_message_service.rb).

* refactor(whatsapp): remove unnecessary safe navigation when accessing contact

This reverts an unnecessary change introduced in b918a92.

* refactor(whatsapp): manually rollback change introduced in b918a92

* refactor(whatsapp): rename endpoint to profile-picture-url

* refactor(whatsapp): simplify profile picture response handling

Replaced manual JSON parsing with HTTParty's parsed_response and removed redundant JSON parsing tests.

* test(whatsapp): separate avatar processing test from message creation test

* test(whatsapp): update profile picture test to match actual API behavior

Change test to expect a 404 response when no profile picture exists, instead of a 200 response with partial data.

* refactor: move new functions to helper module

* test: more specs

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
2025-08-27 13:02:04 -03:00
Tanmay Deep Sharma
1ba00075ce
feat: Add BE changes for captain pdf support for faq generation (#12113) 2025-08-27 20:31:22 +05:30
Tanmay Deep Sharma
ad90deb709
feat: Add agent capacity controllers (#12200)
## Linear reference:
https://linear.app/chatwoot/issue/CW-4649/re-imagine-assignments

## Description
This PR introduces the foundation for Assignment V2 system by
implementing agent_capacity and their association with inboxes and
users.

## Type of change

- [ ] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

Test Coverage:
-  Controller specs for assignment policies CRUD operations
-  Enterprise-specific specs for balanced assignment order
-  Model specs for community/enterprise separation

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
2025-08-26 19:12:58 -07:00
Gabriel Jablonski
16f5c2c62d
fix: update notification setting to clear selected email flags (#100)
* fix: update notification setting to clear selected email flags

* test: fix spec
2025-08-25 18:11:29 -03:00
Muhsin Keloth
7d6a43fc72
feat: Added the backend support for twilio content templates (#12272)
Added comprehensive Twilio WhatsApp content template support (Phase 1)
enabling text, media, and quick reply templates with proper parameter
conversion, sync capabilities.

 **Template Types Supported**
  - Basic Text Templates: Simple text with variables ({{1}}, {{2}})
  - Media Templates: Image/Video/Document templates with text variables
  - Quick Reply Templates: Interactive button templates
  
 Front end changes is available via #12277

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2025-08-24 10:05:15 +05:30
Pranav
7f56cd92f8
chore: Update the prompts to include language of the account for FAQs (#12280)
There were customer reported issues with FAQs which were generated in a
different langauge than what they were expecting. The reason behind this
was that the language of the account was not considered in the prompt
provided. If the language of the content was say Spanish, and the
account locale was english. The output was not predicable. The output
depends on the model and the execution time.

This PR would update the prompt to behave consistently with the account
locale. Even though the content provided is in a different language, it
would generate FAQs in the account locale.

Changes:
- Updated the prompt to include a detailed expectation of the FAQs
quality along with the language
- Added specs for the services where the prompt generator is called.

Tested the prompt using Phoenix playground across GPT 5, GPT 4.1, GPT
4.0. The reasoning setting for GPT 5 needs to be low so that it doesn't
generate random questions like "What was this updated?"
2025-08-22 10:03:52 -07:00
Sojan Jose
d48503bdcf
feat(voice): Improved voice call creation flow [EE] (#12268)
This PR improves the voice call creation flow by simplifying
configuration and automating setup with Twilio APIs.

references: #11602 , #11481 

## Key changes

- Removed the requirement for twiml_app_sid – provisioning is now
automated through APIs.
- Auto-configured webhook URLs for:
  - Voice number callbacks
  - Status callbacks
  -  twiML callbacks
- Disabled business hours, help center, and related options until voice
inbox is fully supported.
- Added a configuration tab in the voice inbox to display the required
Twilio URLs (to make verification easier in Twilio console).


## Test Cases
- Provisioning
- Create a new voice inbox → verify that Twilio app provisioning happens
automatically.
  - Verify twiML callback 
- Webhook configuration
- Check that both voice number callback and status callback URLs are
auto-populated in Twilio.
- Disabled features
- Confirm that business hours and help center options are
hidden/disabled for voice inbox.
- Configuration tab
- Open the voice inbox configuration tab → verify that the displayed
Twilio URLs match what’s set in Twilio.
2025-08-22 13:38:23 +02:00
Muhsin Keloth
35d0a7f1a7
feat: Add liquid template support for WhatsApp template parameters (#12227)
Extends liquid template processing to WhatsApp `template_params`,
allowing dynamic variable substitution in template parameter values.

Users can now use liquid variables in WhatsApp template parameters:

```
{
  "template_params": {
    "name": "greet",
    "category": "MARKETING",
    "language": "en",
    "processed_params": {
      "body": {
        "customer_name": "{{contact.name}}",
        "customer_email": "{{contact.email | default: 'no-email@example.com'}}"
      }
    }
  }
}

```

When the message is saved, {{contact.name}} gets replaced with the
actual contact name.

Supported Variables

- {{contact.name}}, {{contact.email}}, {{contact.phone_number}}
- {{agent.name}}, {{agent.first_name}}
- {{account.name}}, {{inbox.name}}
- {{conversation.display_id}}
- Custom attributes: {{contact.custom_attribute.key_name}}
- Liquid filters: {{ contact.email | default: "fallback@example.com" }}
2025-08-21 16:44:51 +05:30
gabrieljablonski
2f8c7f0697 chore: fix spec 2025-08-20 12:08:01 -03:00
gabrieljablonski
801033bd5f Merge branch 'main' into chore/merge-upstream-4.5.0 2025-08-20 11:20:31 -03:00
Tanmay Deep Sharma
341487b93e
feat: Add assignment policies controllers with jbuilder views (#12199)
## Linear reference:
https://linear.app/chatwoot/issue/CW-4649/re-imagine-assignments

## Description
This PR introduces the foundation for Assignment V2 system by
implementing assignment policies and their association with inboxes.
Assignment policies allow configuring how conversations are distributed
among agents, with support for different assignment orders (round_robin
in community, balanced in enterprise) and conversation prioritization
strategies

Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Test Coverage:
-  Controller specs for assignment policies CRUD operations
-  Enterprise-specific specs for balanced assignment order
-  Model specs for community/enterprise separation

Manual Testing:
1. Create assignment policy: POST
/api/v1/accounts/{id}/assignment_policies
2. List policies: GET /api/v1/accounts/{id}/assignment_policies
3. Assign policy to inbox: POST
/api/v1/accounts/{id}/assignment_policies/{id}/inboxes
4. View inbox policy: GET
/api/v1/accounts/{id}/inboxes/{id}/assignment_policy
5. Verify community edition ignores "balanced" assignment order
6. Verify enterprise edition supports both "round_robin" and "balanced"

- testing the flows after enterprise folder deletion

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Pranav <pranavrajs@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2025-08-18 19:15:21 -07:00
Gabriel Jablonski
99255c199f
feat: on whatsapp baileys check (#95)
* feat: on whatsapp baileys check

* chore: refactoring

* chore: refactoring
2025-08-18 12:41:06 -03:00
Cayo P. R. Oliveira
c6f9e814c2
feat: add customizable signature position and separator options (#78)
* feat: add customizable signature position and separator options

* fix: correct default value note for signatureSeparator and ensure reactivity

* fix: correct watcher boolean conversion and add immediate ui_settings updates

- Fix watchers to convert string props to boolean values for reactive refs
- Add immediate event handlers for switch changes to update ui_settings in real-time
- Ensure proper synchronization between switch states and user.ui_settings

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: split signature content and ui_settings updates to resolve persistence bug

- Use updateUISettings store action for signature_position and signature_separator
- Keep updateProfile for message_signature content only
- Fixes FormData serialization issue that corrupted nested ui_settings object
- Add diagnostic logging to verify data flow

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* clean: remove diagnostic console logging from updateSignature method

- Remove temporary console.log statements added for verification
- Keep core implementation that splits signature content and ui_settings updates
- Keep console.error for proper error handling with eslint-disable comment
- Implementation now ready for production use

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: updateUISettings call in updateSignature method

* chore: move signature application to send-time and add button highlighting (#79)

* fix: move signature application from editor manipulation to send-time

- Remove addSignature/removeSignature/toggleSignatureInEditor from WootWriter
- Remove signature logic from draft handling and canned response insertion
- Apply signatures only in getMessagePayload during message sending
- Add button highlighting for signature toggle when activated
- Prevents signature duplication and persistence in editor content
- Fixes signature position toggle bug

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: escape signature separator to prevent markdown setext heading interpretation

- Escape '--' separator as '\--' in appendSignature to prevent H2 heading creation
- Update removeSignature to handle escaped separators correctly
- Fixes signature separator being rendered as markdown instead of plain text
- Refactor nested ternary to fix ESLint error

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: prevent signature separator markdown interpretation in message processing

- Add fix_signature_separator_markdown method to escape '--' separators
- Update ensure_processed_message_content to fix separators before saving
- Prevents signature separators from being interpreted as setext headings
- Ensures correct message display in channels and email notifications

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: update separator format to use \n--\n instead of escaping

- Change separator delimiter from '\--' to '\n--\n' format
- Update removeSignature function to handle new separator format correctly
- Simplify message processing since separators are already properly formatted
- Ensures consistent separator handling across frontend and backend

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: update signature delimiter format to include extra new lines

* chore: remove comment about signature application logic

* refactor: remove unused method and comments related to signature separator markdown processing

* chore: simplify slash command detection by using updatedMessage directly

* refactor: remove signature logic from draft message handling

* refactor: simplify body empty check by removing signature manipulation logic

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cayo@fazer.ai <cayoproliveira@gmail.com>

* refactor: extract signature settings logic into a separate method

* fix: handle nil ui_settings in signature position and separator methods

* fix: update return value of findSignatureInBody to include position information

* fix: update signature handling in findSignatureInBody and related methods

* fix: adjust delimiter length handling in removeSignature function

* test: add cases for appending, removing, and replacing signatures with various separators

* test: add cases for signature position and separator handling

* test: add cases for updating signature position and separator in ui_settings

* fix: correct typo in comment for findSignatureInBody function

* refactor: simplify translation function calls in MessageSignature component

* chore: refactoring

* chore: refactor

* feat: switch -> select

* chore: refactor and undo changes

* chore: refactor and undo changes

* chore: refactor

* fix: remove old select component usage

* chore: remove useless style

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
2025-08-17 23:01:41 -03:00
Shivam Mishra
c6be04cdc1
feat: scenario agents & runner (#11944)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2025-08-14 12:39:21 +05:30
Tanmay Deep Sharma
6b42ff8d39
fix: setup webhook for create and update should be done after db commit (#12176)
## Reference
https://github.com/chatwoot/chatwoot/pull/12149#issuecomment-3178108388

## Description

setup_webhook was done before the save, and hence the meta webhook
validation might fail because of a race condition where the facebook
validation is done before we saving the entry to the database.

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- New inbox creation, webhook validation
- Existing inbox update, webhook validation
- 
<img width="614" height="674" alt="image"
src="https://github.com/user-attachments/assets/be223945-deed-475a-82e5-3ae9c54a13fa"
/>


## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-13 20:53:31 +05:30
Shivam Mishra
a88fef2e1d
fix: incorrect first response time for reopened conversations (#12058)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-13 16:39:43 +05:30
Clairton Rodrigo Heinzen
b711bfd2ca
feat: Add automation rule event conversation resolved (#9669)
# Description

add automation rule event conversation resolved

<img width="1552" alt="Captura de Tela 2024-06-22 às 21 25 39"
src="https://github.com/chatwoot/chatwoot/assets/471685/b3a64ebc-35c8-468c-a0e5-7974134a40f9">

---------

Co-authored-by: Sojan <sojan@pepalo.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-13 12:57:14 +05:30
Vishnu Narayanan
9a7318a9db
fix: cw-5411 handle unrepresentable image attachments (#12178)
# Pull Request Template

## Description

Fixes
https://linear.app/chatwoot/issue/CW-5411/actionviewtemplateerror-activestorageunrepresentableerror

###  Problem
API endpoints return 500 errors when conversations contain image
attachments that can't be processed by ActiveStorage (e.g., files with
non-ASCII filenames, corrupted images, or malicious XSS filenames).

Root Cause: Commit 6cab74139 removed the representable? safety check
from thumb_url, causing `ActiveStorage::UnrepresentableError` to bubble
up and crash the API when it encountered a malformed image file.

Fix: Rescue `thumb_url` method to catch UnrepresentableError and return
an empty string while logging problematic names for future debugging.

This ensures the messages/attachments api does not break due to a single
corrupted image file.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- Added specs

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
2025-08-12 19:26:58 -07:00
Muhsin Keloth
48fa7bf72b
fix: Handle nil processed_params for WhatsApp templates without params (#12177)
WhatsApp templates without parameters (body-only templates like
notifications, confirmations) were failing to send with the error:
ArgumentError (Unknown legacy format: NilClass). This affected all
parameter-less templates across marketing messages, notifications, and
utility templates.
2025-08-12 22:56:53 +05:30
Sojan Jose
ad4ec9e93b
fix: Flaky Instagram webhook specs (#12170)
### Summary

Fixed flaky Instagram webhook specs that failed intermittently in cloud
environments due to shared let blocks creating conflicting inboxes. The
Instagram channel factory already creates an inbox automatically, but
tests were adding extra ones in shared contexts.
Moved channel/inbox creation to isolated test contexts to prevent race
conditions between Facebook Page and Instagram Direct tests.

### Testing

```
for i in {1..30}; do 
  echo "=== Run $i ==="
  RAILS_ENV=test bundle exec rspec spec/jobs/webhooks/instagram_events_job_spec.rb --fail-fast || break
done
```

Previously, intermittent failures could be reproduced locally. With
these changes, tests achieve ~100% pass rate.
2025-08-12 20:12:18 +05:30
Muhsin Keloth
dbb164a37d
fix: Improve WhatsApp template message error handling (#12168)
WhatsApp template message errors were not being properly handled because
the `@message instance` variable was only set in the `send_message`
method but not in `send_template`. When template sending failed, the
`handle_error` method couldn't update the message status due to the
missing @message reference, resulting in silent failures with no user
feedback.
2025-08-12 16:31:56 +05:30
Muhsin Keloth
fdcfed2cd7
feat: Add WhatsApp profile for contact name resolution (#12123)
Fixes https://linear.app/chatwoot/issue/CW-4397/whatsapp-contacts-name-update-after-responsd-to-template
2025-08-12 14:20:52 +05:30
Gabriel Jablonski
587623a09f
fix: ensure contact name defaults to phone number when pushName is absent (#94) 2025-08-11 23:10:31 -03:00
Petterson
81d8d3862d
feat: Add route to list accounts that belongs to a platform_app (#12140)
This PR creates a new route to list all accounts that a platform_app has access to.

Fixes: #12109
2025-08-11 21:23:05 +02:00
Sojan Jose
c31325e982
fix: resolve mutex conflicts in Instagram webhook specs (#12154)
This PR fixes flaky test failures in the Instagram webhook specs that
were caused by Redis mutex lock conflicts when
   tests ran in parallel.

 ### The Problem:
The InstagramEventsJob uses a Redis mutex with a key based on sender_id
and ig_account_id to prevent race
conditions. However, all test factories were using the same hardcoded
sender_id: 'Sender-id-1', causing multiple
test instances to compete for the same mutex lock when running in
parallel.

 ### The Solution:
- Updated all Instagram event factories to generate unique sender IDs
using SecureRandom.hex(4)
- Modified test stubs and expectations to work with dynamic sender IDs
instead of hardcoded values
- Ensured each test instance gets its own unique mutex key, eliminating
lock contention
2025-08-11 23:31:25 +05:30
Muhsin Keloth
28452b300d
chore: WhatsApp template message error handling for invalid templates (#12157) 2025-08-11 20:08:52 +05:30
Muhsin Keloth
6784eb9b3d
feat: Enhanced WhatsApp template support with media headers (#11997) 2025-08-11 18:49:05 +05:30
Shivam Mishra
fcc6e2b8b2
feat: Add feature_citation toggle for Captain assistants (#12052)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-11 13:06:20 +05:30
Vishnu Narayanan
6cab741392
fix: handle active storage preview error for password protected pdfs (#11888)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-11 12:41:37 +05:30
Sojan Jose
3214d06a83
fix: Error shouldn't halt the campaign for entire audience (#11980)
## Summary
- handle Twilio failures per contact when running one-off SMS campaigns
- rescue errors in WhatsApp and generic SMS one-off campaigns so they
continue
- add specs confirming campaigns continue sending when a single contact
fails

fixes:  https://github.com/chatwoot/chatwoot/issues/9000

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-11 12:03:48 +05:30
Petterson
fd28ed8d83
feat: add support to embedded whatsapp coexistence method (#12108)
This update adds support to the coexistence method to Embedded Whatsapp,
allowing users to add their existing whatsapp business number in order
to use it in both places(chatwoot and whatsapp business) at the same
time.

This update require some changes in the permissions for the Meta App, as
described in the Meta Oficial Docs, I'll leave this listed below:

- **history** — describes past messages the business customer has
sent/received
- **smb_app_state_sync** — describes the business customer's current and
new contacts
- **smb_message_echoes** — describes any new messages the business
customer sends with the WhatsApp Business app after having been
onboarded

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com>
2025-08-08 18:28:50 +05:30
Shivam Mishra
b5f5c5c1bc
feat: add more tools (#12116)
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-08 17:57:30 +05:30
Tanmay Deep Sharma
d2583d32e9
feat: add reauth flow for wa embedded signup (#11940)
# Pull Request Template

## Description

Please include a summary of the change and issue(s) fixed. Also, mention
relevant motivation, context, and any dependencies that this change
requires.
Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.


## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-08 01:48:45 +05:30
Vishnu Narayanan
462ab5241c
perf: fix notifications duplicate query and add composite index (#12110)
Database CPU utilization was spiking due to expensive notification COUNT
queries. Analysis revealed two critical issues:

1. Missing database index: Notification count queries were performing
table scans without proper indexing
2. Duplicate WHERE clauses: SQL queries contained redundant read_at IS
NULL conditions, causing unnecessary query complexity

 ### Root Cause Analysis

  The expensive queries were:
```
  -- 41.61 calls/sec with duplicate condition
  SELECT COUNT(*) FROM "notifications"
  WHERE "notifications"."user_id" = $1
    AND "notifications"."account_id" = $2
    AND "notifications"."snoozed_until" IS NULL
    AND "notifications"."read_at" IS NULL
    AND "notifications"."read_at" IS NULL  -- Duplicate!
```
This was caused by a logic error in NotificationFinder#unread_count
introduced in commit cd06b2b33 (PR #8907). The method assumed
@notifications contained all notifications, but @notifications was
already filtered to unread notifications in most cases.

###  The Default Query Flow:

1. Frontend calls: NotificationsAPI.getUnreadCount() →
/notifications/unread_count
  2. No parameters sent, so params = {}
  3. NotificationFinder setup:
    - find_all_notifications: WHERE user_id = ? AND account_id = ?
    - filter_snoozed_notifications: WHERE snoozed_until IS NULL
- filter_read_notifications: WHERE read_at IS NULL (because
type_included?('read') is false)
  4. unread_count called: Adds another WHERE read_at IS NULL
----
### Solution

  1. Added Missing Database Index
  - Index: (user_id, account_id, snoozed_until, read_at)
  2. Fixed Duplicate WHERE Clause Logic
2025-08-07 15:59:40 +05:30
Muhsin Keloth
f984d745e7
feat: Integrate Twilio WhatsApp ProfileName for contact name resolution (#12122)
- Update existing contacts retroactively when ProfileName is available
- Only update contacts whose names exactly match their phone numbers
2025-08-07 12:53:39 +05:30
Muhsin Keloth
855dd590ab
fix: Use WhatsApp profile name for contacts created via Twilio (#12105)
- Use `ProfileName` parameter from Twilio WhatsApp webhooks when
creating contacts
- Fall back to formatted phone number for regular SMS contacts
2025-08-05 13:55:24 +05:30
Pranav
7e70f7a68a
fix: Disable automations on auto-reply emails (#12101)
The term "sorcerer’s apprentice mode" is defined as a bug in a protocol
where, under some circumstances, the receipt of a message causes
multiple messages to be sent, each of which, when received, triggers the
same bug. - RFC3834

Reference: https://github.com/chatwoot/chatwoot/pull/9606

This PR:
- Adds an auto_reply attribute to message.
- Adds an auto_reply attribute to conversation. 
- Disable conversation_created / conversation_opened event if auto_reply
is set.
- Disable message_created event if auto_reply is set.

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-08-05 13:17:06 +05:30
Pranav
661e905dbd
fix: Skip HookJob for inactive or irrelevant hooks (#12093)
On Aug 2, we had a P0 because of a sudden spike in Sidekiq jobs. The
queue went up to 100k jobs and workers scaled from 400 threads to 1000+.
Most of the jobs were HookJobs, and a large chunk of them were for
Linear but they weren’t doing anything useful.

Turns out, whenever there’s an update on a contact or conversation, we
were triggering all account-level hooks without checking if the event
was relevant. So if someone did a bulk import or ran an update, it would
enqueue a huge number of unnecessary jobs.

This PR adds two checks before enqueuing:
- Whether the hook is active
- Whether the event is relevant for that hook
2025-08-04 19:08:45 -07:00
Muhsin Keloth
60a1e9b15d
fix: Populate meta field for whatsApp shared contacts (#12097)
Fixes https://github.com/chatwoot/chatwoot/issues/11999
2025-08-04 14:50:45 -07:00
Pranav
51b9fd8eca
fix: Disable IMAP inboxes that requires authorization (#12092)
This PR disables queueing IMAP sync jobs for emails channels that 
- are in free plan if on Chatwoot cloud.
- requires authorization
2025-08-01 16:32:29 -07:00