docs: reconcile design docs with shipped code (enums, Sms, per-channel retention, SiteCalls schema, conventions)

PLAN-04 Task 24. Component-Commons: AuditChannel gains SecuredWrite (5), AuditKind full
15-value list (+SecuredWrite*/ReconciliationAbandoned), NotificationType Email/Sms (Teams
evaluated+dropped), AuditLogRow persistence-only-projection deviation note. ConfigDB:
Type discriminator Email/Sms, data-layer conventions (UTC DateTime + Utc converter, MSSQL-
only repos/fixtures, AuditLog clustered-key + P3/P4/P6 tracked follow-ups). SiteCallAudit:
schema table rewritten to shipped columns (Channel/Target/AuditStatus-Status/SourceNode/
HttpStatus/IngestedAtUtc; no Kind/TargetSummary/provenance) + stored-vs-tracking-view note.
AuditLog: per-channel retention config lists all 5 channels incl SecuredWrite. Also fixed
two stale 'Teams planned' refs surfaced by the verification grep (HighLevelReqs, CentralUI).
This commit is contained in:
Joseph Doherty
2026-07-09 10:03:13 -04:00
parent 3a21e77c03
commit 7f1b59ff84
6 changed files with 56 additions and 25 deletions
+4 -3
View File
@@ -43,11 +43,12 @@ Commons must define shared primitive and utility types used across multiple comp
- **`TrackedOperationId`**: A GUID identifying a tracked store-and-forward operation (`ExternalSystem.CachedCall`, `Database.CachedWrite`, `Notify.Send`). Generated caller-side at the site at call time, returned to the script as a tracking handle, and reused as the idempotency key for telemetry sent to central. The notification domain's existing `NotificationId` is the notification-specific name for this same concept.
- **`TrackedOperationKind` enum**: ExternalCall, DatabaseWrite. Discriminates the two cached-call kinds carried by a tracked operation (notifications are tracked separately via the `NotificationType` enum).
- **`TrackedOperationStatus` enum**: Pending, Retrying, Delivered, Parked, Failed, Discarded. The unified lifecycle state shared by all tracked store-and-forward operations. This is the operation's externally-observable lifecycle status in the site-local tracking table (the status record); it is related to but distinct from the S&F buffer's own `StoreAndForwardMessageStatus`, which tracks a buffered message's retry state within the buffer (the retry mechanism). `Failed` (permanent failure) has no notification analogue — notifications use only the other five states (the `NotificationStatus` enum omits `Failed`).
- **`AuditChannel` enum**: ApiOutbound, DbOutbound, Notification, ApiInbound. Discriminates the script-trust-boundary channel that produced an `AuditEvent`. Owned by the Audit Log component.
- **`AuditKind` enum**: ApiCall, ApiCallCached, DbWrite, DbWriteCached, NotifySend, NotifyDeliver, InboundRequest, InboundAuthFailure, CachedSubmit, CachedResolve. Channel-specific event kind — the valid `Kind` values for each `AuditChannel` are listed in the Audit Log component design (`Component-AuditLog.md`).
- **`AuditChannel` enum**: ApiOutbound, DbOutbound, Notification, ApiInbound, SecuredWrite. Discriminates the script-trust-boundary channel that produced an `AuditEvent` (`SecuredWrite` extends the boundary to the two-person MxGateway secured-write flow). Owned by the Audit Log component.
- **`AuditKind` enum**: ApiCall, ApiCallCached, DbWrite, DbWriteCached, NotifySend, NotifyDeliver, InboundRequest, InboundAuthFailure, CachedSubmit, CachedResolve, SecuredWriteSubmit, SecuredWriteApprove, SecuredWriteReject, SecuredWriteExecute, ReconciliationAbandoned. Channel-specific event kind — the valid `Kind` values for each `AuditChannel` are listed in the Audit Log component design (`Component-AuditLog.md`). (`SecuredWrite*` are the four secured-write lifecycle events; `ReconciliationAbandoned` is the durable record emitted when a reconciliation pull permanently fails to insert a lost row — arch-review 04.)
- **`AuditStatus` enum**: Submitted, Forwarded, Attempted, Delivered, Failed, Parked, Discarded, Skipped. Lifecycle status of an audit event row; cached operations transit Submitted → Forwarded → Attempted → Delivered/Parked/Discarded. `Skipped` covers short-circuited (e.g. dry-run) actions that should still be audited.
- **`AuditForwardState` enum**: Pending, Forwarded, Reconciled. Site-local SQLite flag governing the telemetry/reconciliation loop (set on a row but never sent to central).
- **`AuditEvent`** (`ZB.MOM.WW.Audit.AuditEvent` — external NuGet package, not a Commons entity class): The canonical, transport-agnostic audit record from the `ZB.MOM.WW.Audit` package that Commons references. Carries the 10 canonical fields: `EventId` (GUID, idempotency key), `OccurredAtUtc`, `Actor`, `Action` (format `"{channel}.{kind}"`), `Outcome` (`AuditOutcome`: `Success`/`Failure`/`Denied`), `Category` (channel name for ScadaBridge), `Target`, `SourceNode`, `CorrelationId`, and `DetailsJson` (JSON extension bag). All ScadaBridge-specific fields — `Channel`, `Kind`, `Status`, `ExecutionId`, `ParentExecutionId`, `SourceSiteId`, `SourceInstanceId`, `SourceScript`, `HttpStatus`, `DurationMs`, `ErrorMessage`, `ErrorDetail`, `RequestSummary`, `ResponseSummary`, `PayloadTruncated`, `Extra`, `IngestedAtUtc` — are carried in `DetailsJson` and are not top-level properties of `AuditEvent`. The `AuditChannel`, `AuditKind`, `AuditStatus`, and `AuditForwardState` enums defined in Commons (under `Types/Enums/`) describe the vocabulary encoded in `DetailsJson` and in the `AuditLogRow` computed columns. The site-local `ForwardState` (`AuditForwardState`) flag used by the telemetry/reconciliation loop is stored separately in the site SQLite `AuditLog` table. See `Component-AuditLog.md` for the persistence schema and ingest semantics.
- **`AuditLogRow` deviation (documented, intentional):** the central `dbo.AuditLog` EF entity `AuditLogRow` is a **persistence-only projection** of the external `ZB.MOM.WW.Audit.AuditEvent` contract — it lives in the Configuration Database component, **not** as a Commons POCO. This is a deliberate exception to the "entities are persistence-ignorant POCOs in Commons" rule: the canonical record is owned by the external `ZB.MOM.WW.Audit` package, and `AuditLogRow` exists only to give EF a table shape (canonical columns + `DetailsJson`-derived computed columns) to read/write. Do not lift it into Commons.
- **`SiteCall`**: A record carrying the central `SiteCalls` operational-mirror row — `TrackedOperationId`, `Channel` (the trust-boundary channel, `ApiOutbound` or `DbOutbound`), `Target` (human-readable call target), `SourceSite` (site id), `SourceNode` (emitting node, nullable), `Status` (string form of `AuditStatus`; monotonic), `RetryCount`, `LastError`, `HttpStatus`, `CreatedAtUtc`, `UpdatedAtUtc`, `TerminalAtUtc`, `IngestedAtUtc` — fed by site `CachedCallTelemetry` and the periodic reconciliation pull.
Types defined here must be immutable and thread-safe.
@@ -86,7 +87,7 @@ Entity classes are organized by domain area:
- **Deployment**: `DeploymentRecord`, `SystemArtifactDeploymentRecord`, `DeployedConfigSnapshot`.
- **Audit**: `AuditLogEntry` (configuration-change audit, owned by Configuration Database), `SiteCall` (`SiteCalls` operational-mirror row). (`AuditEvent` is `ZB.MOM.WW.Audit.AuditEvent` from the external NuGet package — not a Commons entity class file; see REQ-COM-1.)
The **`Notification`** entity is the persistence-ignorant POCO for a row of the central `Notifications` table — the durable notification queue owned by the Notification Outbox. It is a plain class with properties for `NotificationId` (GUID, the idempotency key), `Type` (`NotificationType` enum discriminator), `ListName`, `Subject`, `Body`, `TypeData` (a JSON string — the type-agnostic extensibility hook), `Status` (`NotificationStatus` enum), `RetryCount`, `LastError`, `ResolvedTargets`, the provenance fields `SourceSiteId` / `SourceInstanceId` / `SourceScript`, and the UTC timestamps `SiteEnqueuedAt`, `CreatedAt`, `LastAttemptAt`, `NextAttemptAt`, `DeliveredAt`. As with every entity class it has no EF dependency; the Configuration Database component supplies the Fluent API mapping, value conversions, and indexes. The `Type` and `Status` enums (`NotificationType`: `Email` — currently the only value; `Teams` and other channels are planned but not yet present in the enum; `NotificationStatus`: `Pending`, `Retrying`, `Delivered`, `Parked`, `Discarded`) are defined under `Types/Enums/` per REQ-COM-1.
The **`Notification`** entity is the persistence-ignorant POCO for a row of the central `Notifications` table — the durable notification queue owned by the Notification Outbox. It is a plain class with properties for `NotificationId` (GUID, the idempotency key), `Type` (`NotificationType` enum discriminator), `ListName`, `Subject`, `Body`, `TypeData` (a JSON string — the type-agnostic extensibility hook), `Status` (`NotificationStatus` enum), `RetryCount`, `LastError`, `ResolvedTargets`, the provenance fields `SourceSiteId` / `SourceInstanceId` / `SourceScript`, and the UTC timestamps `SiteEnqueuedAt`, `CreatedAt`, `LastAttemptAt`, `NextAttemptAt`, `DeliveredAt`. As with every entity class it has no EF dependency; the Configuration Database component supplies the Fluent API mapping, value conversions, and indexes. The `Type` and `Status` enums (`NotificationType`: `Email`, `Sms` — SMS via Twilio shipped 2026-06-19; a Microsoft Teams adapter was evaluated and dropped, because an outbound-only Graph client cannot send 1:1 chat bodies without a Bot Framework inbound endpoint; `NotificationStatus`: `Pending`, `Retrying`, `Delivered`, `Parked`, `Discarded`) are defined under `Types/Enums/` per REQ-COM-1.
### REQ-COM-4: Per-Component Repository Interfaces