diff --git a/docs/plans/2026-05-20-auditlog-m4-remaining-boundaries.md b/docs/plans/2026-05-20-auditlog-m4-remaining-boundaries.md new file mode 100644 index 0000000..909d98e --- /dev/null +++ b/docs/plans/2026-05-20-auditlog-m4-remaining-boundaries.md @@ -0,0 +1,24 @@ +# Audit Log #23 — M4 Remaining Boundary Emission Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:subagent-driven-development (bundled cadence). + +**Goal:** Close every remaining script-trust-boundary emission gap: sync DB writes/reads via Database.Connection().Execute*/ExecuteReader, Notification Outbox central dispatcher attempts + terminal, site-side Notify.Send submission, and Inbound API middleware. Audit-write failure NEVER aborts the user-facing action across all five new code paths. + +**Vocabulary (M3 reality-locked):** +- `AuditKind.DbWrite` (Channel=DbOutbound) for both Execute and ExecuteReader; `Extra` carries `{"op":"write"|"read","rowsAffected":N|"rowsReturned":N}`. +- `AuditKind.NotifyDeliver` for each Notification Outbox attempt; `AuditStatus.Attempted` on attempts, `AuditStatus.Delivered|Failed|Parked|Discarded` on terminal. +- `AuditKind.NotifySend` for site-emit at Notify.Send; `AuditStatus.Submitted`. +- `AuditKind.InboundRequest` for happy-path inbound; `AuditStatus.Delivered`. `AuditKind.InboundAuthFailure` for 401; `AuditStatus.Failed`. +- `AuditStatus.Failed` replaces "PermanentFailure" / "TransientFailure" terminal wording throughout. + +**Bundles:** +- Bundle A — DB sync emissions (T1, T2) +- Bundle B — NotificationOutbox central emissions (T3, T4, T5) +- Bundle C — Site Notify.Send emission (T6) +- Bundle D — Inbound API audit middleware (T7, T8) +- Bundle E — Integration tests (T9, T10, T11, T12) +- Final cross-bundle review + merge + +Each task follows the M2 Bundle F / M3 Bundle E emission pattern: capture timing, build AuditEvent with provenance, write via try/catch that swallows + logs, never propagate audit failure to the user-facing action. Mirror M2's ScriptRuntimeContext wrapper pattern where the emission is script-context-aware. + +Integration tests go in `tests/ScadaLink.AuditLog.Tests/Integration/` (component-level per M2 Bundle H + M3 Bundle G — the existing IntegrationTests factory disables Akka).