Skip to content

Commit ad192cb

Browse files
docs(kernel): correct the audit-write failure report granularity to once per cause (#19212)
Fixes #17451 ## What this changes One bullet on `content/docs/kernel/runtime-services/audit-service.mdx` (the `## Typical Errors` section, lines 76-79 before this change). It described the failed ledger insert of `recordAuthEvent` as reported at `error` level **once per process**, with every later failure dropping to `debug`. That sentence is false on `origin/main` today, and the page it sits on is the audit service's own contract documentation. The bullet now states the granularity the runtime actually has: **once per cause**, a cause being the error `code` plus the object the row is about. A repeat of an already-reported cause still degrades to `debug`; a **new** cause gets its own `error` line, once. ## Where the behaviour actually lives Measured in this worktree at `24d622b94` (the branch point), re-read rather than inherited from the card: - The paragraph's subject is `recordAuthEvent`, whose implementation is `packages/plugins/plugin-audit/src/auth-event-audit.ts:282` — the same file the page already names as its **Canonical source** (`:7`). - The dedupe there is cause-keyed, not a process-wide boolean: `auth-event-audit.ts:211` declares `reportedAuthEventFailureCauses` as a `Set` of cause keys (a `Set` parameterised by the string type — spelled out here rather than written literally), filled at `:229` and read at `:221`. The key is built at `:220` by `auditFailureCauseKey(SESSION_OBJECT, err)`, with `SESSION_OBJECT = 'sys_session'` at `:152`. - The shared key is `packages/plugins/plugin-audit/src/audit-writers.ts:739` `export function auditFailureCauseKey(object: string, err: unknown): string` — the error's `code` when it is a string or a number, and the single bucket `(no code)` otherwise, joined with the object name. - The runtime message this seam prints already says the same thing in words (`auth-event-audit.ts:239-240`): "this CAUSE is reported ONCE … a DIFFERENT cause gets its own `error` line". The page was the last place still describing the old unit. ⚠️ The card attributes the falsification to PR #17450 / card #15166, which re-keyed `audit-writers.ts`. That is the wrong file for this paragraph: `audit-writers.ts` backs the CRUD audit writers, not `recordAuthEvent`. The second, independent copy of the process-wide boolean — the one this page documents — lived in `auth-event-audit.ts` and was re-keyed separately. The card's conclusion holds; only its citation is corrected here. ## Scope - One file, one bullet. `git diff --stat` on this branch: `1 file changed, 7 insertions(+), 4 deletions(-)`. - ⛔ No code changed anywhere under `packages/**`. - Verified before editing: `once per process` occurs **1** time in this page's 114 lines (`:76`). Positive control for the query: the same phrase returns **3** further hits elsewhere under `content/docs/` — so that `1` is a reading, not a broken pattern. ## Changeset No changeset, `skip-changeset` label applied. Measured rather than assumed: `content/docs/` is consumed by `apps/docs`, whose manifest is `"private": true`, and no published package in the workspace lists a `content`- or `docs`-shaped entry in its `files[]`. Positive control for that scan: published packages with a `files[]` array are found and printed (`@objectstack/hono`, `@objectstack/cli`, `@objectstack/client-react`, …), all of them shipping `dist` / `README.md` / `CHANGELOG.md` only. This diff therefore publishes nothing. ## Tests `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 40 commands for this path; all 40 were run. See the PR's Acceptance notes below for the four that first reported `PREREQUISITE NOT MET` against unbuilt workspace packages and were re-run after building them. ## Acceptance notes - **Noted, not filed here:** `content/docs/permissions/record-view-auditing.mdx:221` carries the same phrase for a different surface. It is deliberately untouched by this PR — the card fences it and so does the `domain:services` seat. It is neither excluded-because-verified nor cleared; it is simply out of this PR's surface, and is reported to the PM for separate triage. --- _Generated by [Claude Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 24d622b commit ad192cb

1 file changed

Lines changed: 7 additions & 4 deletions

File tree

‎content/docs/kernel/runtime-services/audit-service.mdx‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,13 @@ error, so every failure is caught, and callers do not need a surrounding `try`/`
7373
The consequences are worth knowing precisely, because none of them are visible from the
7474
caller's side:
7575

76-
- A failed ledger insert is reported at `error` level **once per process** — every later
77-
failure drops to `debug` — and the row is simply lost. Nothing retries it. The sign-in
78-
itself succeeded and returned 200, so the shipped `auth_events` list view and the
79-
system-overview widgets keep showing an empty, healthy-looking screen.
76+
- A failed ledger insert is reported at `error` level **once per cause** — a cause is the
77+
error's `code` plus the object the row is about, so every uncoded failure collapses into
78+
one bucket and the object is always `sys_session` on this seam — and the row is simply
79+
lost. Nothing retries it. A repeat of an **already-reported** cause drops to `debug`; a
80+
**new** cause gets its own `error` line, once. The sign-in itself succeeded and returned
81+
200, so the shipped `auth_events` list view and the system-overview widgets keep showing
82+
an empty, healthy-looking screen.
8083
- The call **silently no-ops** when no data engine resolves, or when `userId` is absent.
8184
A caller that passes an event without a subject records nothing and is told nothing.
8285
- The most common cause of a failing insert is a datasource split rather than a broken

0 commit comments

Comments
 (0)