feat(auditlog): ExecutionId on site SQLite schema + gRPC AuditEventDto

This commit is contained in:
Joseph Doherty
2026-05-21 14:53:08 -04:00
parent 990731d12f
commit 6b16a48886
7 changed files with 139 additions and 48 deletions

View File

@@ -41,9 +41,9 @@ public class SqliteAuditWriterSchemaTests
}
[Fact]
public void Opens_Creates_AuditLog_Table_With_20Columns_And_PK_On_EventId()
public void Opens_Creates_AuditLog_Table_With_21Columns_And_PK_On_EventId()
{
var (writer, dataSource) = CreateWriter(nameof(Opens_Creates_AuditLog_Table_With_20Columns_And_PK_On_EventId));
var (writer, dataSource) = CreateWriter(nameof(Opens_Creates_AuditLog_Table_With_21Columns_And_PK_On_EventId));
using (writer)
{
using var connection = OpenVerifierConnection(dataSource);
@@ -57,7 +57,7 @@ public class SqliteAuditWriterSchemaTests
columns.Add((reader.GetString(1), reader.GetInt32(5)));
}
Assert.Equal(20, columns.Count);
Assert.Equal(21, columns.Count);
var expected = new[]
{
@@ -65,7 +65,7 @@ public class SqliteAuditWriterSchemaTests
"SourceSiteId", "SourceInstanceId", "SourceScript", "Actor", "Target",
"Status", "HttpStatus", "DurationMs", "ErrorMessage", "ErrorDetail",
"RequestSummary", "ResponseSummary", "PayloadTruncated", "Extra",
"ForwardState",
"ForwardState", "ExecutionId",
};
Assert.Equal(expected.OrderBy(n => n), columns.Select(c => c.Name).OrderBy(n => n));

View File

@@ -353,4 +353,37 @@ public class SqliteAuditWriterWriteTests
await writer.MarkReconciledAsync(new[] { Guid.NewGuid(), Guid.NewGuid() });
// Completes without throwing.
}
// ----- ExecutionId column (universal per-run correlation value) ----- //
[Fact]
public async Task WriteAsync_NonNullExecutionId_RoundTripsThroughMapRow()
{
var (writer, _) = CreateWriter(nameof(WriteAsync_NonNullExecutionId_RoundTripsThroughMapRow));
await using var _w = writer;
var executionId = Guid.NewGuid();
var evt = NewEvent() with { ExecutionId = executionId };
await writer.WriteAsync(evt);
var rows = await writer.ReadPendingAsync(limit: 10);
var row = Assert.Single(rows);
Assert.Equal(executionId, row.ExecutionId);
}
[Fact]
public async Task WriteAsync_NullExecutionId_RoundTripsAsNull()
{
var (writer, _) = CreateWriter(nameof(WriteAsync_NullExecutionId_RoundTripsAsNull));
await using var _w = writer;
var evt = NewEvent() with { ExecutionId = null };
await writer.WriteAsync(evt);
var rows = await writer.ReadPendingAsync(limit: 10);
var row = Assert.Single(rows);
Assert.Null(row.ExecutionId);
}
}

View File

@@ -19,6 +19,7 @@ public class AuditEventDtoMapperTests
var occurredAt = new DateTime(2026, 5, 20, 10, 15, 30, 123, DateTimeKind.Utc);
var ingestedAt = new DateTime(2026, 5, 20, 10, 15, 31, 0, DateTimeKind.Utc);
var correlationId = Guid.NewGuid();
var executionId = Guid.NewGuid();
var eventId = Guid.NewGuid();
var original = new AuditEvent
@@ -29,6 +30,7 @@ public class AuditEventDtoMapperTests
Channel = AuditChannel.ApiOutbound,
Kind = AuditKind.ApiCallCached,
CorrelationId = correlationId,
ExecutionId = executionId,
SourceSiteId = "site-1",
SourceInstanceId = "Pump01",
SourceScript = "OnDemand",
@@ -54,6 +56,7 @@ public class AuditEventDtoMapperTests
Assert.Equal(original.Channel, roundTripped.Channel);
Assert.Equal(original.Kind, roundTripped.Kind);
Assert.Equal(original.CorrelationId, roundTripped.CorrelationId);
Assert.Equal(original.ExecutionId, roundTripped.ExecutionId);
Assert.Equal(original.SourceSiteId, roundTripped.SourceSiteId);
Assert.Equal(original.SourceInstanceId, roundTripped.SourceInstanceId);
Assert.Equal(original.SourceScript, roundTripped.SourceScript);
@@ -90,6 +93,7 @@ public class AuditEventDtoMapperTests
var dto = AuditEventDtoMapper.ToDto(evt);
Assert.Equal(string.Empty, dto.CorrelationId);
Assert.Equal(string.Empty, dto.ExecutionId);
Assert.Equal(string.Empty, dto.SourceSiteId);
Assert.Equal(string.Empty, dto.SourceInstanceId);
Assert.Equal(string.Empty, dto.SourceScript);
@@ -113,6 +117,7 @@ public class AuditEventDtoMapperTests
Kind = nameof(AuditKind.ApiCall),
Status = nameof(AuditStatus.Submitted),
CorrelationId = string.Empty,
ExecutionId = string.Empty,
SourceSiteId = string.Empty,
SourceInstanceId = string.Empty,
SourceScript = string.Empty,
@@ -128,6 +133,7 @@ public class AuditEventDtoMapperTests
var evt = AuditEventDtoMapper.FromDto(dto);
Assert.Null(evt.CorrelationId);
Assert.Null(evt.ExecutionId);
Assert.Null(evt.SourceSiteId);
Assert.Null(evt.SourceInstanceId);
Assert.Null(evt.SourceScript);