chatwoot/app/javascript/dashboard/featureFlags.js
Muhsin Keloth 0e122188e9
feat: Add voice calling as a capability on Twilio SMS channel(Enterprise) (#13963)
Voice calling is now a capability on the existing TwilioSms rather than
a separate Voice model. A single Twilio phone number handles both SMS
and voice calls through one inbox.
Fixes
https://linear.app/chatwoot/issue/CW-6683/add-voice-calling-as-a-capability-on-twilio-sms-channel
and https://linear.app/chatwoot/issue/PLA-120/add-the-support-for-sms

**What changed**
- Replaced Channel::Voice with voice_enabled flag on Channel::TwilioSms
- Added voice_enabled, twiml_app_sid, api_key_secret columns to
channel_twilio_sms table
  - Dropped channel_voice table (no production data)
- All voice logic lives in Enterprise layer via
prepend_mod_with('Channel::TwilioSms')
- Added Voice settings tab on Twilio SMS inbox settings to
enable/disable voice
  - Validates Twilio number voice capability before provisioning
- Teardown service cleans up TwiML app and credentials when voice is
disabled
- Frontend voice detection uses isVoiceCallEnabled() /
getVoiceCallProvider() helpers — extensible to future providers
  - Gated by channel_voice feature flag

**How to test**

1. Enable feature flag:
Account.find(<id>).enable_features('channel_voice')
2. Create voice inbox: Inboxes → Voice tile → enter Twilio credentials →
verify incoming/outgoing calls and SMS work
3. Enable voice on existing SMS inbox: Inboxes → select Twilio SMS inbox
→ Voice tab → toggle on → provide API key credentials → verify calls
work
4. Disable voice: Voice tab → toggle off → verify TwiML app is deleted,
credentials cleared, SMS still works
5. Re-enable voice: Toggle on again → must provide api_key_secret again
→ new TwiML app provisioned

---------

Co-authored-by: Muhsin <[email protected]>
2026-04-29 11:32:19 +04:00

62 lines
2.0 KiB
JavaScript

export const FEATURE_FLAGS = {
AGENT_BOTS: 'agent_bots',
AGENT_MANAGEMENT: 'agent_management',
ASSIGNMENT_V2: 'assignment_v2',
ADVANCED_ASSIGNMENT: 'advanced_assignment',
AUTO_RESOLVE_CONVERSATIONS: 'auto_resolve_conversations',
AUTOMATIONS: 'automations',
CAMPAIGNS: 'campaigns',
WHATSAPP_CAMPAIGNS: 'whatsapp_campaign',
CANNED_RESPONSES: 'canned_responses',
CRM: 'crm',
CUSTOM_ATTRIBUTES: 'custom_attributes',
INBOX_MANAGEMENT: 'inbox_management',
INTEGRATIONS: 'integrations',
LABELS: 'labels',
MACROS: 'macros',
HELP_CENTER: 'help_center',
REPORTS: 'reports',
TEAM_MANAGEMENT: 'team_management',
VOICE_RECORDER: 'voice_recorder',
AUDIT_LOGS: 'audit_logs',
INBOX_VIEW: 'inbox_view',
SLA: 'sla',
CHANNEL_EMAIL: 'channel_email',
CHANNEL_FACEBOOK: 'channel_facebook',
CHANNEL_WEBSITE: 'channel_website',
CUSTOM_REPLY_DOMAIN: 'custom_reply_domain',
CUSTOM_REPLY_EMAIL: 'custom_reply_email',
DISABLE_BRANDING: 'disable_branding',
EMAIL_CONTINUITY_ON_API_CHANNEL: 'email_continuity_on_api_channel',
INBOUND_EMAILS: 'inbound_emails',
IP_LOOKUP: 'ip_lookup',
LINEAR: 'linear_integration',
CAPTAIN: 'captain_integration',
CUSTOM_ROLES: 'custom_roles',
CHATWOOT_V4: 'chatwoot_v4',
CHANNEL_INSTAGRAM: 'channel_instagram',
CHANNEL_TIKTOK: 'channel_tiktok',
CHANNEL_VOICE: 'channel_voice',
CONTACT_CHATWOOT_SUPPORT_TEAM: 'contact_chatwoot_support_team',
CAPTAIN_CUSTOM_TOOLS: 'custom_tools',
CAPTAIN_V2: 'captain_integration_v2',
CAPTAIN_TASKS: 'captain_tasks',
SAML: 'saml',
QUOTED_EMAIL_REPLY: 'quoted_email_reply',
COMPANIES: 'companies',
ADVANCED_SEARCH: 'advanced_search',
CONVERSATION_REQUIRED_ATTRIBUTES: 'conversation_required_attributes',
};
export const PREMIUM_FEATURES = [
FEATURE_FLAGS.SLA,
FEATURE_FLAGS.CAPTAIN,
FEATURE_FLAGS.CAPTAIN_CUSTOM_TOOLS,
FEATURE_FLAGS.CUSTOM_ROLES,
FEATURE_FLAGS.AUDIT_LOGS,
FEATURE_FLAGS.HELP_CENTER,
FEATURE_FLAGS.SAML,
FEATURE_FLAGS.CONVERSATION_REQUIRED_ATTRIBUTES,
FEATURE_FLAGS.ADVANCED_ASSIGNMENT,
];