feat(centralui): ParentExecutionId column, filter and parent drill-in on the Audit Log page

This commit is contained in:
Joseph Doherty
2026-05-21 18:38:02 -04:00
parent 252bf0a970
commit 0b5723b777
17 changed files with 387 additions and 9 deletions

View File

@@ -139,6 +139,7 @@ public class AuditExportEndpointsTests
{
var correlationId = Guid.NewGuid().ToString();
var executionId = Guid.NewGuid().ToString();
var parentExecutionId = Guid.NewGuid().ToString();
var url =
"/api/centralui/audit/export?" +
"channel=ApiOutbound&" +
@@ -149,6 +150,7 @@ public class AuditExportEndpointsTests
"actor=apikey-1&" +
$"correlationId={correlationId}&" +
$"executionId={executionId}&" +
$"parentExecutionId={parentExecutionId}&" +
"from=2026-05-20T00:00:00Z&" +
"to=2026-05-20T23:59:59Z";
@@ -170,6 +172,7 @@ public class AuditExportEndpointsTests
f.Actor == "apikey-1" &&
f.CorrelationId == Guid.Parse(correlationId) &&
f.ExecutionId == Guid.Parse(executionId) &&
f.ParentExecutionId == Guid.Parse(parentExecutionId) &&
f.FromUtc == new DateTime(2026, 5, 20, 0, 0, 0, DateTimeKind.Utc) &&
f.ToUtc == new DateTime(2026, 5, 20, 23, 59, 59, DateTimeKind.Utc)),
Arg.Any<AuditLogPaging>(),
@@ -199,6 +202,7 @@ public class AuditExportEndpointsTests
f.Actor == null &&
f.CorrelationId == null &&
f.ExecutionId == null &&
f.ParentExecutionId == null &&
f.FromUtc == null &&
f.ToUtc == null),
Arg.Any<AuditLogPaging>(),
@@ -245,6 +249,25 @@ public class AuditExportEndpointsTests
}
}
[Fact]
public async Task ExportEndpoint_UnparseableParentExecutionId_SilentlyDropped()
{
// Lax-parse contract: an unparseable parentExecutionId is dropped (no 400)
// — mirrors the executionId / correlationId parse.
var (client, repo, host) = await BuildHostAsync();
using (host)
{
var response = await client.GetAsync("/api/centralui/audit/export?parentExecutionId=not-a-guid");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
_ = await response.Content.ReadAsStringAsync();
await repo.Received().QueryAsync(
Arg.Is<AuditLogQueryFilter>(f => f.ParentExecutionId == null),
Arg.Any<AuditLogPaging>(),
Arg.Any<CancellationToken>());
}
}
/// <summary>
/// Test-only authentication handler that signs every request in as an Admin.
/// Admin is in <c>AuditExportRoles</c>, so the endpoint's AuditExport policy