sqlinsight-pro/src/SQLInsight.Notifications/Notification.cs
Claude eac799a1f1
Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
Fase 2: notifications by e-mail, Teams and webhook
- Repository reports which findings opened and resolved per evaluation
- Agent notifies on new and resolved findings and on instance
  unreachable/recovered transitions, with links to the web UI
- Channels: e-mail (MailKit, HTML-encoded), Microsoft Teams Workflows
  webhook (Adaptive Card), generic JSON webhook signed with HMAC-SHA256
- Per-channel minimum severity (outages always sent), one message per
  batch, hourly cap per channel; a failing channel never stops monitoring
- Tested with a real SMTP server (Mailpit) and the real agent pipeline

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 08:08:06 +00:00

43 lines
1.3 KiB
C#

using SQLInsight.Core.Findings;
namespace SQLInsight.Notifications;
public enum NotificationKind
{
FindingOpened,
FindingResolved,
InstanceUnreachable,
InstanceRecovered,
}
/// <summary>
/// Something worth telling a person about. Carries no query text or evidence values, only what is needed to decide
/// whether to open the web UI.
/// </summary>
public sealed record Notification
{
public required NotificationKind Kind { get; init; }
public required string Instance { get; init; }
public required string Title { get; init; }
public Severity Severity { get; init; }
public string? RuleId { get; init; }
public string? Subject { get; init; }
/// <summary>The first sentence of the explanation.</summary>
public string? Summary { get; init; }
/// <summary>Link to the finding or instance in the web UI, when a base URL is configured.</summary>
public Uri? Url { get; init; }
public required DateTimeOffset At { get; init; }
}
public interface INotificationChannel
{
string Name { get; }
/// <summary>Lowest severity this channel wants for new findings. Instance outages are always sent.</summary>
Severity MinSeverity { get; }
Task SendAsync(IReadOnlyList<Notification> notifications, CancellationToken cancellationToken);
}