docs(audit): fix canonical record field count (10 not 8) + drop BCL-only overstatement (review fixes)
This commit is contained in:
@@ -56,8 +56,8 @@ adoption plan:
|
|||||||
enum (`Success | Failure | Denied`); the `IAuditWriter` seam (best-effort, never throws to
|
enum (`Success | Failure | Denied`); the `IAuditWriter` seam (best-effort, never throws to
|
||||||
caller); the `IAuditRedactor` seam (pure, never throws, over-redacts on failure); shipped
|
caller); the `IAuditRedactor` seam (pure, never throws, over-redacts on failure); shipped
|
||||||
helpers (`NoOpAuditWriter`, `CompositeAuditWriter`, `RedactingAuditWriter`,
|
helpers (`NoOpAuditWriter`, `CompositeAuditWriter`, `RedactingAuditWriter`,
|
||||||
`NullAuditRedactor`, `TruncatingAuditRedactor`). Library is BCL-only — no Akka / EF / SQLite
|
`NullAuditRedactor`, `TruncatingAuditRedactor`). Library has no Akka / EF / SQLite / Serilog
|
||||||
/ Serilog dependency.
|
dependency; its only non-BCL dependency is `Microsoft.Extensions.DependencyInjection.Abstractions`.
|
||||||
|
|
||||||
**Left per-project (each project keeps these behind the seam):** transport and storage (Akka
|
**Left per-project (each project keeps these behind the seam):** transport and storage (Akka
|
||||||
singleton + EF/SQL Server; SQLite; site-SQLite + central MS SQL + forwarding/reconcile
|
singleton + EF/SQL Server; SQLite; site-SQLite + central MS SQL + forwarding/reconcile
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ replace* — mostly naming alignment; the enormous transport/storage/CLI/UI stay
|
|||||||
|
|
||||||
`src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Audit/AuditEvent.cs:22` — a `sealed record`,
|
`src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Audit/AuditEvent.cs:22` — a `sealed record`,
|
||||||
append-only, "single source of truth for AuditLog (#23) rows." Far richer than the canonical
|
append-only, "single source of truth for AuditLog (#23) rows." Far richer than the canonical
|
||||||
8-field event. Notable fields:
|
10-field event. Notable fields:
|
||||||
|
|
||||||
- Identity / correlation: `EventId` (idempotency key, `:25`), `CorrelationId` (per-op
|
- Identity / correlation: `EventId` (idempotency key, `:25`), `CorrelationId` (per-op
|
||||||
lifecycle, `:68`), `ExecutionId` (per-run, `:75`), `ParentExecutionId` (spawner link, `:82`).
|
lifecycle, `:68`), `ExecutionId` (per-run, `:75`), `ParentExecutionId` (spawner link, `:82`).
|
||||||
@@ -139,7 +139,7 @@ done carelessly. **Priority: LOW. Blast radius: HIGH.**
|
|||||||
- **Confirm the writer contract matches.** `IAuditWriter.WriteAsync(AuditEvent, CancellationToken
|
- **Confirm the writer contract matches.** `IAuditWriter.WriteAsync(AuditEvent, CancellationToken
|
||||||
= default)` is already byte-for-byte the canonical signature, and the "never abort the
|
= default)` is already byte-for-byte the canonical signature, and the "never abort the
|
||||||
user-facing action" wording matches. The only delta is the **record type**: the library's
|
user-facing action" wording matches. The only delta is the **record type**: the library's
|
||||||
`IAuditWriter` is typed on the *canonical* 8-field `AuditEvent`, while ScadaBridge's is typed on
|
`IAuditWriter` is typed on the *canonical* 10-field `AuditEvent`, while ScadaBridge's is typed on
|
||||||
its ~25-field record. Resolve by either (a) keeping ScadaBridge's writer on its own rich record
|
its ~25-field record. Resolve by either (a) keeping ScadaBridge's writer on its own rich record
|
||||||
and adopting only the library's *interface name + outcome enum*, or (b) having the shared seam be
|
and adopting only the library's *interface name + outcome enum*, or (b) having the shared seam be
|
||||||
generic over the event type. **Recommended: (a)** — adopt the canonical `AuditOutcome` enum and
|
generic over the event type. **Recommended: (a)** — adopt the canonical `AuditOutcome` enum and
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ code-verified current-state docs (`../current-state/`) and the locked design
|
|||||||
- **Transport & storage** — OtOpcUa's Akka cluster-broadcast → singleton `AuditWriterActor` (batch
|
- **Transport & storage** — OtOpcUa's Akka cluster-broadcast → singleton `AuditWriterActor` (batch
|
||||||
500 / 5 s, two-layer dedup) over `ConfigAuditLog`; MxGateway's SQLite `IApiKeyAuditStore` append +
|
500 / 5 s, two-layer dedup) over `ConfigAuditLog`; MxGateway's SQLite `IApiKeyAuditStore` append +
|
||||||
list-recent; ScadaBridge's site-SQLite hot-path → central MS SQL ingest / reconcile / purge /
|
list-recent; ScadaBridge's site-SQLite hot-path → central MS SQL ingest / reconcile / purge /
|
||||||
partition-maintenance / hash-chain pipeline. The shared core is **BCL-only** and carries no Akka /
|
partition-maintenance / hash-chain pipeline. The shared core carries no Akka / EF / SQLite /
|
||||||
EF / SQLite / Serilog dependency.
|
Serilog dependency; its only non-BCL dependency is `Microsoft.Extensions.DependencyInjection.Abstractions`
|
||||||
|
(for `AddZbAudit`).
|
||||||
- **Domain vocabulary** — ScadaBridge's `Channel` / `Kind` / `Status` / `ForwardState` enums and
|
- **Domain vocabulary** — ScadaBridge's `Channel` / `Kind` / `Status` / `ForwardState` enums and
|
||||||
OtOpcUa's `EventType` strings (`DraftCreated`, `Published`, `OpcUaAccessDenied`, …). These map
|
OtOpcUa's `EventType` strings (`DraftCreated`, `Published`, `OpcUaAccessDenied`, …). These map
|
||||||
*into* `Action` / `Category` / `Outcome` / `DetailsJson`; they do not leak into the shared type.
|
*into* `Action` / `Category` / `Outcome` / `DetailsJson`; they do not leak into the shared type.
|
||||||
@@ -125,12 +126,12 @@ name (identical `AuditEvent Apply(AuditEvent)` signature, pure / never-throws /
|
|||||||
library essentially **lifts ScadaBridge's seams**.
|
library essentially **lifts ScadaBridge's seams**.
|
||||||
|
|
||||||
The one real (non-naming) decision is the **writer's record type**: the canonical `IAuditWriter` is
|
The one real (non-naming) decision is the **writer's record type**: the canonical `IAuditWriter` is
|
||||||
typed on the 8-field `AuditEvent`; ScadaBridge's writer is typed on its ~25-field record.
|
typed on the 10-field `AuditEvent`; ScadaBridge's writer is typed on its ~25-field record.
|
||||||
|
|
||||||
> **Resolution (recommended):** share the **interface *name* + the `AuditOutcome` enum**, not the
|
> **Resolution (recommended):** share the **interface *name* + the `AuditOutcome` enum**, not the
|
||||||
> record schema. ScadaBridge keeps its rich ~25-field record as its **storage shape** (its whole
|
> record schema. ScadaBridge keeps its rich ~25-field record as its **storage shape** (its whole
|
||||||
> transport / partition / forwarding / reconciliation layer is built on the extra columns), and maps
|
> transport / partition / forwarding / reconciliation layer is built on the extra columns), and maps
|
||||||
> to the canonical 8-field record **only at cross-app reporting boundaries**. This is the
|
> to the canonical 10-field record **only at cross-app reporting boundaries**. This is the
|
||||||
> minimal-coupling option — share the contract, not the schema — and avoids making the shared seam
|
> minimal-coupling option — share the contract, not the schema — and avoids making the shared seam
|
||||||
> generic over the event type. ScadaBridge therefore converges by **renaming one interface** and
|
> generic over the event type. ScadaBridge therefore converges by **renaming one interface** and
|
||||||
> adopting `AuditOutcome`, with no transport / storage / CLI / UI change.
|
> adopting `AuditOutcome`, with no transport / storage / CLI / UI change.
|
||||||
|
|||||||
Reference in New Issue
Block a user