Uh oh!
There was an error while loading. Please reload this page.
docs(plugin-audit): the published README documents the record-view audit surface that shipped - #9541
Merged
Conversation
…dit surface that shipped (#9517) PR #9531 corrected this README against the shipped surface while record-view auditing was still an unmerged draft, so it correctly refused to describe it. That work has since landed (#8992 via PR #9515), which made two of the page's statements false: "reads and views are not on the ledger", and that the plugin takes no configuration. The page now documents the surface that exists, each point measured against the source rather than against a description of it: the `read` action and its writer in the action table, the `record_views` list view, the record-detail discriminator (one materialized record plus a primary-key pin, `$or`/`$not` refused) that keeps list and search reads out of scope, the batched off-request-path writes with the view-instant `created_at` and the two loud once-only failure postures, and the two declared boundaries — a system-elevated read and a read with no principal both write no row. The opt-in is documented as what it is: an INSTALL-TIME list on the plugin constructor, explicitly not an `enable.auditReads` object-metadata key. That spelling was ruled against on #8992 for the reason this card exists — a declarable key can be set on an object in a deployment that never installs the plugin, producing metadata that reads as audited and writes nothing. Two things the page now says that only reading the code shows: `maxBufferedEvents` is a writer knob the plugin does not forward, and the shipped `record_views` view carries an `ip_address` column that is always empty on a `read` row because no read-path writer stamps it. Record-view auditing adds no enterprise dependency — this package's declared edition is `open` — so nothing new is annotated under that pattern; the two existing annotations are unchanged. A changeset is owed because the README ships in the package's `files` array: a docs-only correction with no version bump never reaches the npm package page. Co-authored-by: Claude <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 4 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
This was referenced Aug 18, 2026
os-project-manager
marked this pull request as ready for review
August 18, 2026 08:33
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#9517
This is the residual half of the card. PR #9531 (
53fc09922) landed the urgent half — the SOC 2 / HIPAA / GDPR claim, the 12 fabricatedauditServicemethods, the wrong row shape, the wrong object name and the 6 nonexistent REST routes are all gone frommain, and two dependency boundaries were annotated. It correctly refused to document record-view auditing because that work was still an unmerged draft.Premise re-verified before editing anything
prints
landed.5126e795disfeat(plugin-audit): record-view auditing — who viewed which record (#8992) (#9515), so the blocker named in the previous round is cleared and the surface is now describable. Everything below was measured againstorigin/mainat53fc09922, not against the card's description of it.What the README now documents
readaction, in the action table with its writer and trigger, and therecord_viewslist view in the views table.destroy()tail drain, and whycreated_atholds the view instant rather than the flush instant.$or/$notrefusal, and the depth bound. This is what keeps list and search reads out of scope, so it is stated as the scope rule rather than as trivia.Two things only reading the code shows, both now on the page:
maxBufferedEvents(default 10000) is a writer knob the plugin does not forward. Documenting it as a plugin option would have been a small instance of exactly this card's defect.record_viewsview carries anip_addresscolumn that is always empty on areadrow, because no read-path writer stamps it. Filed separately asrecord_viewslists anip_addresscolumn that no read-path writer ever stamps — a declared-but-unwritten column on a shipped compliance view #9539; documented here rather than left to surprise a reader.The opt-in is an install-time list, not a metadata key
The README says so explicitly, and says why.
enable.auditReadsappears on the page exactly once, in a sentence stating it does not exist — and the verification below asserts that, so a later edit cannot quietly turn the mention into a documented API.Scope 4 re-checked: record-view auditing introduces no enterprise boundary
packages/spec/src/kernel/platform-capabilities.ts:143declaresaudit: { package: '@objectstack/plugin-audit', edition: 'open' }. Thereadwriter lives in this package, the opt-in is ordinary plugin configuration, and nothing about the capability degrades on an open build. ⇒ Nothing new is annotated under theaccess-recipes.mdxpattern; the page says so in one sentence rather than inventing a dependency. The two existing annotations (archive datasource fails closed to retention, hierarchy resolver fails closed toown) are untouched, and the second is noted as applying toreadrows the same way it applies to every other row.Evidence: a set-equality check anyone can re-run
Matching the bar PR #9531 set. Save and run from the repo root:
Output at
4435acf66:Nothing is documented that the source does not declare, and nothing declared is left out: 8 of 8 action values, 13 of 13 fields, 6 of 6 list views, 28 of 28 export symbols resolving in
src/index.ts, 3 of 3 plugin options with their defaults matching the writer's.The check is proven able to fail
A green check nobody has seen go red is an assurance, not evidence. Three ablations, each run against the committed tree and each restored to byte identity afterwards:
readrow from the action tableFAIL action enum: documented 7 / declared 8 — omitted: ["read"]record_viewsrow from the views tableFAIL list views: documented 5 / declared 6 — omitted: ["record_views"]maxBatchSizeas 25FAIL default maxBatchSize: README 25 / source 50After restore,
git diff --stat HEADis empty and the check passes again.Gates
Derived from
git merge-base origin/main HEAD(53fc09922) per #9320, not from a two-dot range:node scripts/pm/dispatch-gates.mjs .changeset/mighty-ducks-repeat.md packages/plugins/plugin-audit/README.mdgives 8 path-derived plus 1 convention-triggered. All run at4435acf66, which is the branch tip and the tree every gate saw.check:changeset-gate-self-testscheck:objectui-changesetcheck:test-source-aliascheck:type-source-resolutioncheck-adr-0087-registration.mjscheck-changeset-no-major.mjscheck-empty-changeset.mjscheck-affected-docs.mjscheck:i18n(convention-triggered)check:nul-bytes(any edit)check:i18nrefused the unbuilt tree first (PREREQUISITE NOT MET, exit 1) and only went green afterturbo run build --filter=@objectstack/cli(55 tasks). Reported green here is green, not skipped.Package scope, after building the dependency closure (
pnpm --filter '@objectstack/plugin-audit^...' build):and
pnpm --filter @objectstack/plugin-audit typecheckclean — the script name is echoed in the output, so this is not a zero-match silent pass. All heavy runs were serialized throughflock -E 99 -w 240 /tmp/os-heavy-verify.lock; no queue timeouts.Changeset
Owed,
patch. PR #9531's reasoning is the precedent and it holds here:README.mdis in this package's publishedfilesarray withprivateunset, so a docs-only correction with no version bump never reaches the npm package page at all. The changeset is the mechanism that publishes the correction, not paperwork — which is whyskip-changesetwould be the wrong call.Findings filed, not fixed here
record_viewslists anip_addresscolumn that no read-path writer ever stamps — a declared-but-unwritten column on a shipped compliance view #9539 —record_viewsdeclares anip_addresscolumn that no read-path writer stamps, so it is empty on every row that view can show. Same defect class as the audit-log-browser: 4 of 10 declared sys_audit_log actions have no writer anywhere (login/logout/permission_change/config_change/export/import never materialize) #7675 / audit-log (C): retireexport/import/permission_changefrom thesys_audit_logaction enum and its in-repo consumer surfaces (ADR-0087 registration) #8147 /sys_audit_log.actiondeclaresrestorewith no writer anywhere —actionFor()structurally cannot return it, while a comment and a shipped list view both assert it is covered #8315 enum retirements, one layer down. Not fixed here: it is a code change to a landed feature and does not meet the in-place bar for a docs-only PR.content/docspage — the shipped compliance capability is documented only in a package README #9540 (finding) — record-view auditing has nocontent/docspage; the only written scope is this README. Recorded, not claimed as a defect:check:affected-docsis green, and "the package README is the right home" is a legitimate disposition.Generated by Claude Code