feat: add Twilio SMS notification channel#3534
Conversation
Adds Twilio SMS as a new notification channel, allowing users to receive SMS alerts via the Twilio API. Backend: provider using HTTP Basic Auth, type registration, validation, service wiring. Uses existing fields: address (Account SID), accessToken (Auth Token), homeserverUrl (From number), phone (To number). Frontend: form UI with 4 fields, validation, i18n keys. Tests: 18 provider tests + updated service test constructor. Closes bluewave-labs#3095 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ajhollid
left a comment
There was a problem hiding this comment.
Looks pretty good 👍
We can declare bespoke fields for twilio here rather than reusing homserverUrl, and we need a couple more tests here.
Thanks for your hard work!
| address: z.string().min(1, "Account SID is required"), | ||
| accessToken: z.string().min(1, "Auth token is required"), | ||
| phone: z.string().min(1, "Recipient phone number is required"), | ||
| homeserverUrl: z.string().min(1, "Twilio phone number is required"), |
There was a problem hiding this comment.
Rather than repurpose the address and homerserverUrl fiels for something they weren't intended for, let's add new fields.
We've already got notification type specific fields like homeserverUrl, so we may as well add twilioPhoneNumber and accountSID or whatever is appropriate here.
Please remember to update repositories/models after making this change. Thanks!
| case "pushover": | ||
| return await this.pushoverProvider.sendMessage!(notification, notificationMessage); | ||
| case "twilio": | ||
| return await this.twilioProvider.sendMessage!(notification, notificationMessage); |
There was a problem hiding this comment.
These two cases (Pushover and Twiliio) are untested, please add the appropriate tests and check coverage by running npm run test
| case "twilio": | ||
| return await this.twilioProvider.sendTestAlert(notification); |
- Added `accountSid` and `twilioPhoneNumber` fields to Notification type, MongoDB model, and frontend type instead of reusing `address` and `homeserverUrl` - Updated provider, validation, form hook, and form UI to use new fields - Added Pushover and Twilio to notificationsService routing tests (both handleNotifications and sendTestNotification) - All 59 tests passing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Both issues addressed:
All 59 tests passing (18 Twilio provider + 15 Pushover provider + 26 notifications service). |
Updated both MongoDB and TimescaleDB repositories to map the new Twilio-specific fields (accountSid, twilioPhoneNumber) in create, update, and toEntity methods. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
This looks good, but there is no migration for the TimescaleDB implementation. The columns have been added to the query, but they don't exist. Postgres is not forgiving like mongo and won't create columns that don't exist. Let's be sure to add that migration 👍
Other than that, do we care if the account SID and Twilio phone number are compromised? They are currently sent from the BE to the FE in plain text.
If they are sensitive, they probably shouldn't be returned at all.
| accountSid: row.account_sid ?? undefined, | ||
| twilioPhoneNumber: row.twilio_phone_number ?? undefined, |
There was a problem hiding this comment.
Do we care if these are returned unmasked? I don't know if these are sensitive or not
ajhollid
left a comment
There was a problem hiding this comment.
@egeoztass an executive decision has just been made to only support MongoDB and drop TimescaleDB for maintenance reasons.
I'm going to merge this now with the caveat that you can review and open a new PR with regards to the plaintext return of the account SID and Twilio phone number if needed.
Thanks for another great PR!
|
Follow-up PR for the sensitive field masking: #3559 Masks |

Summary
Changes
Backend (7 files)
twilio.tsprovider — sends via Twilio REST API with HTTP Basic AuthNotificationsService(bothsendandsendTestNotificationrouting)services.ts, exported from service indexFrontend (5 files)
"twilio"toNotificationChannelstypeuseNotificationFormhookTests (2 files)
NotificationsServicetest constructor withtwilioProviderField mapping
Uses existing Notification schema fields — no schema migration needed:
address→ Account SIDaccessToken→ Auth TokenhomeserverUrl→ From number (Twilio number)phone→ To number (recipient)Test plan
npm test -- --testPathPatterns="twilioProvider"— all 18 tests passnpm test -- --testPathPatterns="notificationsService"— all 24 tests passCloses #3095
🤖 Generated with Claude Code