using ScadaLink.AuditLog.Payload; namespace ScadaLink.AuditLog.Central; /// /// Audit Log (#23) M6 Bundle E read-side surface exposing the central-side /// audit-health counters: (every /// repository insert throw from / /// ), /// (every payload-filter redactor throw on the central path), and /// (per-site latched state from the /// ). /// /// /// /// Read-only contract. Implementations expose a point-in-time snapshot /// — increments and tracker updates happen through the dedicated counter / /// tracker interfaces, not through this surface. Consumers (M7+ central /// health pages) read these properties; they never mutate. /// /// /// Why a parallel surface from . /// aggregates per-site /// SiteHealthState reports the SITE emits. The central audit-write /// failure / redaction-failure counters originate ON central (no site report /// carries them), so they live on a dedicated snapshot rather than being /// retro-fitted into a per-site state. The two surfaces will be composed at /// the M7 dashboard layer. /// /// public interface IAuditCentralHealthSnapshot { /// /// Count of central-side audit-write failures since process start. /// Incremented by every / /// repository insert that throws. /// int CentralAuditWriteFailures { get; } /// /// Count of central-side payload-filter redactor over-redactions since /// process start. Incremented by every header / body / SQL-parameter /// redactor stage that throws (the filter falls back to the /// <redacted: redactor error> marker and never aborts the /// user-facing action). Sites have their own counter /// (-backed /// SiteHealthReport.AuditRedactionFailure) and the central /// composition root's binding routes ALL central redactor throws /// (CentralAuditWriter + AuditLogIngestActor paths) into this counter. /// int AuditRedactionFailure { get; } /// /// Per-site latched stalled state: true when the /// has observed two /// consecutive non-draining cycles for that site, false after the /// first draining cycle. Sites absent from the map are interpreted as /// healthy (Stalled=false default). Snapshot is a defensive /// copy — readers must not mutate. /// IReadOnlyDictionary SiteAuditTelemetryStalled { get; } }