From c7ddfc71404a406971f54c0fdc366b3513d4d3aa Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 20 May 2026 08:20:44 -0400 Subject: [PATCH] docs(audit): central direct-write of notification dispatch events to AuditLog --- docs/requirements/Component-NotificationOutbox.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/requirements/Component-NotificationOutbox.md b/docs/requirements/Component-NotificationOutbox.md index 612ae47..020d6e4 100644 --- a/docs/requirements/Component-NotificationOutbox.md +++ b/docs/requirements/Component-NotificationOutbox.md @@ -106,6 +106,10 @@ The dispatcher loop runs on a fixed interval. On each tick the `NotificationOutb - **transient failure** → `Retrying`, increment `RetryCount`, set `NextAttemptAt`, record `LastError`; once retries are exhausted → `Parked`. - **permanent failure** → `Parked`, record `LastError`. +Each delivery attempt also writes a `Notification.Attempt` row to the central `AuditLog` via `ICentralAuditWriter`; a transition to a terminal status (`Delivered` / `Parked` / `Discarded`) writes a `Notification.Terminal` row. Audit writes are **direct** (no telemetry — the dispatcher runs at central), insert-if-not-exists on `EventId`. The site-emitted `Notification.Enqueued` row arrives separately via the standard audit telemetry channel from the site's SQLite write-buffer, so the full per-notification audit trail is `Enqueued` (site-originated) → `Attempt` × N (central direct-write) → `Terminal` (central direct-write). See [Component-AuditLog.md](Component-AuditLog.md), Central direct-write (central-originated events). + +The operational `Notifications` table remains the **source of truth** for the dispatcher and for Retry/Discard actions; the `AuditLog` rows are immutable shadows. Operator Retry/Discard still mutates only the `Notifications` row, and each transition emits the corresponding `Notification.Attempt` / `Notification.Terminal` audit row. + ## Delivery Adapters A delivery adapter implementing `INotificationDeliveryAdapter` is registered per `Type`. Each `Deliver(...)` call returns one of `success | transient failure | permanent failure`, mirroring the External System Gateway error-classification pattern. @@ -157,6 +161,7 @@ Delivery max-retry-count and retry interval are not part of `NotificationOutboxO - **Notification Service**: Provides notification-list and SMTP definitions, and the per-type delivery adapters the outbox invokes. - **Configuration Database**: Hosts the `Notifications` table; provides the entity POCO, repository, and EF migration for outbox persistence. - **Central–Site Communication**: Carries inbound notification submissions and acks between sites and central. +- **Audit Log (#23)**: The dispatcher direct-writes `Notification.Attempt` and `Notification.Terminal` rows to the central `AuditLog` via `ICentralAuditWriter` (insert-if-not-exists on `EventId`); the site-emitted `Notification.Enqueued` row arrives via the standard audit telemetry channel. See [Component-AuditLog.md](Component-AuditLog.md), Central direct-write (central-originated events). - **Health Monitoring**: Consumes the outbox KPIs as central-computed headline metrics. - **Central UI**: Hosts the Notification Outbox page.