Skip to content

[lint/automation] 嵌套 region(try_catch / loop / parallel)里的节点对 flow 规则不可见 —— 两条 gating error 静默失效,第三条降级为 warning #4380

Description

@os-zhuang

现象

packages/lint 里所有走 flow 节点的规则都只遍历顶层 flow.nodes。一旦作者把同一个节点挪进 try_catch / loop / parallel 的嵌套 region,检查就整体失效。

同一组「坏节点」放在顶层 vs 放进 try_catch.config.try.nodes,实测(对着已构建的 @objectstack/lint dist):

规则 严重级 顶层 嵌套
flow-node-write-unknown-field(#4369/#4374) error 1 0
flow-update-readonly-field(#3425) error 1 0
approval-approver-type-unknown 等(#3583) error/warning 1 0
flow-template-unknown-field filter 位置(#3810) error 1 1,但降级为 warning

最后一行是最隐蔽的一种失败。validateFlowTemplatePaths 因为对整个 config 做递归 string-leaf 扫描,碰巧还能看见嵌套节点里的 token,但 collectNodeLeaves 只在节点 config 的顶层拆分 filter 键,嵌套后 filter 位置信息丢失:

FLAT     error  	flow "f" node "get_record"	flows[0].nodes[1]
NESTED   warning	flow "f" node "try_catch"  	flows[0].nodes[1]

#3810 那条「条件被抹掉会放宽查询,运行时直接拒绝执行该节点」的 gating 判断,变成一行黄色 advisory,而且定位到外层 try_catch 而不是真正出问题的 get_record。这正是那条规则的严重级分档所要防止的事。

根因

FlowRegionSchema(packages/spec/src/automation/control-flow.zod.ts:79)持有完整的 nodes: z.array(FlowNodeSchema).min(1),一共四个嵌套槽位:

节点类型 槽位
try_catch config.tryconfig.catch
loop config.body
parallel config.branches[](ParallelBranchSchema)

而每条规则都是同一行:

const nodes = Array.isArray(flow.nodes) ? (flow.nodes as AnyRec[]) : [];

出现在 validate-flow-node-writes.ts:184validate-readonly-flow-writes.ts:137validate-flow-template-paths.ts:248/266/290validate-approval-approvers.ts:154validate-expressions.ts:132。没有一条递归进 region。

(validate-flow-trigger-readiness.ts:72 找的是 start 节点,按定义只在顶层,不受影响。validate-expressions.ts 在结构上属于同一类,但我的探针在顶层也没触发它,未确认。)

影响面不是假设

app-showcase 现在就有一个 update_record 落在 catch region 里(examples/app-showcase/src/automation/flows/index.ts:967-978,写 sync_status / sync_error)。那个节点字段是对的,所以不是线上 bug —— 但它从未被检查过,而 os validate 通过给了它「已检查」的假象。「在 catch 分支里用 update_record 记录失败」恰恰是这个 region 最典型的用法。

建议

不要三处各写一遍遍历 —— 那正是会漂移的形状(#3583 建套件、#4330 收拢 system-fields 都是在收拾这个)。

  • packages/lint 出一个共享的 flow 节点游走器,产出 { node, path, container };
  • path 必须能表达嵌套位置(flows[0].nodes[1].config.catch.nodes[0].config.fields.stagee),否则 finding 定位不到真正的节点 —— 上面 NESTED 那行报在 flows[0].nodes[1] 就是这个问题;
  • 上述规则改用它;validateFlowTemplatePaths 还需要让 filter 位置判定跟着嵌套走,否则 gating 降级问题不会因为「能看见」而自动修好;
  • 一条测试钉住四个槽位都被走到 —— 参照 validate-flow-node-writes.test.ts 里对着 spec schema 行为式推导的 partition 测试,让新增的嵌套槽位无法静默漏掉。

版本

@objectstack/*@17.0.0-rc.0,main @ 38182ffb8。发现自 #4369 / #4374(flow write-set gate)的收尾核查。

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions