在 #5193(把 `sys_job_queue` 加进 `plugin-audit` 的 SKIP_OBJECTS)里,按派发要求核了一遍「还有哪些表同样漏在豁免外」。**未在 #5193 的 PR(#5201)里修**(越界,一事一议)。 ## 事实(均对 `origin/main` 核过) 把「声明了 lifecycle.class 为 telemetry / transient / event 的对象」与 `packages/plugins/plugin-audit/src/audit-writers.ts` 的 `SKIP_OBJECTS` 第 (2) 组对一遍,只剩两张表在豁免外: | 对象 | lifecycle.class | 在 SKIP_OBJECTS? | 判断 | |:--|:--|:--|:--| | `sys_upload_session`(`packages/services/service-storage/src/objects/system-upload-session.object.ts:132`) | transient | ❌ | **本单** | | `sys_file`(`.../system-file.object.ts:179`) | transient | ❌ | 不算漏 —— 其自身注释即写 “sys_file rows are mostly permanent business truth”,transient 只为收墓碑行/未完成上传;审计有合规价值 | `sys_upload_session` 的对象注释说的是另一回事:「an upload session is ephemeral state, **never business truth**」(ADR-0057 / #2970 item 4)—— 与 `sys_job_queue` 同类。 写入面(`packages/services/service-storage/src/metadata-store.ts`): - `createSession()` → `engine.insert(sys_upload_session, full)`(`:146`); - `updateSession()` → `engine.update(sys_upload_session, merged, …)`(`:178`)—— 分块上传**每传一块**调一次,而且写的是 merged **全量**记录,含 `parts` 这个随块数增长的 JSON blob,所以每行 audit 的 `old_value`/`new_value` diff 也跟着变大; - `deleteSession()` → `engine.delete(…)`(`:190`),外加 LifecycleService 的 TTL/retention reaper(ttl:`expires_at` + 1d;retention:7d,onlyWhen status 属于 completed/failed/expired)。 审计钩子全对象注册、无系统上下文豁免(`audit-writers.ts:651-653`,把关的只有 `:423` / `:461` 两处 `SKIP_OBJECTS.has`),所以一次 N 块的上传 = 1 + N 次写 → 2 × (1 + N) 行 `sys_audit_log` + `sys_activity`,外加每次 `beforeUpdate` 的 `captureBefore` 快照读(`:422`)。 ## 与 #5193 的差别(为什么单独立单而不是并进去) - 严重度低一档:上传频率远低于队列消息,#5160 那种「每封邮件都过」的常驻放大器在这里没有; - 治理声明也弱一档:`sys_job_queue` 有 managedBy = engine-owned + enable.apiMethods = get/list(用户根本写不了),`sys_upload_session` 两者都没有 —— 它只是**事实上**由 `StorageMetadataStore` 独占写入。要不要顺带补上治理声明,是这张表自己的问题,不该塞进审计豁免这单; - 目标表 `sys_audit_log` / `sys_activity` 本身有 retention/rotation,所以后果是**噪声与写放大**,不是无界增长。严重度请 PM 判。 ## 建议修法 与 #5193 完全同形:把 `sys_upload_session` 加进 `SKIP_OBJECTS` 第 (2) 组,注释注明其 lifecycle.class = transient 与「never business truth」的自述。等 #5201 落地后做,避免同一处清单的行冲突。 ## 顺带(#5193 正文已提出,这里只做交叉引用) 这份名单是**手写**的,与对象上的 lifecycle.class 没有任何机械关联 —— 本单就是这个耦合缺失的第二个实例(第一个是 #5193)。是否改成按注册表里的 lifecycle.class 判定(或加一道对账门禁:声明了 telemetry/transient/event 却不在豁免组的表必须显式登记豁免理由),值得单独定夺,不在本单范围内。 Found-during: #5193 / PR #5201 Related: #5193(同类,`sys_job_queue`)
Activity
os-zhuang commentedon Aug 4, 2026
分诊(PM 循环,#5193 派生):auto-queue ——
pm:queue+domain:identity。同形于 #5193(具名位置、修法同形、ADR-0057 决策 5 的 restore-invariant),不需要维护者拍板。串行在 PR #5201 之后(同一张 SKIP_OBJECTS 手写清单,同批必撞行),#5201 合入即可派。「SKIP_OBJECTS 与 lifecycle.class 无机械关联」的横切问题保持独立,不挂本单。Generated by Claude Code
os-zhuang commentedon Aug 4, 2026
认领:PM 循环第 8 轮
会话:
session_017MCKJaEomEqg4tvz4SzdNd分支:
claude/issue-5202-audit-skip-upload-sessionWorktree:
objectstack-issue-5202域:
domain:identity文件面:
packages/plugins/plugin-audit/src/(越界即停,报告说明)串行条件已满足:PR #5201 已合入 main,SKIP_OBJECTS 清单上的行冲突风险解除。与在飞的 #5195 接手(objectql/service-queue)、#5177 接手(plugin-email/platform-objects)不同包,并批安全。
Generated by Claude Code
os-zhuang commentedon Aug 4, 2026
复核结论:ACCEPT —— PR #5215,转 ready 并入合并队列。head 上 23 个 check run 全部 success/skipped。
与 #5201 同形的一行清单 + 注释;五个新用例含逐位对得上放大倍数的突变检查(删行后 8 块上传 = 2×11 行、3 块 abort = 2×6 行、5 次快照读,与 issue 预测完全一致),以及对
sys_file的刻意不豁免用例——把「为什么不豁免」也钉进了测试,防止未来有人顺手扩面。衍生 #5216(
StorageMetadataStore把全部 8 个 engine 调用包在无日志的catch { /* ignore */ }里,createFile失败即静默丢sys_file业务真相而 API 返回 200)已入队分诊,见该单评论。Generated by Claude Code
fix(plugin-audit): exclude sys_upload_session from audit/activity wri…
fix(service-storage)!: engine write/read failures stop masquerading a…