Filed unassigned and ungraded by the domain:engine execution seat, carrying an open question #13636's dev raised and deliberately did not implement. ⛔ domain:*, priority and type are triage's. The fix面 is plugin-audit, which is the domain:services lane — ⛔ never repaired from this lane.
Filed as a card, not left in a dispatch report, because a cross-seat request that lives only in a report is invisible to that lane's candidate query, sweep and ageing alarms.
How it surfaced
PR #14923 (#13636) admits sys_audit_log into the #8844 derive-or-refuse machinery under the new conditional verdict. Admission makes the object stricter, which is the ruled intent. Its writers now declare their legitimately org-less cases explicitly.
One population is deliberately left undeclared, and that is correct on the merits: case 2 of audit-writers.ts's own enumeration — an audit row whose subject has an organization column whose value is NULL, written under a system context on a walled install. It is left to refuse because at that call site it is indistinguishable from the missing-stamp defect; #9516 was exactly that bug, on those exact lines.
The consequence, which is the actual subject of this card
That refusal (SystemWriteOrganizationRequiredError) lands inside plugin-audit's best-effort swallow-and-report catch.
⇒ ⭐ The outcome is a lost audit row, not a visible failure — and the row that is lost is precisely the audit record about a defective row. The control gets sharper and the evidence disappears at the same moment.
⚠️Not speculative: reachable today on any walled install holding a record whose organization column is NULL.
Three directions, as the dev costed them
四棱分析(维护者裁决用)
- 实际业务需求 —— ⭐ 拉动是实测的:case 2 在任何 walled 安装上、只要存在 organization 列为 NULL 的记录就可达,不是构造出来的边角。丢的还偏偏是关于那条缺陷记录的审计行,即最该留下的那一条。
- 项目长远合理性 —— ⭐ A 与 B 是在同两个好处之间对换:A 保住控制的锐度、静默丢行;B 保住行、致盲控制。C 拒绝承认这个交换是被迫的 —— A 的损失并非由拒绝造成,而是由拒绝不可见造成,而 plugin-audit 早已持有让这类丢失变响的通道。
- 防 AI 写代码犯错 —— ⭐ 本棱指向 C:C 让申报词表保持封闭,任何未来的写入方都无法伸手拿一个 case-2 理由去安抚一条它没读懂的拒绝。B 恰恰相反 —— 它新开一个最容易被误用的申报理由。
- 创业阶段不扩散需求 —— C 不新增能力、不新增面,只是在一条已经在上报的路径上改日志级别/通道。B 才是扩大接受集。
⚠️ 四棱同向指向 C,但 C 改的是 p1 security 路径上的失败上报行为,⇒ 仍应走独立评审卡,⛔ 不适合作为 #13636 的搭车修改 —— 这也正是该 dev ⛔ 未实施的理由。
Re-check
git grep -n "DURABILITY_CRITICAL_CALLEES" origin/main
git grep -n "persistAuditTrailRow" origin/main -- packages/plugins/plugin-audit/src
git show origin/main:packages/plugins/plugin-audit/src/audit-writers.ts | grep -n "organization"
Dedup — declared WEAK
⚠️search_issues free-text is recorded in #14743 as returning 0 for terms present in open issue titles with incomplete_results: false, so ⛔ a zero from it supports no negative. Whoever grades this should re-run with a keyword pass.
Refs: #13636 / PR #14923 (where it surfaced) · #13491 (execution point 3) · #9516 (the missing-stamp bug on these exact lines) · #8844 (the derive-or-refuse machinery).
Filed unassigned and ungraded by the
domain:engineexecution seat, carrying an open question #13636's dev raised and deliberately did not implement. ⛔domain:*, priority and type are triage's. The fix面 isplugin-audit, which is thedomain:serviceslane — ⛔ never repaired from this lane.Filed as a card, not left in a dispatch report, because a cross-seat request that lives only in a report is invisible to that lane's candidate query, sweep and ageing alarms.
How it surfaced
PR #14923 (#13636) admits
sys_audit_loginto the #8844 derive-or-refuse machinery under the newconditionalverdict. Admission makes the object stricter, which is the ruled intent. Its writers now declare their legitimately org-less cases explicitly.One population is deliberately left undeclared, and that is correct on the merits: case 2 of
audit-writers.ts's own enumeration — an audit row whose subject has an organization column whose value is NULL, written under a system context on a walled install. It is left to refuse because at that call site it is indistinguishable from the missing-stamp defect; #9516 was exactly that bug, on those exact lines.The consequence, which is the actual subject of this card
That refusal (
SystemWriteOrganizationRequiredError) lands inside plugin-audit's best-effort swallow-and-report catch.⇒ ⭐ The outcome is a lost audit row, not a visible failure — and the row that is lost is precisely the audit record about a defective row. The control gets sharper and the evidence disappears at the same moment.
Three directions, as the dev costed them
isSystem写入是否在租户审计控制范围内?——#13178 类级装置(A/B/C)的共同前置,从未被裁过 #13491's execution point 3 says what is added can only be a refusal or a warning, and a NULL organization column on a walled install is itself the defect class that ruling exists to find. Cost: the audit row is silently lost, because the refusal is swallowed.SystemWriteOrganizationRequiredErroron an audit write report through the durability-degradation channel plugin-audit already owns —persistAuditTrailRowis registered inDURABILITY_CRITICAL_CALLEESfor exactly this class of loss — rather than being caught as an ordinary write failure.四棱分析(维护者裁决用)
Re-check
Dedup — declared WEAK
search_issuesfree-text is recorded in #14743 as returning 0 for terms present in open issue titles withincomplete_results: false, so ⛔ a zero from it supports no negative. Whoever grades this should re-run with a keyword pass.Refs: #13636 / PR #14923 (where it surfaced) · #13491 (execution point 3) · #9516 (the missing-stamp bug on these exact lines) · #8844 (the derive-or-refuse machinery).