Adds three new selectable providers behind the existing
Sms.send_message interface. Per-account credentials are namespaced in
the encrypted sms_configs hash (twilio_*, voipms_*, signalwire_*) so
existing BulkVS configs keep working unchanged.
- lib/sms.rb: dispatch via per-provider classes and delegate the
"is this configured" check to each provider, replacing the BulkVS-only
hardcoded gate in enabled_for?.
- lib/sms/providers/twilio.rb: form-encoded POST to the Messages API,
Basic Auth with SID:Token, treats 201-with-error_code as failure.
- lib/sms/providers/voipms.rb: GET with query-string auth, treats
status != "success" as failure even on HTTP 200, enforces the API's
160-byte hard cap up front.
- lib/sms/providers/signalwire.rb: Twilio-shaped client targeting the
per-account Space URL host; strips https:// and trailing / from the
user-supplied space URL.
- app/controllers/sms_settings_controller.rb: extend the
preserve-secret-on-blank-edit pattern to all four providers' password
fields via a SECRET_KEYS array.
- app/views/sms_settings/index.html.erb: dynamic provider select sourced
from Sms::SUPPORTED_PROVIDERS with per-provider field blocks toggled by
a nonce'd inline script (the app's CSP requires nonces on inline JS).
- SMS.md: new "Configuring …" sections for each provider, wire-format
quick-reference table, and updated extension/code-map sections.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>