docs(notification-outbox): add Notifications table, entity, and message contracts

This commit is contained in:
Joseph Doherty
2026-05-18 23:30:16 -04:00
parent d7a16084b5
commit bb5519f6f2
2 changed files with 26 additions and 6 deletions

View File

@@ -52,9 +52,10 @@ The configuration database stores all central system data, organized by domain a
- **Database Connection Definitions**: Named database connections (name, connection details, retry settings).
### Notifications
- **Notification Lists**: List definitions (name).
- **Notification Lists**: List definitions (name, `Type` discriminator — `Email` / `Teams` / … — selecting the list's notification type and type-specific targets).
- **Notification Recipients**: Recipients per list (name, email address).
- **SMTP Configuration**: Email server settings.
- **Notifications**: The durable central notification queue owned by the Notification Outbox — one row per notification, the single source of audit truth. The schema is **type-agnostic** so it records any notification type the system supports (email today, Microsoft Teams and others later): a `Type` discriminator selects the type, and a `TypeData` JSON column (`nvarchar(max)`) carries any future per-type fields without a schema change. Columns: `NotificationId` (GUID, primary key — generated at the site, used as the idempotency key), `Type`, `ListName`, `Subject`, `Body`, `TypeData`, `Status`, `RetryCount`, `LastError`, `ResolvedTargets`, `SourceSiteId`, `SourceInstanceId`, `SourceScript`, `SiteEnqueuedAt`, `CreatedAt`, `LastAttemptAt`, `NextAttemptAt`, `DeliveredAt`. `Status` is a `NotificationStatus` enum stored with values `Pending`, `Retrying`, `Delivered`, `Parked`, `Discarded` (the site-local `Forwarding` state is never persisted centrally). Indexed on `Status` and `NextAttemptAt` for efficient dispatcher polling of due rows, and on `SourceSiteId` and `CreatedAt` for KPI computation and the Central UI query page. Terminal rows (`Delivered`, `Parked`, `Discarded`) are removed by a daily purge job after a configurable retention window (default 365 days); non-terminal rows are never purged. See Component-NotificationOutbox.md for the full lifecycle.
### Inbound API
- **API Keys**: Key definitions (name/label, key value, enabled flag).
@@ -94,7 +95,8 @@ Repository interfaces are defined in **Commons** alongside the POCO entity class
| `ISecurityRepository` | Security & Auth | LDAP group mappings, site scoping rules |
| `IInboundApiRepository` | Inbound API | API keys, API method definitions |
| `IExternalSystemRepository` | External System Gateway | External system definitions, method definitions, database connection definitions |
| `INotificationRepository` | Notification Service | Notification lists, recipients, SMTP configuration |
| `INotificationRepository` | Notification Service | Notification lists (including the `Type` field), recipients, SMTP configuration |
| `INotificationOutboxRepository` | Notification Outbox | The `Notifications` table — insert-if-not-exists ingest, due-row polling, status transitions, KPI aggregate queries, and daily purge of terminal rows |
| `IHealthMonitoringRepository` | Health Monitoring | (Minimal — health data is in-memory; repository needed only if connectivity history is persisted in the future) |
| `ICentralUiRepository` | Central UI | Read-oriented queries spanning multiple domain areas for display purposes |
@@ -226,6 +228,7 @@ Results are returned in reverse chronological order (most recent first) with pag
- Schema changes are managed via EF Core Migrations (`dotnet ef migrations add`, `dotnet ef migrations script`).
- Each migration is a versioned, incremental schema change.
- New tables are introduced as their own migration — for example, the `Notifications` table for the Notification Outbox ships as a dedicated EF Core migration that creates the table, its `Type`/`Status` value conversions, and its dispatcher and KPI indexes.
### Development Environment
- Migrations are **auto-applied** at application startup using `dbContext.Database.MigrateAsync()`.
@@ -265,6 +268,14 @@ The Configuration Database supports seeding initial data required for the system
---
## Scheduled Maintenance
### Notifications Table Purge
The `Notifications` table grows one row per notification and is never trimmed by normal operation — `Discarded` rows are deliberately retained for audit. To bound table growth while preserving a strong audit trail, a **daily purge job** deletes terminal rows (`Delivered`, `Parked`, `Discarded`) whose `CreatedAt` is older than a configurable retention window (default 365 days). Non-terminal rows (`Pending`, `Retrying`) are never purged. The purge is a bulk `DELETE` against `INotificationOutboxRepository`; it is owned and scheduled by the Notification Outbox component (see Component-NotificationOutbox.md), which supplies the retention window from `NotificationOutboxOptions`. The Configuration Database component provides only the repository operation and the table.
---
## Connection Management
- Connection strings are provided via the Host's `DatabaseConfiguration` options (bound from `appsettings.json`).
@@ -289,6 +300,7 @@ The Configuration Database supports seeding initial data required for the system
- **Inbound API**: Uses `IInboundApiRepository` for API keys and method definitions.
- **External System Gateway**: Uses `IExternalSystemRepository` for external system and database connection definitions.
- **Notification Service**: Uses `INotificationRepository` for notification lists and SMTP configuration.
- **Notification Outbox**: Uses `INotificationOutboxRepository` for all access to the `Notifications` table — ingest, dispatch polling, status updates, KPI queries, and the daily purge of terminal rows.
- **Central UI**: Uses `ICentralUiRepository` for read-oriented queries across domain areas, including audit log queries for the audit log viewer.
- **All central components that modify state**: Call `IAuditService.LogAsync()` after successful operations to record audit entries within the same transaction.
- **Host**: Provides database connection configuration. Registers DbContext, repository implementations, and `IAuditService` implementation in the DI container. Triggers auto-migration in development or validates schema version in production.