Skip to content

[观察] registerHook 的代码注册面没有 #4281 那道校验:object: '' 静默变全局;allow 与 exclude 完全抵消时静默永不触发 #6573

Description

@qq9340100

发现于 #5928 的实施(PR 见该单)。观察级:今天没有调用方能触发,不是在飞缺陷。

事实

#4281(hook-empty-target-not-wildcard)把「空目标不是无目标」关在了两处:packages/spec/src/data/hook.zod.ts 的 authorable HookSchema.object refine,以及 packages/objectql/src/hook-binder.tsnormalizeObjects。两处都在元数据路径上。

engine.registerHook(event, handler, { object }) 这条代码路径不经过其中任何一处。匹配逻辑对 object 做的是真值判断(#5928 之前 triggerHooksif (entry.object),hasHooksForif (!entry.object) return true,#5928 收敛后的 hookMatchesObject 按行为守恒保留了同一判断),于是:

#5928 新增排除面后,同一类「注册期可静态判定为无意义」的形状还多了一个:

为什么判为观察级

全仓 registerHook 调用方传的都是字面量常量('sys_user''sys_comment'DELEGATION_OBJECT 等),没有任何调用方传入可能为空的计算值,因此今天无人能触发。#5928 的 PR 里已把 object: '' 的现有读法原样钉住并注明是保留而非认可(hook-exclude-objects.test.ts),避免后来者在无意中翻转它。

为什么不在 #5928 里顺手改

翻转 object: '' 会把一个「对所有对象触发」的 hook 静默变成「对任何对象都不触发」—— 方向相反的静默失效,且发生在一个讲另一个契约面的 PR 里。正确的做法与 #4281 一致:注册期响亮拒绝(而不是改变匹配读法),这是一个独立的契约决定,值得单独评估。

可能的处置(供分诊)

  1. registerHook 里对 object 施加与 excludeObjects 同款的拒绝(空名 / 空白成员),消息沿用 fix(spec,objectql)!: hook 的空目标不再被静默放大成通配符 #4281 的措辞;顺带处理 allow 与 exclude 完全抵消的永不触发形状。
  2. 维持现状,仅保留 hook 注册契约只能表达「命中这些对象」,无法表达「全局但排除这些对象」—— #5860 因此在 plugin-audit 内无法落地 #5928 已加的钉子。

倾向 1:该面新增拒绝对现有调用方零影响(全是字面量常量),且把两条 ADR-0078 形状一次关掉;但它改变了代码注册面的严格度,属于契约决定,应由维护者定。

Refs: #4281#4001#5928、ADR-0078

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions