From 05bda5f742bf3a76e88f5df41d9aa4bbc0eea81c Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 13 May 2026 20:09:48 +0530 Subject: [PATCH] feat: don't let onboarding write domain (#14442) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop the onboarding flow from writing the user's company website into `accounts.domain`. That column is reserved for the inbound email domain used to construct reply-to addresses (`reply+@`), and silently overloading it from onboarding was breaking email continuity for accounts whose domain MX didn't point at Chatwoot's inbound — customer replies were going to an unreachable address. The website value now lives in `custom_attributes.website`, which is what the rest of the app already treats as the "company website" field. --- app/controllers/api/v1/accounts_controller.rb | 2 +- .../dashboard/routes/dashboard/onboarding/Index.vue | 4 ++-- app/models/account.rb | 3 +++ app/services/onboarding/web_widget_creation_service.rb | 2 +- app/views/api/v1/models/_account.json.jbuilder | 1 + .../enterprise/onboarding/web_widget_creation_service_spec.rb | 3 ++- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index dddf3dd09..865b387b9 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -111,7 +111,7 @@ class Api::V1::AccountsController < Api::BaseController end def custom_attributes_params - params.permit(:industry, :company_size, :timezone, :referral_source, :user_role) + params.permit(:industry, :company_size, :timezone, :referral_source, :user_role, :website) end def settings_params diff --git a/app/javascript/dashboard/routes/dashboard/onboarding/Index.vue b/app/javascript/dashboard/routes/dashboard/onboarding/Index.vue index 66ac0d57f..592672462 100644 --- a/app/javascript/dashboard/routes/dashboard/onboarding/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/onboarding/Index.vue @@ -134,7 +134,7 @@ const populateFormFields = () => { if (!locale.value) locale.value = detectBestLocale(); if (!website.value) { - website.value = account?.domain || brandInfo?.domain || ''; + website.value = attrs.website || brandInfo?.domain || ''; } if (!timezone.value) { timezone.value = @@ -216,7 +216,7 @@ const handleSubmit = async () => { await updateAccount({ name: accountName.value, locale: locale.value, - domain: website.value, + website: website.value, industry: industry.value, company_size: companySize.value, timezone: timezone.value, diff --git a/app/models/account.rb b/app/models/account.rb index 6070b57f4..b4cc03337 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -38,6 +38,9 @@ class Account < ApplicationRecord }.freeze validates :name, presence: true + # `domain` is the inbound email domain used to construct reply addresses + # (see `inbound_email_domain`). Do not repurpose it for a website or any + # non-mail-related domain. validates :domain, length: { maximum: 100 } validates_with JsonSchemaValidator, schema: SETTINGS_PARAMS_SCHEMA, diff --git a/app/services/onboarding/web_widget_creation_service.rb b/app/services/onboarding/web_widget_creation_service.rb index 363643f05..502b67e6c 100644 --- a/app/services/onboarding/web_widget_creation_service.rb +++ b/app/services/onboarding/web_widget_creation_service.rb @@ -55,7 +55,7 @@ class Onboarding::WebWidgetCreationService end def website_url - @account.domain.presence || brand_info[:domain].presence + @account.custom_attributes['website'].presence || brand_info[:domain].presence end def widget_color diff --git a/app/views/api/v1/models/_account.json.jbuilder b/app/views/api/v1/models/_account.json.jbuilder index 5253e7c70..7506592ba 100644 --- a/app/views/api/v1/models/_account.json.jbuilder +++ b/app/views/api/v1/models/_account.json.jbuilder @@ -6,6 +6,7 @@ if resource.custom_attributes.present? json.subscribed_quantity resource.custom_attributes['subscribed_quantity'] json.subscription_status resource.custom_attributes['subscription_status'] json.subscription_ends_on resource.custom_attributes['subscription_ends_on'] + json.website resource.custom_attributes['website'] if resource.custom_attributes['website'].present? json.industry resource.custom_attributes['industry'] if resource.custom_attributes['industry'].present? json.company_size resource.custom_attributes['company_size'] if resource.custom_attributes['company_size'].present? json.timezone resource.custom_attributes['timezone'] if resource.custom_attributes['timezone'].present? diff --git a/spec/enterprise/services/enterprise/onboarding/web_widget_creation_service_spec.rb b/spec/enterprise/services/enterprise/onboarding/web_widget_creation_service_spec.rb index 90272f5ef..eb379d5db 100644 --- a/spec/enterprise/services/enterprise/onboarding/web_widget_creation_service_spec.rb +++ b/spec/enterprise/services/enterprise/onboarding/web_widget_creation_service_spec.rb @@ -7,7 +7,8 @@ end RSpec.describe Enterprise::Onboarding::WebWidgetCreationService do let(:account) do - create(:account, name: 'Acme Inc', domain: 'acme.com', custom_attributes: { + create(:account, name: 'Acme Inc', custom_attributes: { + 'website' => 'acme.com', 'brand_info' => { 'slogan' => 'Fallback slogan', 'description' => 'Fallback description' } }) end