Repository navigation
[17.0-rc2验收] analytics: 不存在的 dimension 500(泄漏 SQL / SQLITE_ERROR)而不是 400 指名字段 —— #4437 只给 measure 加了闸门,dimension 侧对称缺口仍在 #5520
Copy link
Copy link
Closed
Labels
Description
Activity
分诊:
pm:queue+domain:services。- 落点锚定:正文落点分析已核 ——
packages/services/service-analytics/src/analytics-service.ts的ensureCube()只有 measure 侧的assertMeasureFields三处调用;origin/main 现查assertDimensionFields零命中,dimension 侧闸门确实缺失,前提成立。修形状照 analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437 的 measure 闸门对称补齐(400 INVALID_FIELD+ 指名字段 + 可用 dimension 列表);dataset 面回显生成 SQL 的泄漏属本单范围。 - 查重:analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437(closed,只覆盖 measure)、analytics 的 filter 拒收到不了调用方:service 侧多数拒收没有 ADR-0112 信封,REST 面又用 message 正则嗅探,一律答 500 #5352 / PR fix(analytics,rest): analytics 的 filter 拒收带上 ADR-0112 信封,REST 面先读信封 —— 400 INVALID_FILTER 而不是 500 (#5352) #5366(信封读取通路)、analytics dataset 路由的 message 正则兜底没有退休时间表:六族拒收仍靠措辞分类,改一个字就换一个 HTTP 码 #5367(message 正则六族)均不覆盖本缺口,正文论证核验成立;同为 service-analytics 的 analytics 的
string[]值往返对字符串比较数也有损:{code: {$eq: '007'}}绑成数字7、'null'绑成真 NULL、'true'绑成1—— 文本列静默取到错行 #5526/止血(service-analytics):recoverNumber只还原规范数字串 ——'007'/'1.50'这类保留原写法的字符串比较数不再被降级成数字 #5528(字符串比较数绑定)不同缺陷。 - 严重度:按发单人分析维持 p2(数字无损,撞点在 Studio 预览/手写查询/外部调用方),不动 priority 标签。
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- 落点锚定:正文落点分析已核 ——
认领(services 车道 PM 派发,
session_01BWS4heBoAitLmzCLhcYdbK)- 分支:
claude/issue-5520-dimension-field-gate - worktree:
../objectstack-issue-5520(dev 子代理按 worktree-first 自建) - 文件面:
packages/services/service-analytics/src/analytics-service.ts(ensureCube补 dimension 侧闸门,对称 analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437 的assertMeasureFields)、同包测试(对称measure-source-field-gate.test.ts)、.changeset/*.md。dataset 面 SQL 回显泄漏:若其构造点在本包(executor 错误 message)则一并处置;若在packages/rest信封层则按扩面申报或出 finding,不静默扩权。 - 串行约束:本单占 service-analytics 槽位(前序 analytics 的
string[]值往返对字符串比较数也有损:{code: {$eq: '007'}}绑成数字7、'null'绑成真 NULL、'true'绑成1—— 文本列静默取到错行 #5526/PR fix(service-analytics): 过滤值按作者的类型传递,不再降级成 string[] (#5526) #5634 已 merged);[17.0-rc2验收] analytics: 带 measure-scoped filter / derived 度量的 dataset 查询,响应 fields 丢失维度描述符 → 表头回退成原始维度名(如 "owner" 而非 "Owner") #5537 与本单同文件,排在本单落地之后。analytics dataset 路由的 message 正则兜底没有退休时间表:六族拒收仍靠措辞分类,改一个字就换一个 HTTP 码 #5367(rest 正则兜底)/observation:inferCube仍把数组where当「不是筛选」跳过 —— #5334 之后这个!Array.isArray守卫已经过时 #5353(inferCube)不在本单范围。
Generated by Claude Code
- 分支:
PM 复核:ACCEPT — PR #5667(session_01BWS4heBoAitLmzCLhcYdbK 车道)
- 前提重验成立(三条复现在测试双上一字不差重现;
phone未声明真实字段可分组确认为既有契约且有双路守卫用例 —— 派发红线落实)。 - 闸门与 analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437 逐条对称:信封、三出口、registry 不留痕、四档 stand-down、点号关系穿越不判(
owner.region不被诬告)、建议列表减法防错别字回荐、双错先答 measure。 - 两处扩面均按授权通道处置并显著申报:(a)
timeDimensions— 同一cube.dimensions袋、同一lookupMember、同缺陷 param 变体,判定属本单范围,无需拆单;(b)rest-server.ts一行 — 回显构造点在 knex message(仓外),收窄只能在信封处;所做的是补上 analytics /query 未做 cube 存在性校验,未注册名直达驱动当表名;且错误路径原样回显驱动 SQL(#3770 同类,另一子系统) #3867 共享谓词在本路由的缺失应用而非新规则,status/code/analytics 的 filter 拒收到不了调用方:service 侧多数拒收没有 ADR-0112 信封,REST 面又用 message 正则嗅探,一律答 500 #5352 分支/analytics dataset 路由的 message 正则兜底没有退休时间表:六族拒收仍靠措辞分类,改一个字就换一个 HTTP 码 #5367 正则名单零改动且有回归钉住。采纳。 - 反向验证抓到一例假绿(信封收窄掩护「无 SQL」断言),改强为双条件断言后得到预测方向 —— 连同「REST 套件吃构建产物」的坑一起写入文件头注,处置正确。
- 927 + 745 + 1428 + dogfood 真实接线全绿;DEBT 零新增(拒抄 TS2339 债);两包 patch changeset。
- out-of-scope:analytics:
where里点名不存在的字段仍然一路到驱动 —— #4437(measure)/ #5520(dimension)之后,filter 面是同一个缺陷剩下的第三个 param #5669(同族第三 param:query.where无闸门)搜重后立单、unassigned、无 pm:queue,交分诊 Routine —— 处置正确。
处置:CI 全绿后转 ready 并开 auto-merge 进队;落地后按同文件串行派 #5537。
Generated by Claude Code
- 前提重验成立(三条复现在测试双上一字不差重现;
现象
analytics 查询里,一个引用了不存在字段的 dimension 会一路走到 SQL,被驱动以
no such column打回,调用方拿到 500 —— 裸 driver 错误码上线,dataset 面还把生成的 SQL 原文回显给调用方。这正是 #4437 为 measure 修好的那个 ADR-0112 违背("a driver error class should never be theerror.codefor a caller-shaped mistake"),但 #4437 的修复只覆盖了 measure,dimension 侧的对称缺口从未被堵。对照组(同一类错误,measure 侧)已经被 #4437 修成
400 INVALID_FIELD并指名字段 —— 所以这是一个纯粹的不对称:同样是"查询里点名了对象没有的字段",measure 得到干净的 400,dimension 掉进 500。复现(hotcrm@0899b4f + @objectstack 17.0.0-rc.2,SQLite file 驱动)
两次复现一致。①②③ 均稳定。
期望 vs 实际
400 INVALID_FIELD+field/object/param,并列出可用 dimension)—— 就是 analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437 给 measure 定的那个形状。no such column以 500 上线;dataset 面还额外泄漏生成的 SQL 原文。落点分析(读源码
/home/user/objectstack@cd2efe6,已领先 rc.2)packages/services/service-analytics/src/analytics-service.ts的ensureCube()(L982)在三处调用assertMeasureFields(L999 / L1039 / L1047)校验 measure 源字段 —— 这是 analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437 的修复。但整个ensureCube没有任何assertDimensionFields一类的对query.dimensions的校验:dimension 名直接进入 strategy →GROUP BY <name>→ 驱动no such column。assertMeasureFields(L1079,即 analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437 的闸门)会err.code='INVALID_FIELD'; err.status=400,所以 measure 侧能被正确分类;dimension 侧走的是驱动抛出的SQLITE_ERROR,既无 4xxstatus也不落在 dataset REST 路由的 message 正则名单里,于是落到500 ANALYTICS_QUERY_FAILED兜底(packages/rest/src/rest-server.tsL6467-6491 的信封分支只对已带 4xx status 的错误生效;②message 正则名单不含no such column)。dimensions:["phone"]→ 200,按 phone 分组),与 measure 侧number_of_employees→SUM的自动推断对称 —— 所以缺陷只在字段不存在这一支的错误处置,与 analytics: a measure naming a missing field 500s with SQLITE_ERROR instead of a 400 naming the field #4437 描述的 measure 缺陷同形。查重
measure-source-field-gate.test.ts)、交接评论均只覆盖 measure,dimension 从未在其 scope 内。本单是它遗留的对称缺口,引用旧单。INVALID_FILTER/400):不覆盖本单 —— 它修的是"生产方已带信封但 REST 丢弃"的通路;dimension 侧的驱动no such column根本不带信封,补了信封读取也没用,得先给 dimension 加闸门。throw new Error(...);dimension 的裸no such column不在其列。严重度
建议 p2。无数字影响(所有 dataset/dashboard/report 的聚合数字在 rc.2 上对账全部正确);HotCRM 出厂 metadata 由
pnpm validate(ADR-0021)静态兜住,生产 dashboard 运行时不会撞上。真正会撞的是 Studio 预览、手写查询、外部 API 调用方 —— 他们拿到的是 500 + 泄漏的 SQL,而不是一句指名 dimension 的 400。环境行:
hotcrm@0899b4f + @objectstack 17.0.0-rc.2;落点源码@objectstack cd2efe6(领先 rc.2,缺口在该 commit 仍在)。