fix(plugin-audit): 把 sys_job_queue 加进 SKIP_OBJECTS 的运维管道豁免组 (#5193) - #5201
Merged
Conversation
…5193) SKIP_OBJECTS group (2) — ADR-0057 decision 5 "stop the amplifier" — already listed sys_job / sys_job_run / sys_automation_run, but not their highest-volume sibling sys_job_queue. The audit writers register for all objects and there is no system-context exemption, so DbQueueAdapter's own writes were mirrored into sys_audit_log AND sys_activity: at least three per message (publish insert, lease pending->running, terminal ->completed), plus a retry update per failure and the #5192 reaper's periodic DELETE — on every email since #5160 routed delivery through the queue. Each beforeUpdate also paid an extra findOne snapshot of the row it was about to change. sys_job_queue is engine-owned plumbing (managedBy: 'engine-owned', enable.apiMethods: ['get','list'], lifecycle.class: 'transient' since #5179) that no user can write, so the rows carried no compliance value. Tests pin the whole message lifecycle (insert/lease/complete/reaper delete) producing zero rows, the four siblings sharing one exemption group, the skipped snapshot read (with a business-object control), and that ordinary writes are still audited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017MCKJaEomEqg4tvz4SzdNd
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 4 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 4, 2026
os-zhuang
marked this pull request as ready for review
August 4, 2026 09:14
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 4, 2026
…tes (objectstack-ai#5202) (objectstack-ai#5215) SKIP_OBJECTS group (2) — ADR-0057 decision 5 "stop the amplifier" — gained sys_job_queue in objectstack-ai#5193/objectstack-ai#5201; sys_upload_session is the same gap one table over. It declares lifecycle.class: 'transient' and its own object comment settles what the rows are worth: "an upload session is ephemeral state, never business truth" (ADR-0057 / objectstack-ai#2970 item 4). Nothing connected that declaration to the exemption list, which is hand-written. The audit writers register for all objects and there is no system-context exemption, so StorageMetadataStore's own writes were mirrored into sys_audit_log AND sys_activity. A chunked upload of N parts costs 1 + N writes — the createSession() insert plus one updateSession() per chunk — then a terminal status update and the row's removal (deleteSession, or the TTL/retention reaper), so 2 × (1 + N) ledger rows for one file, each with its own beforeUpdate snapshot read. Each row was unusually fat too: updateSession() writes the merged FULL record, so the `parts` JSON blob that grows with every chunk rode along in every diff's old_value/new_value. sys_file stays audited on purpose: it declares transient as well, but only to reap tombstones and unfinished uploads — its rows are mostly permanent business truth with real compliance value. Tests pin a completed 8-chunk lifecycle and an aborted-then-reaped one producing zero rows, the skipped snapshot read (with a business-object control), the deliberate non-exemption of sys_file, and that ordinary writes are still audited. Removing the one list entry turns the first three red (22, 12 and 5 unwanted writes respectively). Claude-Session: https://claude.ai/code/session_017MCKJaEomEqg4tvz4SzdNd Co-authored-by: Claude <noreply@anthropic.com>
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 free
to 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 #5193
问题
audit-writers.ts的SKIP_OBJECTS第 (2) 组是 ADR-0057 决策 5「stop the amplifier」在写入器这一层的落点,组里已经有sys_job/sys_job_run/sys_automation_run,唯独漏了同族里量最大的sys_job_queue。审计钩子(
afterInsert/afterUpdate/afterDelete)是全对象注册的,并且没有任何「系统上下文写入不记审计」的豁免 —— 把关的只有SKIP_OBJECTS。所以DbQueueAdapter自己用 SYSTEM_CTX 写的每一行都照记不误:pending → running、完成的→ completed(失败还要每次 retry 多一次 update),再加 fix(service-queue,platform-objects): sys_job_queue 的 completed 行按声明式 retention 到期即清(#5179) #5192 reaper 对 completed 行的周期性 DELETE;sys_audit_log和sys_activity两行;beforeUpdate还额外做一次captureBefore的findOne快照 —— 队列每次状态流转都白读一行;sys_job_queue是纯平台内部管道(managedBy = engine-owned、enable.apiMethods = get/list、#5179 起 lifecycle.class = transient),用户根本写不了它,这些行没有任何合规价值,只是噪声与写放大。修法
与兄弟表完全同形:把
sys_job_queue加进第 (2) 组(紧挨sys_job_run),注释里写清理由并引 #5193 与 ADR-0057 决策 5、上下游的 #5160 / #5179 / #5192。一个名字、一处清单,没有新分支、没有新配置。测试
packages/plugins/plugin-audit/src/audit-writers.test.ts新增一组(照该文件既有的 fake-engine 形状,不引入新设施;fake engine 没有delete方法,因此不触及assertEngineDeleteDispatch门禁):service-queue为一条消息做的全部写按序打一遍(publish insert → lease update → complete update → reaper delete),断言created为空数组(不是「少了几行」,是零);sys_job/sys_job_run/sys_job_queue/sys_automation_run四张表同组同待遇;beforeUpdate/beforeDelete不再对被跳过的对象做findOne,并用一个业务对象(crm_lead确实被快照)作对照,证明该断言能失败;sys_audit_log+sys_activity。变异验证:临时删掉那一行后,上述 1/2/3 三个用例全部转红(4 是对照,两种情况下都绿),确认测试钉的是修复本身。
越界发现(未在本 PR 修)
sys_upload_session同样声明了 lifecycle.class = transient(其自身注释即写「ephemeral state, never business truth」)却不在SKIP_OBJECTS里,分块上传每传一块就是一次updateSession全量写。已按一事一议单独立单:#5202(未指派,交 PM 分诊)。🤖 Generated with Claude Code
https://claude.ai/code/session_017MCKJaEomEqg4tvz4SzdNd