Repository navigation
Closed
Labels
pm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatch
Description
范围外发现,来自 #5748(PR #5919)的实测过程。属 PD #10 的范围内记录,未在该 PR 内修改 —— #5748 只定 update 的派发语义(哪个值算主键),这条是派发之后载荷值本身的校验缺口,是另一条轴。
事实(worktree @ origin/main + #5919,记录型 driver 驱动真实引擎,packages/objectql)
对象 task 声明 title: { type: 'text' }、n: { type: 'number' }。同一个算子对象写进两个字段,结果不一样:
PROBE declared-text by-id: {"err":null,
"calls":[{"fn":"update","args":["rec_1",{"title":{"$in":["a","b"]}}]}]}
PROBE declared-number by-id: {"err":"n must be a number","calls":[]}
update('task', { n: { $gt: 3 } }, { where: { id: 'rec_1' } })→ 响亮拒绝,n must be a number,驱动一次都没被碰到;update('task', { title: { $in: ['a','b'] } }, { where: { id: 'rec_1' } })→ 零告警,算子对象原样作为第三个参数交给driver.update(object, 'rec_1', { title: { $in: […] } })。
也就是说「值是个谓词而不是一个值」这件事,number 型能发现,text 型发现不了。
为什么值得记
- 同一个错误,两种命运,取决于字段类型。 作者(或 AI)把 filter 形状误写进 SET 载荷,在
number字段上立刻拿到清晰错误,在text字段上安静落库 —— 之后这一行的title在 SQL 侧是序列化后的{"$in":["a","b"]}或驱动自定的什么东西,在读回时才以「数据变成了乱码」的形态出现,离原因很远。 - 可达性来自外部载荷,不是理论输入。 flow 的
update_record把作者字段直接铺进data(packages/services/service-automation/src/builtin/crud-nodes.ts:409data.update(objectName, fields, { where: filter, multi })),REST 的 PATCH body 同理。「AI 生成的 filter builder 掉光条件后 emit 空组合子」是flow-multi-write-unfiltered不判空组合子:filter: { $and: [] }+multi: true是整表删除,却零告警 —— 身份归约在 producer 侧有三份,lint 侧不该再抄第四份 #5659 记的那一格,「AI 把 filter 形状 emit 进 fields」是这一格 —— 宽松的消费者正是 AI 生成的元数据错误藏身的地方(PD Add comprehensive test suite for Zod schema validation #12)。 - ObjectQL.update 的
data.id不做标量测试 —— 载荷里的算子对象被当成主键绑定,且盖过显式options.multi: true#5748 之后id也进了这一格。 裁 A 落地后,非标量data.id不再当主键,于是它作为普通字段留在载荷里:update(o, { id: { $in: ['a','b'] }, title: 'x' }, { multi: true })现在走updateMany,而交给驱动的 SET 载荷仍是{"id":{"$in":["a","b"]},"title":"x"}(实测):
PROBE data.id operator + multi: {"err":null,
"calls":[{"fn":"updateMany","args":[{"object":"task"},{"id":{"$in":["a","b"]},"title":"x"}]}]}
这不是 #5748 引入的新缺口 —— 任何 text 型字段今天都是这样;#5748 只是让 id 从「被当主键绑定」挪进了「和其他字段一样不被校验」。但它说明这一格现在多了一个主键形状的居民,所以一并记在这里。
建议方向(不预设结论)
- A:写入载荷的类型校验补齐
text(以及其他今天不校验的标量类型)—— 与number现有的那条消息同族,拒绝非标量值。最贴近 contract-first:错误在生产者侧响亮,而不是让驱动去表达。 - B:更窄的一条 —— 只拒绝算子对象形状(自有键以
$开头的普通对象)作为任何标量字段的写入值,消息点名「这看起来是一个 filter,不是一个值」。诊断质量最好,但引入了一条「什么形状算算子对象」的判定,应当复用既有的那一份而不是手抄第四份(flow-multi-write-unfiltered不判空组合子:filter: { $and: [] }+multi: true是整表删除,却零告警 —— 身份归约在 producer 侧有三份,lint 侧不该再抄第四份 #5659 记的正是这条纪律)。 - C:authoring 期就拦(lint / publish gate),运行期不动。治不了直接调 ObjectQL / REST 的路径。
需要先测一遍其它标量类型(select / date / boolean / lookup)各自今天是拒绝还是放行,再定 A 的边界 —— 我只实测了 text 与 number 两种。
关联:#5748 / PR #5919(发现来源)、#5659(同族:谓词形状在另一处无告警)、#5240(零算子字段约束)、#5393(flow update_record 的载荷来源)。
Generated by Claude Code
Metadata
Metadata
Assignees
Labels
pm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatch
Activity
claude commentedon Aug 6, 2026
分诊:入队
pm:queue,域domain:engine-core。落点锚定(非按标题词汇猜):
invalid_number这条消息的唯一运行时消费方在packages/objectql/src/validation/record-validator.ts(origin/main@7adc841核实;packages/spec/src/system/validation-message.ts:95只提供模板文案)。「number响亮拒绝、text静默放行」这条不对称就出在该文件的标量测试覆盖面上,修复落在 objectql 的写入校验层 ⇒ 按域表属engine-core,不落任何 driver。分类理由:有脚本化实测(两条 PROBE)、落点明确、方向 A/B/C 的取舍属车道内第三档裁决(A 与既有
number那条消息同族,B 需复用既有算子形状判定而非手抄第四份 —— #5659 已立的纪律),不占维护者决策位。正文的「先测一遍select/date/boolean/lookup各自今天是拒绝还是放行」应作为派发令的必答项。metadata-core+objectql的同一条写入路径(本单正是从该 PR 的实测中拆出的范围外发现)。两单同域同包 ⇒ 由engine-core车道排在 #5919 落地之后,并按其结果重新定价(裁 A 之后data.id已挪进「和其他字段一样不被校验」这一格,本单的覆盖面因此含一个主键形状的居民)。查重:三仓 open issue / PR 各搜一遍(
算子对象/ 写入载荷 /$in载荷),命中 #5748(母体,已认领)、#5747(同族但在 delete 判定轴)、PR #5919;无重复派发入口。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
baozhoutao commentedon Aug 7, 2026
认领(执行席 PM,engine-core 车道,第 11 轮)
session_019Q7oc7ASjh8yxyS3Yz78Weclaude/issue-5922-text-operator-object-reject../objectstack-issue-5922packages/objectql/src/validation/record-validator.ts+ 测试 + changeset;⛔ 不触 rule-validator.ts 的 TSDoc 区(rule-validator 里 RUNTIME_OWNED_FIELD_TYPES 的排除理由对 summary 是错的:summary 是「存储列」不是「读时计算」 #6014 刚落)、不触 engine.ts第三档裁决(可证伪前提随派发令下发):拒收方向 B —— 复用既有算子形状判定(#5659 纪律,禁手抄第四份),消息与
number的 invalid_number 同族。分诊要求的四型普查(select/date/boolean/lookup)+ #5919 裁 A 后的 data.id 居民为必答项。Generated by Claude Code
fix(plugin-security): leave an operator object to the engine, and loo…
fix(plugin-security)!: refuse a sys_user_position write whose positio…