flow_chat 0.4.2 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/SECURITY.md ADDED
@@ -0,0 +1,365 @@
1
+ # FlowChat Security Guide
2
+
3
+ This guide covers the security features and best practices for FlowChat, including webhook signature validation and simulator authentication.
4
+
5
+ ## Overview
6
+
7
+ FlowChat includes comprehensive security features to protect your WhatsApp and USSD applications:
8
+
9
+ - **Webhook Signature Validation**: Verify that WhatsApp webhooks are authentic
10
+ - **Simulator Authentication**: Secure access to the testing simulator
11
+ - **Configuration Validation**: Prevent insecure configurations
12
+ - **Environment-Specific Security**: Different security levels per environment
13
+
14
+ ## WhatsApp Webhook Security
15
+
16
+ ### Signature Validation
17
+
18
+ FlowChat automatically validates WhatsApp webhook signatures using HMAC-SHA256 to ensure requests come from WhatsApp.
19
+
20
+ #### Required Configuration
21
+
22
+ For webhook signature validation, you need to configure your WhatsApp app secret:
23
+
24
+ ```ruby
25
+ # Using Rails credentials
26
+ rails credentials:edit
27
+ ```
28
+
29
+ ```yaml
30
+ whatsapp:
31
+ app_secret: "your_whatsapp_app_secret"
32
+ # ... other credentials
33
+ ```
34
+
35
+ Or using environment variables:
36
+
37
+ ```bash
38
+ export WHATSAPP_APP_SECRET="your_whatsapp_app_secret"
39
+ ```
40
+
41
+ #### Security Modes
42
+
43
+ FlowChat supports two security modes for webhook validation:
44
+
45
+ **1. Full Security (Recommended for Production)**
46
+
47
+ ```ruby
48
+ config = FlowChat::Whatsapp::Configuration.new
49
+ config.app_secret = "your_whatsapp_app_secret" # Required
50
+ config.skip_signature_validation = false # Default: enforce validation
51
+ ```
52
+
53
+ **2. Development Mode (Testing Only)**
54
+
55
+ ```ruby
56
+ config = FlowChat::Whatsapp::Configuration.new
57
+ config.app_secret = nil # Not required when disabled
58
+ config.skip_signature_validation = true # Explicitly disable validation
59
+ ```
60
+
61
+ ⚠️ **Security Warning**: Never disable signature validation in production environments.
62
+
63
+ #### Configuration Error Handling
64
+
65
+ When `app_secret` is missing and validation is not explicitly disabled, FlowChat raises a `ConfigurationError`:
66
+
67
+ ```ruby
68
+ begin
69
+ processor.run WelcomeFlow, :main_page
70
+ rescue FlowChat::Whatsapp::ConfigurationError => e
71
+ Rails.logger.error "Security configuration error: #{e.message}"
72
+ head :internal_server_error
73
+ end
74
+ ```
75
+
76
+ The error message provides clear guidance:
77
+
78
+ ```
79
+ WhatsApp app_secret is required for webhook signature validation.
80
+ Either configure app_secret or set skip_signature_validation=true to explicitly disable validation.
81
+ ```
82
+
83
+ ### Environment-Specific Security
84
+
85
+ Configure different security levels per environment:
86
+
87
+ ```ruby
88
+ # config/initializers/flowchat.rb
89
+ case Rails.env
90
+ when 'development'
91
+ # Relaxed security for easier development
92
+ config.skip_signature_validation = true
93
+
94
+ when 'test'
95
+ # Skip validation for deterministic testing
96
+ config.skip_signature_validation = true
97
+
98
+ when 'staging', 'production'
99
+ # Full security for production-like environments
100
+ config.skip_signature_validation = false
101
+
102
+ # Ensure app_secret is configured
103
+ if ENV['WHATSAPP_APP_SECRET'].blank?
104
+ raise "WHATSAPP_APP_SECRET required for #{Rails.env} environment"
105
+ end
106
+ end
107
+ ```
108
+
109
+ ## Simulator Security
110
+
111
+ ### Authentication System
112
+
113
+ The FlowChat simulator uses secure HMAC-SHA256 signed cookies for authentication. This prevents unauthorized access to your simulator endpoints.
114
+
115
+ #### Required Configuration
116
+
117
+ Configure a simulator secret in your initializer:
118
+
119
+ ```ruby
120
+ # config/initializers/flowchat.rb
121
+ FlowChat::Config.simulator_secret = "your_secure_secret_here"
122
+ ```
123
+
124
+ #### Environment-Specific Secrets
125
+
126
+ Use different secrets per environment:
127
+
128
+ ```ruby
129
+ case Rails.env
130
+ when 'development', 'test'
131
+ # Use Rails secret key with environment suffix
132
+ FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_#{Rails.env}"
133
+
134
+ when 'staging', 'production'
135
+ # Use environment variable for production
136
+ FlowChat::Config.simulator_secret = ENV['FLOWCHAT_SIMULATOR_SECRET']
137
+
138
+ if FlowChat::Config.simulator_secret.blank?
139
+ Rails.logger.warn "FLOWCHAT_SIMULATOR_SECRET not configured. Simulator will be unavailable."
140
+ end
141
+ end
142
+ ```
143
+
144
+ #### Cookie Security
145
+
146
+ Simulator cookies are automatically configured with security best practices:
147
+
148
+ - **HMAC-SHA256 signed**: Prevents tampering
149
+ - **24-hour expiration**: Limits exposure window
150
+ - **Secure flag**: Only sent over HTTPS in production
151
+ - **HttpOnly flag**: Prevents XSS access
152
+ - **SameSite=Lax**: CSRF protection
153
+
154
+ #### Enabling Simulator Mode
155
+
156
+ Enable simulator mode only when needed:
157
+
158
+ ```ruby
159
+ # Enable simulator only in development/staging
160
+ enable_simulator = Rails.env.development? || Rails.env.staging?
161
+
162
+ processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator: enable_simulator) do |config|
163
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
164
+ config.use_session_store FlowChat::Session::CacheSessionStore
165
+ end
166
+ ```
167
+
168
+ ### Simulator Request Flow
169
+
170
+ 1. **User visits simulator**: Browser requests `/simulator`
171
+ 2. **Cookie generation**: Server generates HMAC-signed cookie
172
+ 3. **Simulator requests**: Include valid cookie for authentication
173
+ 4. **Cookie validation**: Server validates HMAC signature and timestamp
174
+ 5. **Request processing**: Continues if authentication succeeds
175
+
176
+ ## Security Best Practices
177
+
178
+ ### Production Checklist
179
+
180
+ ✅ **WhatsApp Security**
181
+ - Configure `app_secret` for webhook validation
182
+ - Set `skip_signature_validation = false`
183
+ - Use environment variables for secrets
184
+ - Handle `ConfigurationError` exceptions
185
+
186
+ ✅ **Simulator Security**
187
+ - Configure `simulator_secret` using environment variables
188
+ - Enable simulator only in development/staging
189
+ - Use unique secrets per environment
190
+
191
+ ✅ **Environment Configuration**
192
+ - Different security levels per environment
193
+ - Fail fast on missing required configuration
194
+ - Log security warnings appropriately
195
+
196
+ ✅ **Error Handling**
197
+ - Catch and log `ConfigurationError` exceptions
198
+ - Return appropriate HTTP status codes
199
+ - Don't expose sensitive information in errors
200
+
201
+ ### Development Guidelines
202
+
203
+ **DO:**
204
+ - Use Rails `secret_key_base` + suffix for development secrets
205
+ - Skip webhook validation in development for easier testing
206
+ - Enable simulator mode for testing
207
+ - Use test-specific credentials in test environment
208
+
209
+ **DON'T:**
210
+ - Hardcode secrets in source code
211
+ - Disable security in production
212
+ - Use production secrets in development
213
+ - Commit secrets to version control
214
+
215
+ ### Example Secure Configuration
216
+
217
+ ```ruby
218
+ # config/initializers/flowchat.rb
219
+ case Rails.env
220
+ when 'development'
221
+ FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_dev"
222
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
223
+
224
+ when 'test'
225
+ FlowChat::Config.simulator_secret = "test_secret_#{Rails.application.secret_key_base}"
226
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
227
+
228
+ when 'staging'
229
+ FlowChat::Config.simulator_secret = ENV.fetch('FLOWCHAT_SIMULATOR_SECRET')
230
+ FlowChat::Config.whatsapp.message_handling_mode = :inline
231
+
232
+ when 'production'
233
+ FlowChat::Config.simulator_secret = ENV.fetch('FLOWCHAT_SIMULATOR_SECRET')
234
+ FlowChat::Config.whatsapp.message_handling_mode = :background
235
+ FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
236
+ end
237
+ ```
238
+
239
+ ## Testing Security Features
240
+
241
+ ### Webhook Signature Validation Tests
242
+
243
+ ```ruby
244
+ test "webhook accepts valid signature" do
245
+ payload = valid_webhook_payload.to_json
246
+ signature = OpenSSL::HMAC.hexdigest(
247
+ OpenSSL::Digest.new("sha256"),
248
+ "your_app_secret",
249
+ payload
250
+ )
251
+
252
+ post "/whatsapp/webhook",
253
+ params: payload,
254
+ headers: {
255
+ "Content-Type" => "application/json",
256
+ "X-Hub-Signature-256" => "sha256=#{signature}"
257
+ }
258
+
259
+ assert_response :success
260
+ end
261
+
262
+ test "webhook rejects invalid signature" do
263
+ post "/whatsapp/webhook",
264
+ params: valid_webhook_payload,
265
+ headers: { "X-Hub-Signature-256" => "sha256=invalid_signature" }
266
+
267
+ assert_response :unauthorized
268
+ end
269
+
270
+ test "webhook rejects missing signature" do
271
+ post "/whatsapp/webhook", params: valid_webhook_payload
272
+ assert_response :unauthorized
273
+ end
274
+ ```
275
+
276
+ ### Simulator Authentication Tests
277
+
278
+ ```ruby
279
+ test "simulator requires valid authentication" do
280
+ post "/whatsapp/webhook", params: {
281
+ simulator_mode: true,
282
+ # ... webhook payload
283
+ }
284
+
285
+ assert_response :unauthorized # No valid simulator cookie
286
+ end
287
+
288
+ test "simulator accepts valid authentication" do
289
+ # Generate valid simulator cookie
290
+ timestamp = Time.now.to_i
291
+ message = "simulator:#{timestamp}"
292
+ signature = OpenSSL::HMAC.hexdigest(
293
+ OpenSSL::Digest.new("sha256"),
294
+ FlowChat::Config.simulator_secret,
295
+ message
296
+ )
297
+
298
+ post "/whatsapp/webhook",
299
+ params: { simulator_mode: true, /* ... */ },
300
+ cookies: { flowchat_simulator: "#{timestamp}:#{signature}" }
301
+
302
+ assert_response :success
303
+ end
304
+ ```
305
+
306
+ ## Troubleshooting
307
+
308
+ ### Common Issues
309
+
310
+ **1. ConfigurationError: app_secret required**
311
+
312
+ ```
313
+ WhatsApp app_secret is required for webhook signature validation.
314
+ ```
315
+
316
+ **Solution**: Configure `WHATSAPP_APP_SECRET` environment variable or disable validation explicitly.
317
+
318
+ **2. Invalid webhook signature**
319
+
320
+ ```
321
+ Invalid webhook signature received
322
+ ```
323
+
324
+ **Solution**: Verify your `app_secret` matches your WhatsApp app configuration.
325
+
326
+ **3. Simulator authentication failed**
327
+
328
+ ```
329
+ Invalid simulator cookie format
330
+ ```
331
+
332
+ **Solution**: Ensure `FlowChat::Config.simulator_secret` is properly configured.
333
+
334
+ **4. Missing simulator secret**
335
+
336
+ ```
337
+ Simulator secret not configured
338
+ ```
339
+
340
+ **Solution**: Set `FLOWCHAT_SIMULATOR_SECRET` environment variable or configure in initializer.
341
+
342
+ ### Debug Mode
343
+
344
+ Enable debug logging for security events:
345
+
346
+ ```ruby
347
+ # config/initializers/flowchat.rb
348
+ if Rails.env.development?
349
+ FlowChat::Config.logger.level = Logger::DEBUG
350
+ end
351
+ ```
352
+
353
+ This will log security validation attempts and help troubleshoot configuration issues.
354
+
355
+ ## Security Updates
356
+
357
+ This security system was introduced in FlowChat v2.0.0 and includes:
358
+
359
+ - HMAC-SHA256 webhook signature validation
360
+ - Secure simulator authentication with signed cookies
361
+ - Environment-specific security configuration
362
+ - Comprehensive error handling and logging
363
+ - Timing-attack resistant signature comparison
364
+
365
+ For the latest security updates and recommendations, check the FlowChat changelog and security advisories.
@@ -19,6 +19,22 @@ FlowChat::Config.cache = Rails.cache
19
19
  # Configure logger (optional)
20
20
  FlowChat::Config.logger = Rails.logger
21
21
 
22
+ # Configure simulator security (REQUIRED for simulator mode)
23
+ # This secret is used to authenticate simulator requests via signed cookies
24
+ case Rails.env
25
+ when 'development', 'test'
26
+ # Use Rails secret key with environment suffix for development
27
+ FlowChat::Config.simulator_secret = Rails.application.secret_key_base + "_#{Rails.env}"
28
+ when 'staging', 'production'
29
+ # Use environment variable for production security
30
+ FlowChat::Config.simulator_secret = ENV['FLOWCHAT_SIMULATOR_SECRET']
31
+
32
+ # Fail fast if simulator secret is not configured but might be needed
33
+ if FlowChat::Config.simulator_secret.blank?
34
+ Rails.logger.warn "FLOWCHAT_SIMULATOR_SECRET not configured. Simulator mode will be unavailable."
35
+ end
36
+ end
37
+
22
38
  # Configure USSD pagination (optional)
23
39
  FlowChat::Config.ussd.pagination_page_size = 140
24
40
  FlowChat::Config.ussd.pagination_back_option = "0"
@@ -29,3 +45,42 @@ FlowChat::Config.ussd.pagination_next_text = "More"
29
45
  # Configure resumable sessions (optional)
30
46
  FlowChat::Config.ussd.resumable_sessions_enabled = true
31
47
  FlowChat::Config.ussd.resumable_sessions_timeout_seconds = 300 # 5 minutes
48
+
49
+ # Configure WhatsApp message handling mode based on environment
50
+ case Rails.env
51
+ when 'development'
52
+ # Development: Use simulator mode for easy testing
53
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
54
+
55
+ when 'test'
56
+ # Test: Use simulator mode for deterministic testing
57
+ FlowChat::Config.whatsapp.message_handling_mode = :simulator
58
+
59
+ when 'staging'
60
+ # Staging: Use inline mode for real WhatsApp testing
61
+ FlowChat::Config.whatsapp.message_handling_mode = :inline
62
+
63
+ when 'production'
64
+ # Production: Use background mode for high volume
65
+ FlowChat::Config.whatsapp.message_handling_mode = :background
66
+ FlowChat::Config.whatsapp.background_job_class = 'WhatsappMessageJob'
67
+ end
68
+
69
+ # Configure per-environment WhatsApp security
70
+ # Note: These are global defaults. You can override per-configuration in your controllers.
71
+
72
+ # Example of per-environment WhatsApp security configuration:
73
+ #
74
+ # For development/test: You might want to disable signature validation for easier testing
75
+ # For staging: Enable validation to match production behavior
76
+ # For production: Always enable validation for security
77
+ #
78
+ # Individual WhatsApp configurations can override these settings:
79
+ #
80
+ # config = FlowChat::Whatsapp::Configuration.new
81
+ # config.access_token = "your_token"
82
+ # config.app_secret = "your_app_secret" # Required for webhook validation
83
+ # config.skip_signature_validation = false # false = validate signatures (recommended)
84
+ #
85
+ # Development override example:
86
+ # config.skip_signature_validation = Rails.env.development? # Only skip in development
@@ -11,7 +11,11 @@ class MultiTenantWhatsappController < ApplicationController
11
11
  # Get tenant-specific WhatsApp configuration
12
12
  whatsapp_config = get_whatsapp_config_for_tenant(tenant)
13
13
 
14
- processor = FlowChat::Whatsapp::Processor.new(self) do |config|
14
+ # Enable simulator for local endpoint testing during development
15
+ # This allows testing different tenant endpoints via the simulator interface
16
+ enable_simulator = Rails.env.development? || Rails.env.staging?
17
+
18
+ processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator: enable_simulator) do |config|
15
19
  config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, whatsapp_config
16
20
  config.use_session_store FlowChat::Session::CacheSessionStore
17
21
  end
@@ -0,0 +1,95 @@
1
+ # Example Simulator Controller
2
+ # Add this to your Rails application as app/controllers/simulator_controller.rb
3
+
4
+ class SimulatorController < ApplicationController
5
+ include FlowChat::Simulator::Controller
6
+
7
+ def index
8
+ flowchat_simulator
9
+ end
10
+
11
+ protected
12
+
13
+ # Define different local endpoints to test on the same server
14
+ def configurations
15
+ {
16
+ ussd_main: {
17
+ name: "Main USSD Endpoint",
18
+ description: "Primary USSD integration endpoint",
19
+ processor_type: "ussd",
20
+ provider: "nalo",
21
+ endpoint: "/ussd",
22
+ icon: "📱",
23
+ color: "#28a745"
24
+ },
25
+ whatsapp_main: {
26
+ name: "Main WhatsApp Endpoint",
27
+ description: "Primary WhatsApp webhook endpoint",
28
+ processor_type: "whatsapp",
29
+ provider: "cloud_api",
30
+ endpoint: "/whatsapp/webhook",
31
+ icon: "💬",
32
+ color: "#25D366"
33
+ },
34
+ whatsapp_v2: {
35
+ name: "WhatsApp API v2",
36
+ description: "Alternative WhatsApp endpoint (v2 API)",
37
+ processor_type: "whatsapp",
38
+ provider: "cloud_api",
39
+ endpoint: "/api/v2/whatsapp/webhook",
40
+ icon: "🔄",
41
+ color: "#17a2b8"
42
+ },
43
+ whatsapp_tenant_a: {
44
+ name: "Tenant A WhatsApp",
45
+ description: "Multi-tenant WhatsApp endpoint for Tenant A",
46
+ processor_type: "whatsapp",
47
+ provider: "cloud_api",
48
+ endpoint: "/tenants/a/whatsapp/webhook",
49
+ icon: "🏢",
50
+ color: "#fd7e14"
51
+ },
52
+ whatsapp_legacy: {
53
+ name: "Legacy WhatsApp",
54
+ description: "Legacy WhatsApp endpoint for backward compatibility",
55
+ processor_type: "whatsapp",
56
+ provider: "cloud_api",
57
+ endpoint: "/legacy/whatsapp",
58
+ icon: "📦",
59
+ color: "#6c757d"
60
+ }
61
+ }
62
+ end
63
+
64
+ # Default configuration to start with
65
+ def default_config_key
66
+ :whatsapp_main
67
+ end
68
+
69
+ # Default test phone number
70
+ def default_phone_number
71
+ "+1234567890"
72
+ end
73
+
74
+ # Default test contact name
75
+ def default_contact_name
76
+ "Test User"
77
+ end
78
+ end
79
+
80
+ # Add this route to your config/routes.rb:
81
+ # get '/simulator' => 'simulator#index'
82
+
83
+ # Usage:
84
+ # 1. Start your Rails server: rails server
85
+ # 2. Visit http://localhost:3000/simulator
86
+ # 3. Select different endpoints from the dropdown to test
87
+ # 4. Send test messages to see how each endpoint responds
88
+ # 5. View request/response logs in real-time
89
+
90
+ # This allows you to test:
91
+ # - Different controller implementations on the same server
92
+ # - Different API versions (v1, v2, etc.)
93
+ # - Multi-tenant endpoints with different configurations
94
+ # - Legacy endpoints alongside new ones
95
+ # - Different flow implementations for different endpoints
@@ -5,17 +5,24 @@ class WhatsappController < ApplicationController
5
5
  skip_forgery_protection
6
6
 
7
7
  def webhook
8
- processor = FlowChat::Whatsapp::Processor.new(self) do |config|
8
+ # Enable simulator mode for local endpoint testing in development
9
+ processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator: Rails.env.development?) do |config|
9
10
  config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi
10
11
  # Use cache-based session store for longer WhatsApp conversations
11
12
  config.use_session_store FlowChat::Session::CacheSessionStore
12
13
  end
13
14
 
14
15
  processor.run WelcomeFlow, :main_page
16
+ rescue FlowChat::Whatsapp::ConfigurationError => e
17
+ Rails.logger.error "WhatsApp configuration error: #{e.message}"
18
+ head :internal_server_error
19
+ rescue => e
20
+ Rails.logger.error "Unexpected error processing WhatsApp webhook: #{e.message}"
21
+ head :internal_server_error
15
22
  end
16
23
  end
17
24
 
18
- # Example with Custom Configuration
25
+ # Example with Custom Configuration and Security
19
26
  class CustomWhatsappController < ApplicationController
20
27
  skip_forgery_protection
21
28
 
@@ -28,13 +35,95 @@ class CustomWhatsappController < ApplicationController
28
35
  custom_config.app_id = ENV["MY_WHATSAPP_APP_ID"]
29
36
  custom_config.app_secret = ENV["MY_WHATSAPP_APP_SECRET"]
30
37
  custom_config.business_account_id = ENV["MY_WHATSAPP_BUSINESS_ACCOUNT_ID"]
38
+
39
+ # Security configuration
40
+ custom_config.skip_signature_validation = !Rails.env.production? # Only skip in non-production
31
41
 
32
- processor = FlowChat::Whatsapp::Processor.new(self) do |config|
42
+ # Enable simulator for local endpoint testing in non-production environments
43
+ processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator: !Rails.env.production?) do |config|
33
44
  config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, custom_config
34
45
  config.use_session_store FlowChat::Session::CacheSessionStore
35
46
  end
36
47
 
37
48
  processor.run WelcomeFlow, :main_page
49
+ rescue FlowChat::Whatsapp::ConfigurationError => e
50
+ Rails.logger.error "WhatsApp configuration error: #{e.message}"
51
+ head :internal_server_error
52
+ rescue => e
53
+ Rails.logger.error "Unexpected error processing WhatsApp webhook: #{e.message}"
54
+ head :internal_server_error
55
+ end
56
+ end
57
+
58
+ # Example with Environment-Specific Security
59
+ class EnvironmentAwareWhatsappController < ApplicationController
60
+ skip_forgery_protection
61
+
62
+ def webhook
63
+ # Configure security based on environment
64
+ custom_config = build_whatsapp_config
65
+
66
+ # Enable simulator for local endpoint testing in development/staging
67
+ enable_simulator = Rails.env.development? || Rails.env.staging?
68
+
69
+ processor = FlowChat::Whatsapp::Processor.new(self, enable_simulator: enable_simulator) do |config|
70
+ config.use_gateway FlowChat::Whatsapp::Gateway::CloudApi, custom_config
71
+ config.use_session_store FlowChat::Session::CacheSessionStore
72
+ end
73
+
74
+ processor.run WelcomeFlow, :main_page
75
+ rescue FlowChat::Whatsapp::ConfigurationError => e
76
+ Rails.logger.error "WhatsApp configuration error: #{e.message}"
77
+ head :internal_server_error
78
+ rescue => e
79
+ Rails.logger.error "Unexpected error processing WhatsApp webhook: #{e.message}"
80
+ head :internal_server_error
81
+ end
82
+
83
+ private
84
+
85
+ def build_whatsapp_config
86
+ config = FlowChat::Whatsapp::Configuration.new
87
+
88
+ case Rails.env
89
+ when 'development'
90
+ # Development: More relaxed security for easier testing
91
+ config.access_token = ENV["WHATSAPP_ACCESS_TOKEN"]
92
+ config.phone_number_id = ENV["WHATSAPP_PHONE_NUMBER_ID"]
93
+ config.verify_token = ENV["WHATSAPP_VERIFY_TOKEN"]
94
+ config.app_id = ENV["WHATSAPP_APP_ID"]
95
+ config.app_secret = ENV["WHATSAPP_APP_SECRET"] # Optional in development
96
+ config.business_account_id = ENV["WHATSAPP_BUSINESS_ACCOUNT_ID"]
97
+ config.skip_signature_validation = true # Skip validation for easier development
98
+
99
+ when 'test'
100
+ # Test: Use test credentials
101
+ config.access_token = "test_token"
102
+ config.phone_number_id = "test_phone_id"
103
+ config.verify_token = "test_verify_token"
104
+ config.app_id = "test_app_id"
105
+ config.app_secret = "test_app_secret"
106
+ config.business_account_id = "test_business_id"
107
+ config.skip_signature_validation = true # Skip validation in tests
108
+
109
+ when 'staging', 'production'
110
+ # Production: Full security enabled
111
+ config.access_token = ENV["WHATSAPP_ACCESS_TOKEN"]
112
+ config.phone_number_id = ENV["WHATSAPP_PHONE_NUMBER_ID"]
113
+ config.verify_token = ENV["WHATSAPP_VERIFY_TOKEN"]
114
+ config.app_id = ENV["WHATSAPP_APP_ID"]
115
+ config.app_secret = ENV["WHATSAPP_APP_SECRET"] # Required for security
116
+ config.business_account_id = ENV["WHATSAPP_BUSINESS_ACCOUNT_ID"]
117
+ config.skip_signature_validation = false # Always validate in production
118
+
119
+ # Ensure required security configuration is present
120
+ if config.app_secret.blank?
121
+ raise FlowChat::Whatsapp::ConfigurationError,
122
+ "WHATSAPP_APP_SECRET is required for webhook signature validation in #{Rails.env}"
123
+ end
124
+ end
125
+
126
+ config
38
127
  end
39
128
  end
40
129
 
@@ -4,9 +4,10 @@ module FlowChat
4
4
  class BaseProcessor
5
5
  attr_reader :middleware
6
6
 
7
- def initialize(controller)
7
+ def initialize(controller, enable_simulator: nil)
8
8
  @context = FlowChat::Context.new
9
9
  @context["controller"] = controller
10
+ @context["enable_simulator"] = enable_simulator.nil? ? (defined?(Rails) && Rails.env.local?) : enable_simulator
10
11
  @middleware = ::Middleware::Builder.new(name: middleware_name)
11
12
 
12
13
  yield self if block_given?
@@ -3,6 +3,7 @@ module FlowChat
3
3
  # General framework configuration
4
4
  mattr_accessor :logger, default: Logger.new($stdout)
5
5
  mattr_accessor :cache, default: nil
6
+ mattr_accessor :simulator_secret, default: nil
6
7
 
7
8
  # USSD-specific configuration object
8
9
  def self.ussd
@@ -33,11 +34,12 @@ module FlowChat
33
34
 
34
35
  class WhatsappConfig
35
36
  attr_accessor :background_job_class
36
- attr_reader :message_handling_mode
37
+ attr_reader :message_handling_mode, :api_base_url
37
38
 
38
39
  def initialize
39
40
  @message_handling_mode = :inline
40
41
  @background_job_class = "WhatsappMessageJob"
42
+ @api_base_url = "https://graph.facebook.com/v22.0"
41
43
  end
42
44
 
43
45
  # Validate message handling mode