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
feat(plugin-audit): record-view auditing — who viewed which record (#8992) (#9515)
* feat(plugin-audit): record-view auditing — the `read` action, its writer, and its view (#8992)
`sys_audit_log` covered writes only: `actionFor()` maps exactly
afterInsert/afterUpdate/afterDelete, and the shipped list views confirmed the
scope. "Who viewed this customer record, and when?" was unanswerable.
Adds the `read` action WRITER-FIRST — the emission point, its tests, and the
`record_views` list view that surfaces it, in one stroke, which is the only way
a value is allowed onto this enum (#8147 / #8315).
Scope is the maintainer's 2026-08-16 ruling, and each pin is code:
- record-detail views only — `extractDetailReadId` requires one materialized
record AND a primary-key pin, so list/search reads produce nothing;
- per-object opt-in, closed — one input, used as the narrow `afterFind`
registration target, so a non-audited read costs no dispatch;
- batched off the request path — the hook enqueues and returns; each row keeps
the VIEW instant via the system-context `created_at` exemption (#4447).
The row carries no field values: `afterFind` runs ahead of the security
middleware's field masking, so `ctx.result` is pre-mask plaintext.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(plugin-audit): give the harness objects their owning package id
`registry.registerObject(schema, packageId)` requires the owner; the one-arg
call ran fine but failed `tsc --noEmit`.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(plugin-audit): type the engine query options instead of erasing them to `any`
The new read-audit suite added 22 sites to the `query-options-erasure`
test-surface ratchet (240 -> 262). Fixed at the source: every find/findOne/
insert options bag is now passed typed, and the shared read context is a named
`ReadContext` alias off `EngineQueryOptions['context']`. The ratchet returns to
240 — flat, not raised.
This is not count-satisfying hygiene here. The gate's #8210 caveat is that in a
package whose tsconfig excludes test files, typing these buys no compiler guard
today. plugin-audit does NOT exclude them, so `tsc` reads this file and a wrong
options key is a real compile error rather than a silently dropped one (#4674).
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments