feat(sms): make FromNumber optional — support Twilio Messaging-Service-only configs (UI-Med-2)
Code-review finding UI-Med-2: the design doc + delivery adapter treat FromNumber and MessagingServiceSid as either-or, but the entity ctor, EF schema, UI and CLI all hard- required FromNumber — so a Messaging-Service-only Twilio config (a normal production setup) could not be created. Bring the implementation into line with the spec: - Commons: SmsConfiguration.FromNumber -> string? (ctor fromNumber optional); UpdateSmsConfigCommand.FromNumber -> string?. - ConfigurationDatabase: FromNumber.IsRequired(false) + migration SmsFromNumberOptional (ALTER COLUMN nullable, idempotent; Down backfills '' — harmless, MsgSid keeps it deliverable) + regenerated model snapshot. - Transport: SmsConfigDto.FromNumber -> string? (round-trips a Messaging-Service-only config). - CentralUI: form validation requires AccountSid + at-least-one-of(FromNumber, MsgSid); nullable create/edit paths; From-number help text. - CLI: --from-number no longer Required; BuildUpdateSmsConfigCommand validates the either-or. - Adapter: From branch null-forgiving (guarded by the existing incomplete-config check). Tests: ManagementActor MsgSid-only persists null FromNumber; CLI MsgSid-only builds + neither-throws + contract (--from-number not Required); CentralUI MsgSid-only save.
This commit is contained in:
@@ -238,8 +238,11 @@ public static class NotificationCommands
|
||||
new("--id") { Description = "SMS config ID", Required = true };
|
||||
private static readonly Option<string> SmsAccountSidOption =
|
||||
new("--account-sid") { Description = "Twilio Account SID", Required = true };
|
||||
private static readonly Option<string> SmsFromNumberOption =
|
||||
new("--from-number") { Description = "Sender phone number (E.164)", Required = true };
|
||||
private static readonly Option<string?> SmsFromNumberOption =
|
||||
new("--from-number")
|
||||
{
|
||||
Description = "Sender phone number (E.164). Provide this and/or --messaging-service-sid.",
|
||||
};
|
||||
private static readonly Option<string?> SmsMessagingServiceSidOption =
|
||||
new("--messaging-service-sid")
|
||||
{
|
||||
@@ -269,10 +272,18 @@ public static class NotificationCommands
|
||||
{
|
||||
var id = result.GetValue(SmsIdOption);
|
||||
var accountSid = result.GetValue(SmsAccountSidOption)!;
|
||||
var fromNumber = result.GetValue(SmsFromNumberOption)!;
|
||||
var fromNumber = result.GetValue(SmsFromNumberOption);
|
||||
var messagingServiceSid = result.GetValue(SmsMessagingServiceSidOption);
|
||||
var apiBaseUrl = result.GetValue(SmsApiBaseUrlOption);
|
||||
var authToken = result.GetValue(SmsAuthTokenOption);
|
||||
// Whole-replace update: the sender identity must be re-supplied. A Twilio config
|
||||
// needs a From number and/or a Messaging Service SID, so reject the case where the
|
||||
// update would leave neither (mirrors the UI + delivery-adapter validation).
|
||||
if (string.IsNullOrWhiteSpace(fromNumber) && string.IsNullOrWhiteSpace(messagingServiceSid))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Provide --from-number and/or --messaging-service-sid (at least one sender identity is required).");
|
||||
}
|
||||
return new UpdateSmsConfigCommand(id, accountSid, fromNumber, messagingServiceSid, apiBaseUrl, authToken);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user