You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(plugin-audit): report a lost audit row once per CAUSE, and name the real cause in the first line (#17450)
* fix(plugin-audit): key the lost-audit-row report per CAUSE, and put the real cause in the first line
`reportAuditWriteFailure` deduped on one process-wide boolean, so after the
first failure of ANY cause every later failure of every OTHER cause degraded to
`debug` for the life of the process, and the one `error` line it did print named
the telemetry-datasource remedy unconditionally — the measured
`ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED` refusal sent its operator to check a
datasource that was working.
The dedupe key is now the failure's identity — the error `code` (or its
absence) plus the object. A repeat of an already-reported cause still degrades
to `debug`; a new cause reports at `error`, once. The key is built from the
`code` and never the message, which is what keeps the cause set bounded by the
boot-declared object registry and the driver's code vocabulary rather than by
traffic.
The ADR-0057 §3.6 datasource guidance is kept and made conditional on the
missing-table cause it is the remedy for, asked through the shared
`isMissingTableError` predicate for both tables `persistAuditTrailRow` writes.
Claude-Session: https://claude.ai/code/session_01ToDPcx9AESFubJkDiFMtKW
Co-authored-by: Claude <noreply@anthropic.com>
* chore(changeset): patch for the cause-keyed audit-write failure report
Claude-Session: https://claude.ai/code/session_01ToDPcx9AESFubJkDiFMtKW
Co-authored-by: Claude <noreply@anthropic.com>
* build(plugin-audit): resolve @objectstack/types to source for tsc
`pnpm check:type-source-resolution` reds on the new dependency: without a
`paths` rule this package's typecheck would be a verdict about
`types/dist` build state rather than about the checkout. Same entry, same
spelling, same reasoning `plugin-security` records for the identical import.
Claude-Session: https://claude.ai/code/session_01ToDPcx9AESFubJkDiFMtKW
Co-authored-by: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
A lost audit row is reported once per failure CAUSE, not once per process, and the first line names the cause instead of a fixed remedy.
6
+
7
+
`reportAuditWriteFailure` — the best-effort catch around `persistAuditTrailRow` — deduped on a single process-wide boolean. After the first failure of any cause, every later failure of every *other* cause degraded to `debug` for the life of the process, so a long-running server could keep losing compliance rows for hours to a second, unrelated fault with one `error` line at the top of the log describing the first. `persistAuditTrailRow` is registered in the durability-degradation vocabulary precisely because a lost audit row must be reported at `error`.
8
+
9
+
The dedupe key is now the failure's identity — the error `code` (or its absence) together with the object being audited. A repeat of an already-reported cause still degrades to `debug`, exactly as before; a new cause reports at `error`, once. The key is built from the `code` and **never** the message: a driver names the offending row in its message, so a message-keyed dedupe would grow one `error` line per failed write. Keyed on the code, the reported-cause set is bounded by the boot-declared object registry and the driver's code vocabulary and does not grow with traffic — measured at 65 lines for 6,500 failed writes and the same 65 for 26,000.
10
+
11
+
The first `error` line now leads with the underlying code and message, which were already computed at the call site and passed only into the `debug` payload. The ADR-0057 §3.6 telemetry-datasource guidance is kept — it is the correct remedy for the "no such table" cause it was written for — but is now printed only for that cause, decided by the shared `isMissingTableError` predicate for both tables this writer writes. Previously it was printed unconditionally, so an organization refusal was answered with "check the datasource", sending the operator to inspect something that was working.
12
+
13
+
`@objectstack/types` is added as a dependency for that predicate, rather than hand-rolling a second driver-error vocabulary.
0 commit comments