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
@@ -107,6 +107,12 @@ public interface INotificationRepository
/// <returns>The SMS configuration, or null if not found.</returns>
Task<SmsConfiguration?> GetSmsConfigurationAsync(CancellationToken cancellationToken = default);
/// <summary>Gets an SMS configuration by ID.</summary>
/// <param name="id">The SMS configuration ID.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The SMS configuration, or null if not found.</returns>
Task<SmsConfiguration?> GetSmsConfigurationByIdAsync(int id, CancellationToken cancellationToken = default);
/// <summary>Gets all SMS configurations.</summary>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A read-only list of SMS configurations.</returns>
@@ -30,7 +30,12 @@ public sealed record ExportBundleCommand(
// Defaulted null so every existing positional caller keeps compiling; the
// handler normalizes null to "select nothing" (or everything under All=true).
IReadOnlyList<string>? SiteNames = null,
IReadOnlyList<string>? InstanceNames = null);
IReadOnlyList<string>? InstanceNames = null,
// Additive (S10b): SMS provider config selection, mirroring
// SmtpConfigurationNames. SmsConfiguration is keyed by AccountSid (no Name
// column), so tokens are AccountSid values. Defaulted null so every existing
// positional caller keeps compiling.
IReadOnlyList<string>? SmsConfigurationNames = null);
/// <summary>
/// Bundle body returned as base64-encoded ZIP. <see cref="ByteCount"/> is the
@@ -15,4 +15,8 @@ public sealed record BundleSummary(
// written by older exporters (which omit these JSON properties) deserialize fine.
int Sites = 0,
int DataConnections = 0,
int Instances = 0);
int Instances = 0,
// Additive (S10b): SMS provider config count, mirroring SmtpConfigs. Defaulted to
// 0 so manifests written by older exporters (which omit this JSON property)
// deserialize fine.
int SmsConfigs = 0);
@@ -17,11 +17,18 @@ public sealed record ExportSelection(
// Additive (M8 A1): site/instance-scoped export. Defaulted to empty so every
// existing positional caller keeps compiling; older callers select no sites/instances.
IReadOnlyList<int>? SiteIds = null,
IReadOnlyList<int>? InstanceIds = null)
IReadOnlyList<int>? InstanceIds = null,
// Additive (S10b): SMS provider config export, mirroring SmtpConfigurationIds.
// Defaulted null (trailing) so every existing positional caller keeps compiling;
// older callers select no SMS configs.
IReadOnlyList<int>? SmsConfigurationIds = null)
{
/// <summary>Sites selected for site/instance-scoped export (M8). Never null.</summary>
public IReadOnlyList<int> SiteIds { get; init; } = SiteIds ?? Array.Empty<int>();
/// <summary>Instances selected for site/instance-scoped export (M8). Never null.</summary>
public IReadOnlyList<int> InstanceIds { get; init; } = InstanceIds ?? Array.Empty<int>();
/// <summary>SMS provider configurations selected for export (S10b). Never null.</summary>
public IReadOnlyList<int> SmsConfigurationIds { get; init; } = SmsConfigurationIds ?? Array.Empty<int>();
}