On self-hosted instances without email configured, users created from
Super Admin can get stuck in an unconfirmed state. This PR implements
the default at the Super Admin frontend form layer, not in backend
creation logic.
What changed:
- Added a custom `ConfirmedAtField` for Super Admin user forms.
- Prefills `confirmed_at` with current time on the **New User** form
(`GET /super_admin/users/new`).
- Kept backend create behavior unchanged
(`resource_class.new(resource_params)`), so API/manual payloads still
behave normally.
Behavior:
- In Super Admin UI, `confirmed_at` is prefilled by default.
- If someone wants an unconfirmed user, they can clear the
`confirmed_at` field before saving.
- If `confirmed_at` is omitted from payload entirely, the created user
remains unconfirmed.
Scope note: external signup flows are intentionally unchanged in this PR
(`/api/v1/accounts`, `/api/v2/accounts`, and social/omniauth signup
behavior are not modified).
## Demo
https://github.com/user-attachments/assets/436abbb0-d4cf-49a6-a1b8-4b6aa85aa09f
Description:
## Summary
- `redis-client` 0.22.2 uses `.call()` during Sentinel master
resolution, but `redis-rb` 5.x undefines `.call()` (only `.call_v()`
exists), causing Sentinel connections to fail.
- Bumps `redis-client` from 0.22.2 to 0.26.4 which includes the upstream
fix (redis-rb/redis-client#283).
- Also bumps transitive dependency `connection_pool` from 2.5.3 to
2.5.5.
Fixes#11665https://github.com/chatwoot/chatwoot/issues/8368
## Test
- `bundle exec rspec spec/lib/redis/config_spec.rb` passes
- Full CI suite passes
## Description
Reduces the frequency of update_presence WebSocket calls from the live
chat widget and fixes agents appearing offline when the dashboard is in
a background tab.
## Fixes # (issue)
https://github.com/chatwoot/chatwoot/issues/13720
## Type of change
- [ ] Bug fix (non-breaking change which fixes an issue)
## 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
Agents using API channel inboxes (e.g., WhatsApp Automate) reported
seeing the same conversation appear twice in their conversation list —
one showing the last message preview and the other showing "No
Messages". Backend investigation confirmed no duplicate conversations
exist in the database, making this purely a frontend issue.
The root cause is a race condition in WebSocket event delivery. When a
conversation is created via the API with auto-assignment, the backend
enqueues multiple ActionCable broadcast jobs (`conversation.created`,
`assignee.changed`, `team.changed`) within milliseconds of each other.
In production with multi-threaded Sidekiq workers, these events can
arrive at the frontend out of order. If `assignee.changed` arrives
before `conversation.created`, the `UPDATE_CONVERSATION` mutation pushes
the conversation into the store (since it doesn't exist yet), and then
`ADD_CONVERSATION` blindly pushes it again — resulting in a duplicate
entry.
The fix adds a uniqueness check in the `ADD_CONVERSATION` mutation to
skip the push if a conversation with the same ID already exists in the
store, matching the dedup pattern already used by
`SET_ALL_CONVERSATION`.
## Summary
This Enterprise-only feature automatically fetches a favicon for
companies created with a domain, and adds a batch task to backfill
missing avatars for existing companies. The flow only targets companies
that do not already have an attached avatar, so existing avatars are
left untouched.
## Demo
https://github.com/user-attachments/assets/d050334e-769f-4e46-b6e7-f7423727a192
## What changed
- Added `Avatar::AvatarFromFaviconJob` to build a Google favicon URL
from the company domain and fetch it through `Avatar::AvatarFromUrlJob`
- Triggered favicon fetching from `Company` with `after_create_commit`
- Added `Companies::FetchAvatarsJob` to batch existing companies that
are missing avatars
- Added `companies:fetch_missing_avatars` under `enterprise/lib/tasks`
- Kept the company-specific implementation inside the Enterprise
boundary
- Stubbed the new favicon request in unrelated specs that now hit this
callback indirectly
- Updated a couple of CI-sensitive specs that were failing due to
callback side effects / reload-safe exception assertions
## How to verify
1. Create a company in Enterprise with a valid domain and no avatar.
2. Confirm that a favicon-based avatar gets attached shortly after
creation.
3. Create another company with a domain and an avatar already attached.
4. Confirm that the existing avatar is not replaced.
5. Run `companies:fetch_missing_avatars`.
6. Confirm that existing companies without avatars get one, while
companies that already have avatars remain unchanged.
## Notes
- This change does not refresh or overwrite existing company avatars
- Favicon fetching only runs for companies with a present domain
- The branch includes the latest `develop`
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Agent bot conversations now feel more natural because AgentBot tokens
can toggle typing status, so end users see a live typing indicator in
the widget while the bot is preparing a reply. This keeps the
interaction responsive and human-like without weakening token
authorization boundaries.
## Closes
- https://github.com/chatwoot/chatwoot/issues/8928
- https://linear.app/chatwoot/issue/CW-5205
## How to test
1. Open the widget and start a conversation as a customer.
2. Connect an AgentBot to the same inbox.
3. Trigger `toggle_typing_status` with the AgentBot token
(`typing_status: on`).
4. Confirm the customer sees the typing indicator in the widget.
5. Trigger `toggle_typing_status` with `typing_status: off` and confirm
the indicator disappears.
## What changed
- Added `toggle_typing_status` to bot-accessible conversation endpoints.
- Restricted bot-accessible endpoint usage to `AgentBot` token owners
only (non-user tokens like `PlatformApp` remain unauthorized).
- Updated typing status flow to preserve AgentBot identity in
dispatch/broadcast paths.
- Added request coverage for AgentBot success and PlatformApp
unauthorized behavior.
- Added Swagger documentation for `POST
/api/v1/accounts/{account_id}/conversations/{conversation_id}/toggle_typing_status`
and regenerated swagger artifacts.