docs(audit): roadmap corrections after M4

M5 head records M4 realities:
- AuditingDbConnection/Command/DataReader decorators need filter plug-in
  at WriteAsync emission point.
- CentralAuditWriter + FallbackAuditWriter are both filter integration
  points for the direct-write + chained-write paths.
- InboundAPI middleware RequestSummary populated, ResponseSummary=null
  pending response-body buffering decision in M5.
- UseWhen(/api/) path-scoped middleware gives natural per-target
  redaction hook.
- Error-row cap raised on Status IN (Failed, Parked, Discarded,
  Attempted, Skipped) per M1 vocab reconciliation.
This commit is contained in:
Joseph Doherty
2026-05-20 16:56:18 -04:00
parent ac7fc9ce4d
commit dae6de2c48

View File

@@ -902,6 +902,14 @@ The design for both is merged on `main` (`alog.md` cached-call tracking section;
## M5 — Payload + redaction policy ## M5 — Payload + redaction policy
> **M4 realities to honor:**
> - **Decorator surfaces to filter**: `AuditingDbConnection`/`AuditingDbCommand`/`AuditingDbDataReader` (Bundle A) emit `RequestSummary` as raw SQL + parameters today. M5's `IAuditPayloadFilter` runs between event construction and writer call; the AuditingDb decorators must call into the filter before `WriteAsync`.
> - **CentralAuditWriter wraps `IAuditLogRepository.InsertIfNotExistsAsync`** (Bundle B). M5 should plug the filter into BOTH the site-side `FallbackAuditWriter` and the central-side `CentralAuditWriter` so direct-write paths (NotificationOutboxActor, AuditWriteMiddleware) are also filtered. Plugin location: in each writer's `WriteAsync` BEFORE the storage call.
> - **InboundAPI middleware `RequestSummary` already populates, `ResponseSummary = null`** (Bundle D punted response-body capture). M5 should add response-body buffering OR document that ResponseSummary stays null for v1 (acceptable per the spec — captures are best-effort).
> - **`AuditWriteMiddleware` path-scoped via `UseWhen(/api/)`** — M5 may want to introduce per-target redaction overrides; that path-scoped setup gives a natural hook for per-route redaction (e.g., `/api/secrets/*` has stricter caps).
> - **Error-row vocabulary**: cap raised to 64 KB on rows with `Status NOT IN ('Delivered', 'Submitted', 'Forwarded')`. The new vocabulary (`Failed/Parked/Discarded/Attempted/Skipped`) is what triggers the elevated cap. NOT "non-Success" wording from the original spec.
> - **InternalsVisibleTo precedent**: AuditLog.Tests can reach internals of SiteRuntime + NotificationOutbox + (newly) AuditLog. M5 redaction tests can exercise internal helpers similarly.
**Goal:** Payload capture is bounded (8 KB / 64 KB on error), headers are redacted by default, SQL parameter values are captured by default with per-connection opt-out, body redactor regexes are configurable per target, and the safety net over-redacts on misconfiguration. **Goal:** Payload capture is bounded (8 KB / 64 KB on error), headers are redacted by default, SQL parameter values are captured by default with per-connection opt-out, body redactor regexes are configurable per target, and the safety net over-redacts on misconfiguration.
**Affected projects:** `AuditLog` (policy engine + options), `ExternalSystemGateway` (HTTP header redactors, SQL param redaction hook), `InboundAPI` (header redactors, body capture), `NotificationOutbox` (subject/body capture follows existing rules). Tests. **Affected projects:** `AuditLog` (policy engine + options), `ExternalSystemGateway` (HTTP header redactors, SQL param redaction hook), `InboundAPI` (header redactors, body capture), `NotificationOutbox` (subject/body capture follows existing rules). Tests.