fix(auditlog): explicit permanent rejections on the ingest ack (IngestAck.rejected_event_ids, field 2) with a dedicated counter; reconciler ignores transient faults for abandonment; persist the served high-water mark; prune only on a non-empty enumeration (review 2026-10-21 06/PERF-1, 06/IMPL-1 adversarial follow-up)

This commit is contained in:
Joseph Doherty
2026-10-22 08:40:42 -04:00
parent 38167bca88
commit b0a08bb63b
23 changed files with 790 additions and 168 deletions
@@ -259,6 +259,23 @@ public class CentralControlDtoMapperTests
Assert.Equal(ids, roundTripped);
}
/// <summary>Verifies the additive rejected-id list round-trips and reads empty when absent.</summary>
[Fact]
public void IngestAck_RejectedIds_RoundTrip_AndAbsentFieldReadsEmpty()
{
// Review 2026-10-21 06/IMPL-1: additive field 2. An older central never sets it, so the
// site must read an EMPTY list (never a refusal) from a pre-field ack.
var accepted = new[] { Guid.NewGuid() };
var rejected = new[] { Guid.NewGuid(), Guid.NewGuid() };
var wire = Wire(CentralControlDtoMapper.ToIngestAck(accepted, rejected));
Assert.Equal(accepted, CentralControlDtoMapper.FromIngestAck(wire));
Assert.Equal(rejected, CentralControlDtoMapper.RejectedFromIngestAck(wire));
Assert.Empty(CentralControlDtoMapper.RejectedFromIngestAck(
Wire(CentralControlDtoMapper.ToIngestAck(accepted))));
}
/// <summary>Verifies that an ingest acknowledgement with nothing accepted stays empty.</summary>
[Fact]
public void IngestAck_RoundTrip_NothingAccepted_StaysEmpty()