f57f61deac
ConfigAuditLog gains two nullable columns (EventId, CorrelationId) + a filtered unique index UX_ConfigAuditLog_EventId. EF migration 20260526105027_AddConfigAuditLogEventIdColumns is additive (nullable + filtered index = legacy rows backfill cleanly). AuditWriterActor now writes EventId + CorrelationId into the dedicated columns instead of synthesising a JSON wrapper into DetailsJson. Cross-restart dedup is now real: a retry of an already-flushed batch hits the unique index and SaveChanges throws; the existing catch drops the duplicate without losing the rest of the batch. WrapDetails helper deleted — F4 (its JSON hardening) becomes moot. AuditWriterActorTests.Details_wrapper_embeds_eventId_and_correlationId renamed + rewritten to assert against the columns. All 29 ControlPlane tests pass, all 95 v2 tests green.
38 lines
1.6 KiB
C#
38 lines
1.6 KiB
C#
namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
|
|
|
/// <summary>
|
|
/// Append-only audit log for every config write + authorization-check event. Grants revoked for
|
|
/// UPDATE / DELETE on all principals (enforced by the authorization migration in B.3).
|
|
/// </summary>
|
|
public sealed class ConfigAuditLog
|
|
{
|
|
public long AuditId { get; set; }
|
|
|
|
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
|
|
|
|
public required string Principal { get; set; }
|
|
|
|
/// <summary>DraftCreated | DraftEdited | Published | RolledBack | NodeApplied | CredentialAdded | CredentialDisabled | ClusterCreated | NodeAdded | ExternalIdReleased | CrossClusterNamespaceAttempt | OpcUaAccessDenied | …</summary>
|
|
public required string EventType { get; set; }
|
|
|
|
public string? ClusterId { get; set; }
|
|
|
|
public string? NodeId { get; set; }
|
|
|
|
public long? GenerationId { get; set; }
|
|
|
|
public string? DetailsJson { get; set; }
|
|
|
|
/// <summary>
|
|
/// Stable per-event identifier from <c>AuditEvent.EventId</c>. Filtered unique index on
|
|
/// this column gives cross-restart idempotency for the batched AuditWriterActor: a flush
|
|
/// that retries after a process crash can re-send the same EventId without producing a
|
|
/// duplicate row. Nullable so pre-v2 rows backfill cleanly.
|
|
/// </summary>
|
|
public Guid? EventId { get; set; }
|
|
|
|
/// <summary>Correlation ID from <c>AuditEvent.CorrelationId</c> so an audit row joins to its
|
|
/// originating request/workflow. Nullable for the same backfill reason as <see cref="EventId"/>.</summary>
|
|
public Guid? CorrelationId { get; set; }
|
|
}
|