feat(commons): add Audit{Channel,Kind,Status,ForwardState} enums for #23

This commit is contained in:
Joseph Doherty
2026-05-20 09:55:13 -04:00
parent 3f8b41182a
commit f80eea375c
5 changed files with 137 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
namespace ScadaLink.Commons.Types.Enums;
/// <summary>
/// Top-level Audit Log (#23) channel — the trust boundary the audited action crosses.
/// One of: outbound API call, outbound DB write, notification send/deliver, or inbound API request.
/// </summary>
public enum AuditChannel
{
ApiOutbound,
DbOutbound,
Notification,
ApiInbound
}

View File

@@ -0,0 +1,14 @@
namespace ScadaLink.Commons.Types.Enums;
/// <summary>
/// Site-local Audit Log (#23) forwarding state, tracked only in the site SQLite hot-path.
/// Central rows leave this null. <c>Pending</c> = not yet sent; <c>Forwarded</c> = telemetry sent
/// and acked; <c>Reconciled</c> = confirmed present centrally via the periodic pull fallback.
/// The site retention purge MUST NOT drop a row whose state is still <c>Pending</c>.
/// </summary>
public enum AuditForwardState
{
Pending,
Forwarded,
Reconciled
}

View File

@@ -0,0 +1,20 @@
namespace ScadaLink.Commons.Types.Enums;
/// <summary>
/// Specific Audit Log (#23) event kind within a channel — what action produced the row.
/// Cached variants emit multiple rows per operation (submit → forward → attempt → resolve).
/// See alog.md §4 for the full taxonomy.
/// </summary>
public enum AuditKind
{
ApiCall,
ApiCallCached,
DbWrite,
DbWriteCached,
NotifySend,
NotifyDeliver,
InboundRequest,
InboundAuthFailure,
CachedSubmit,
CachedResolve
}

View File

@@ -0,0 +1,18 @@
namespace ScadaLink.Commons.Types.Enums;
/// <summary>
/// Lifecycle status of an Audit Log (#23) event row.
/// Cached operations produce multiple rows tracking <c>Submitted → Forwarded → Attempted → Delivered/Parked/Discarded</c>.
/// <c>Skipped</c> is used when an action was short-circuited (e.g. dry-run) but should still be audited.
/// </summary>
public enum AuditStatus
{
Submitted,
Forwarded,
Attempted,
Delivered,
Failed,
Parked,
Discarded,
Skipped
}

View File

@@ -0,0 +1,72 @@
using ScadaLink.Commons.Types.Enums;
namespace ScadaLink.Commons.Tests.Types.Enums;
/// <summary>
/// Asserts the exact member sets of the Audit Log (#23) enums.
/// Lock-in tests; any addition/removal/rename is a deliberate design change
/// that must come with a corresponding update to alog.md §4.
/// </summary>
public class AuditEnumTests
{
[Fact]
public void AuditChannel_HasExactlyExpectedMembers()
{
var expected = new[] { "ApiOutbound", "DbOutbound", "Notification", "ApiInbound" };
var actual = Enum.GetValues(typeof(AuditChannel))
.Cast<AuditChannel>()
.Select(x => x.ToString())
.ToArray();
Assert.Equal(expected.Length, actual.Length);
Assert.Equal(expected, actual);
}
[Fact]
public void AuditKind_HasExactlyTenExpectedMembers()
{
var expected = new[]
{
"ApiCall", "ApiCallCached", "DbWrite", "DbWriteCached",
"NotifySend", "NotifyDeliver", "InboundRequest", "InboundAuthFailure",
"CachedSubmit", "CachedResolve",
};
var actual = Enum.GetValues(typeof(AuditKind))
.Cast<AuditKind>()
.Select(x => x.ToString())
.ToArray();
Assert.Equal(10, actual.Length);
Assert.Equal(expected, actual);
}
[Fact]
public void AuditStatus_HasExactlyEightExpectedMembers()
{
var expected = new[]
{
"Submitted", "Forwarded", "Attempted", "Delivered",
"Failed", "Parked", "Discarded", "Skipped",
};
var actual = Enum.GetValues(typeof(AuditStatus))
.Cast<AuditStatus>()
.Select(x => x.ToString())
.ToArray();
Assert.Equal(8, actual.Length);
Assert.Equal(expected, actual);
}
[Fact]
public void AuditForwardState_HasExactlyExpectedMembers()
{
var expected = new[] { "Pending", "Forwarded", "Reconciled" };
var actual = Enum.GetValues(typeof(AuditForwardState))
.Cast<AuditForwardState>()
.Select(x => x.ToString())
.ToArray();
Assert.Equal(expected.Length, actual.Length);
Assert.Equal(expected, actual);
}
}