feat(sms): complete SmsConfig bundle export/import wiring + GetSmsConfigurationByIdAsync (S10b)

This commit is contained in:
Joseph Doherty
2026-06-19 11:10:39 -04:00
parent 78fadb82d2
commit c3501ecd72
19 changed files with 586 additions and 6 deletions
@@ -252,6 +252,40 @@ public sealed class ArtifactDiff
return BuildItem("SmtpConfiguration", incoming.Host, changes);
}
/// <summary>
/// Compares an incoming SMS provider configuration against the existing one in
/// the database (S10b). Mirrors <see cref="CompareSmtpConfiguration"/>: keyed by
/// the natural key <c>AccountSid</c>, with the auth token diffed presence-only
/// (it lives in <see cref="SecretsBlock"/>, never compared by value).
/// </summary>
/// <param name="incoming">The incoming SMS configuration from the bundle.</param>
/// <param name="existing">The existing SMS configuration in the database, or null if new.</param>
/// <returns>An import preview item describing the conflict type and differences.</returns>
public ImportPreviewItem CompareSmsConfiguration(SmsConfigDto incoming, SmsConfiguration? existing)
{
ArgumentNullException.ThrowIfNull(incoming);
if (existing is null) return New("SmsConfiguration", incoming.AccountSid);
var changes = new List<FieldChange>();
AddIfDifferent(changes, "FromNumber", existing.FromNumber, incoming.FromNumber);
AddIfDifferent(changes, "MessagingServiceSid", existing.MessagingServiceSid, incoming.MessagingServiceSid);
AddIfDifferent(changes, "ApiBaseUrl", existing.ApiBaseUrl, incoming.ApiBaseUrl);
AddIfDifferent(changes, "ConnectionTimeoutSeconds", existing.ConnectionTimeoutSeconds, incoming.ConnectionTimeoutSeconds);
AddIfDifferent(changes, "MaxRetries", existing.MaxRetries, incoming.MaxRetries);
AddIfDifferent(changes, "RetryDelay", existing.RetryDelay.ToString(), incoming.RetryDelay.ToString());
var existingHasSecret = !string.IsNullOrEmpty(existing.AuthToken);
var incomingHasSecret = incoming.Secrets is not null && incoming.Secrets.Values.ContainsKey("AuthToken");
if (existingHasSecret != incomingHasSecret)
{
changes.Add(new FieldChange("Secrets.AuthToken",
existingHasSecret ? "<present>" : null,
incomingHasSecret ? "<present>" : null));
}
return BuildItem("SmsConfiguration", incoming.AccountSid, changes);
}
// CompareApiKey was removed in re-arch C4: inbound API keys are not transported
// between environments, so the import preview never diffs keys.