- 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>
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#3095
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds Pushover as a new notification channel, allowing users to receive
push notifications on their devices via the Pushover API.
Backend: provider, type registration, validation, service wiring
Frontend: form UI with app token and user key fields, validation, i18n
Tests: full unit test suite (15 tests, 100% coverage on provider)
Closes#3445
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the loose NotificationDefaults intermediate type and 'as NotificationFormData'
cast with an exhaustive buildDefaults() helper that narrows each branch of the
discriminated union explicitly. TypeScript now infers the return type correctly from
the discriminated union without any casts, satisfying strong typing for all channels
(email, slack, discord, webhook, pager_duty, teams, matrix, telegram).
Per @ajhollid review: define defaults up-front with a NotificationDefaults type
and eliminate the trailing else branch entirely. The if/else-if blocks only
override when the type is matrix or telegram.
- useNotificationForm: replace nested ternary with if/else if/else block
- TelegramProvider: type error as unknown and access properties safely
via instanceof checks instead of casting to HTTPError