Skip to content

perf(plugin-audit): 审计跳过名单上到注册面,SKIP_OBJECTS 表不再买单前置行读 (#5860) - #6614

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5860-audit-exclude-objects
Aug 8, 2026
Merged

perf(plugin-audit): 审计跳过名单上到注册面,SKIP_OBJECTS 表不再买单前置行读 (#5860)#6614
baozhoutao merged 1 commit into
mainfrom
claude/issue-5860-audit-exclude-objects

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5860

#5928 裁决预告与 06:28Z 解锁注记收敛:五个写入注册带 excludeObjects,writeCommentMentions 收为 { object: 'sys_comment' },handler 早退保留为纵深防御。

前提复核(origin/main,逐处实测)

前提 单据记录 实测
5 个注册全部无 object 544/545、746/747/748 行号已漂移,内容成立(改前 registerHook 六处,五处裸 { packageId })
excludeObjects 已在引擎 PR #6575 engine.ts:716(HookEntry)、:1287(options)、:770(hookMatchesObject)、:818(拒绝语义)
在飞零相交 #6428 应不相交 遍历全部 remote claude/* 分支 diff,plugin-audit 命中数 0
运行期后注册对象天然被审计 第 5 轮 probe D 的合规担忧 已成立,并反向探针证明该钉子有牙(见下)

改法

SKIP_OBJECTS 这份知识一直存在,只是停在 handler 早退里、注册面上看不见,所以按注册面计算的需求门(#5284 单 id update() 前置行门、#5038 批量门)只能保守判真。现在:

const AUDIT_EXCLUDED_OBJECTS: string[] = [...SKIP_OBJECTS];

五个注册带上它。派生而非重抄 —— 注册面与 handler 早退是同一份名单,不可能各自漂移;早退保留,护住每一个非 hook 调用方,审计写入行为逐位守恒。

拒绝语义按 #6575 正文:名单是字面量常量,展开后既不含 '' 也不含 '*',测试对这两点直接断言。

为什么是减法,不是枚举补集

对象全集在运行期是开放的:/meta PUT 把新对象注册进运行中的引擎,而 SchemaRegistry.registerObject 不发任何事件,插件侧没有可订阅的通道去追平枚举名单 —— 那样的名单在启动时冻结,此后新建的对象静默不被审计。这条不是转述,是本 PR 的反向探针实测(见下)。

先红后绿(方向先判后跑)

新增 audit-hook-object-scope.test.ts,用 ObjectQL + 计数驱动,而非只读注册面的假引擎。

改前(预判红:门判"需要"):

FAIL  single-id update() on `sys_job_queue` pays ZERO prior reads
AssertionError: expected 1 to be +0
FAIL  the gate itself answers `false` for every audit event on a skipped object
AssertionError: expected true to be false
Tests  5 failed | 117 passed (122)

expected 1 to be +0 就是白读的那一次;expected true to be false 是门判定本身 —— #5284 门翻转的直接证据

改后: Test Files 8 passed | Tests 122 passed (122)

诚实读数: 「非 SKIP 对象门仍判需要」「后注册对象仍被审计」「mentions 只在 sys_comment 触发」三条改前改后都绿 —— 它们是守恒钉,不是翻转钉,测试正文里逐条注明了,不要读成有牙的翻转断言。

反向探针(补上守恒钉的牙)

守恒钉恒绿就有变成幻影检查的风险,所以单独跑了一次「改坏」:把 writeAuditafterInsert/afterUpdate 换成枚举式允许列表 { object: ['biz_task'] }。预判合规钉红,实测正是它红:

FAIL  a `/meta`-style late registration is covered with no re-install
AssertionError: expected false to be true

即安装后注册的对象门直接关闭 —— probe D 担忧的静默漏审。顺带发现既有的 audit-plugin.test.ts 也会红一条,说明过度收窄有两道网。探针已回滚,回滚后复跑 122 全绿。

验证读数

  • pnpm --filter @objectstack/plugin-audit test8 files / 122 tests 全绿(改前 5 红 117 绿)
  • pnpm --filter @objectstack/dogfood test85 passed / 1 skipped(86 files),520 tests 通过 —— 消费半径:四个 dogfood 套件装真 kernel + plugin-audit 断言审计轨迹
  • pnpm --filter @objectstack/plugin-audit typecheck 绿
  • check:nul-bytes(6183 文件)、check:engine-double-contractcheck:empty-changesetcheck:wildcard-fallthroughcheck:published-filescheck:type-check-coveragecheck:durability-log-levelcheck:adr-anchors 全绿

两处需要复核的判断

其一:测试用了真引擎,因此给 plugin-audit 加了 @objectstack/objectql 的 devDependency。 假引擎只能证明"注册面写了什么",证明不了"门怎么判" —— 而本单的验收判据恰恰是后者。先例是 plugin-auth(同为 devDependency,last-admin-guard.test.ts 用真 ObjectQL)。

其二:vitest.config.ts 的 alias 从对象形式改为锚定正则数组。 不是顺手重构,是本测试跑不起来的直接原因:对象形式按前缀匹配,裸 @objectstack/spec 那条吞掉了所有没逐条列出的子路径,@objectstack/spec/ui 解析成 spec/src/index.ts/uiENOTDIR(objectql 传递性地引到它)。service-knowledge/vitest.config.ts 已经把这个坑和改法记录在案,这里照搬同一形状,现有映射语义逐条保留。

范围外发现

无。⛔ 未触 packages/objectql(引擎门属 engine-core;#5846 (a) 半边明令不合 PR)。


Generated by Claude Code

五个写入注册(captureBefore 的 beforeUpdate/beforeDelete,writeAudit 的
afterInsert/afterUpdate/afterDelete)此前不带任何对象范围,在引擎眼里全部是
全局 hook。SKIP_OBJECTS 这份知识停在 handler 早退里,注册面上看不见,于是
#5284 的单 id update() 前置行门与 #5038 的批量门只能保守判真,对 sys_job_queue
一类平台内部表每次写入白读一遍行集 —— 而 handler 第一行就返回。

现在五个注册带上 #5928 / PR #6575 落地的 excludeObjects,名单由 SKIP_OBJECTS
派生而非重抄,两个面无法各自漂移;handler 早退保留为纵深防御,审计行为守恒。
排除面(减法)而非允许列表(枚举补集):对象全集在运行期开放,枚举出来的名单
会在启动时冻结并静默漏审此后新建的对象。

顺带把 writeCommentMentions 收为 { object: 'sys_comment' } —— 封闭单名允许
列表,现有契约一直表达得了,行为不变。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JwwiU9bjhwy2SWj13ho8uv
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 7:11am

Request Review

@github-actions github-actions Bot added the size/l label Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/plugin-audit.

4 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/deployment/cli.mdx (via @objectstack/plugin-audit)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/plugin-audit)
  • content/docs/plugins/packages.mdx (via @objectstack/plugin-audit)
  • content/docs/releases/implementation-status.mdx (via @objectstack/plugin-audit)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling labels Aug 8, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review August 8, 2026 07:22
@baozhoutao
baozhoutao added this pull request to the merge queue Aug 8, 2026
Merged via the queue into main with commit 0f8d16a Aug 8, 2026
26 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-5860-audit-exclude-objects branch August 8, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

plugin-audit 的 5 个 hook 全部无 object 注册 ⇒ 引擎「按对象」需求门(#5284 单 id / #5038 批量)在 audit 启用时恒真

2 participants