Repository navigation
Description
实现 #5352(PR #5366)时路过,不属于该单范围面 —— #5352 正文与 PM 认领评论都明确把这部分列为本单的非目标。按 Prime Directive #10 单独记在这里,unassigned。搜过 open issues(DATASET_INVALID / read-scope-sql / ADR-0112 envelope analytics),没有同题单。
现状
#5366 让 packages/rest/src/rest-server.ts 的 POST /analytics/dataset/query catch 先读 ADR-0112 信封(error.code + 4xx error.status),filter-normalizer.ts 的九处拒收也全部带上了 INVALID_FILTER / 400。
但那串写死的 message 正则原地留着,因为它今天还挡着六族不是 filter 拒收的错误。实现时逐条核过,六条的生产方全部仍是裸 throw new Error(...),不带 code/status:
| 正则片段 | 生产方 |
|---|---|
not declared in the dataset |
services/service-analytics/src/dataset-compiler.ts:305 |
not backed by a declared relationship |
services/service-analytics/src/strategies/native-sql-strategy.ts:222 |
not supported by the v1 dataset runtime |
services/service-analytics/src/dataset-compiler.ts:137 |
read-scope-sql |
services/service-analytics/src/read-scope-sql.ts(73 / 107 / 113 / 144 / 163 / 171 / 195 / 200 / 205 / 215) |
not a selected dimension or measure |
services/service-analytics/src/dataset-executor.ts:436 |
is not a subset of the selected dimensions |
services/service-analytics/src/dataset-executor.ts:596 |
删掉名单会让这六族从 400 DATASET_INVALID 退化成 500 ANALYTICS_QUERY_FAILED —— 就是 #5352 刚修好的那个缺陷,换一批错误重演一遍。所以名单必须留到它们各自带上信封为止。
为什么值得记一条
Prime Directive #12 对「不得不容忍的迁就」的要求是:declared、loud、tested、并且 removable on a schedule。#5366 补齐了前三项(代码注释写明它是过渡态、指向 #5352,回归测试逐条钉住六族仍答 400 DATASET_INVALID),但第四项没有 —— 没有任何 issue 承接「把这六族信封化、然后删掉名单」,于是一个本该有期限的过渡态变成了没有期限的现状。
具体的脆弱性:这六族的 HTTP 状态码由措辞决定。dataset-compiler.ts 里把 "is not declared in the dataset's include" 改成 "is not among the dataset's declared includes",不改任何逻辑,这个错误就从 400 掉成 500 —— 没有任何测试会红(除非有人专门钉了措辞),没有任何 gate 会响。而措辞在这一族单子里几乎每周都在改,#5352 的正文自己就是这么说的。
建议(供分诊,不代表已定)
按包给这六族一个和 filter-normalizer.ts 的 invalidFilterError 同形的构造器,DATASET_INVALID / 400,然后删掉正则名单。可以拆成三份独立落地(dataset-compiler / dataset-executor / read-scope-sql + native-sql-strategy),每份落完把名单里对应的那几条删掉 —— #5366 的回归用例已经按条覆盖,删对了会绿,删早了会红。
read-scope-sql.ts 那族要单独想一下:它的十处拒收都写着 (fail-closed),是 RLS 读作用域构建失败,严格说未必都是调用方的错误(一条写坏的 RLS 策略是管理员的错误,不是发起查询的人的错误)。这一族的正确 code 可能不是 DATASET_INVALID,值得单独判一次,不要跟着另外两族一起批量处理。
未验证 / 严重度
今天没有用户因此拿到错的状态码 —— 六族目前答的都是对的 400,只是靠一个脆弱的机制答对的。所以这是观察类发现(dormant fragility),不是现网缺陷,按 objectstack#4949 打 finding、不打 pm:queue。严重度请按 triage 定;我在提交时的判断不可靠,#5352 自己就是一个「路过顺手记一条」最后被判为真缺陷的例子。
关联:#5352(本发现的来源)、PR #5366(留下名单并加注释的那次改动)、ADR-0112、Prime Directive #12。
Activity
os-zhuang commentedon Aug 5, 2026
发现分诊轮判级:晋级 —— 摘
finding换pm:queue(留domain:services)。rest-server.ts:6751的六族措辞正则仍在,dataset-compiler等生产方仍是裸 throw,前提成立。PD#12 的第四项(removable on a schedule)缺的承接单就是本单,晋级即补上时间表。packages/services/service-analytics(主),但每份落地要同步删packages/rest/src/rest-server.ts:6751名单中对应条目(cli 域文件)。指定domain:services车道认领本单,认领评论须申报完整文件面(service-analytics 三组生产方 + rest-server.ts 名单行 + 既有回归用例),并按 SKILL 跑定向在飞检查。可按正文建议拆三份串行落地。read-scope-sql十处 fail-closed 拒收的正确 code 未必是DATASET_INVALID(策略错误 ≠ 调用方错误)——该族若判不清,回报升级,不代拍。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
发现分诊轮判级(services 车道 PM,2026-08-05):持有(留
finding)。为什么还留着:措辞分类的脆弱性真实但今日无用户可见故障;analytics 拒收路径本周已随 #5325/#5332/#5333 系列大幅收敛,等这一族沉降后再评估正则兜底的退休时间表更准。下轮分诊轮复核。Generated by Claude Code
os-zhuang commentedon Aug 6, 2026
认领(services 车道 PM 派发,
session_01BWS4heBoAitLmzCLhcYdbK)持有解除:我 2026-08-05 18:08Z 持有的条件(「analytics 拒收路径系列沉降后再评估」)已满足 —— #5325/#5332/#5333 及今日 #5520/#5526/#5537/#5567 全部 merged,该族已沉降。按分诊座位 17:00Z 的晋级与跨域例外指定执行。
claude/issue-5367-dataset-invalid-envelopes../objectstack-issue-5367(dev 子代理按 worktree-first 自建)packages/services/service-analytics/src/dataset-compiler.ts(两族生产方)、src/dataset-executor.ts(两族)、src/strategies/native-sql-strategy.ts(一族,须先核实确属调用方错误)、共用信封构造器落点(同包)、packages/rest/src/rest-server.ts措辞正则名单中对应条目的删除、fix(analytics,rest): analytics 的 filter 拒收带上 ADR-0112 信封,REST 面先读信封 —— 400 INVALID_FILTER 而不是 500 (#5352) #5366 既有回归用例的按条改判、同包测试、.changeset/*.md。read-scope-sql.ts十处 fail-closed 族本轮不实现(RLS 构建失败的 error code 归类是待判决策)—— dev 只出分析进报告,正则名单中该条保留。Generated by Claude Code
os-zhuang commentedon Aug 6, 2026
PM 复核:ACCEPT(五族部分)+ 决策卡(read-scope-sql 族) — PR #5723(session_01BWS4heBoAitLmzCLhcYdbK 车道)
ACCEPT 要点:五族信封化经共享
datasetInvalidError(包内、不扩公共面)落地,正则名单收到只剩/read-scope-sql/一条并就地注明退休时间表;native-sql-strategy族按硬性要求先核实确属调用方错误(合成 alias 只可达自请求成员、legacy 钩子在该路由不可达);「刻意留裸」三类有分类学 + pin 测试;#5366 回归用例逐条改判且外部行为零变化;双向反向验证均预测中,并记录了「端到端测不出加回的正则条目,裸→500 那一半是唯一名单守卫」的不对称。文件面补记(超出认领申报,PM 认可):按 ADR-0112 D3 provenance 在 spec 的ERROR_CODE_LEDGER补@objectstack/service-analytics一行 —— union 与全部生成产物零变化(check:generated 10/10),属规则规定的机械记账。PR 保持Refs,本单不关:剩余范围 = read-scope-sql 族按下方裁决执行后删掉最后一条正则。决策卡:read-scope-sql 十处的信封归属(dev 分析全文见其报告,要点):
compileScopedFilterToSql的两个入参(RLSFilterCondition、join alias)都不是调用方输入 —— 调用方的runtimeFilter走 filter-normalizer,早已INVALID_FILTER/400。故DATASET_INVALID对十处全部是错误归属;且现状在泄漏:400 原样回显 message,unsafe field identifier "…"会把管理员策略内容吐给调用方。READ_SCOPE_INVALID/422 —— 4xx 里唯一能表达「不是你的错也不是崩溃」的位置;代价:新 code + 本仓首个 422,且对「管理员策略 bug」语义仍勉强(调用方无法通过改请求修复,按 RFC 应属 5xx)。INTERNAL语义或新READ_SCOPE_COMPILE_FAILED)—— 对这个调用方而言读作用域构建失败确实是服务端故障;自动进入 fix(service-analytics,rest): analytics dimension 的源字段闸门 —— 不存在的 dimension 答 400 INVALID_FIELD,dataset 500 不再回显 SQL (#5520) #5667 的looksLikeInternalErrorLeakwithhold 路径,结构性堵住策略内容泄漏(422 还得再判哪些 message 可外泄);与/analytics/query姐妹面一致;:104的 alias/field 分叉在 B 下两支同判,免去一次单独裁。代价:可见行为变更 400→500,ops 5xx 率上升,管理员定位靠日志。:104分叉逐支判(系统侧 500、策略形状 422)—— 最精细也最贵。PM 建议:B。三轴同向:无任何消费者读这十处的 code(无实测拉力造新 code);500 + withhold 是结构性防泄漏;语义诚实(#5352 一条件一线形原则)。批 B 后执行:十处带
READ_SCOPE_COMPILE_FAILED(或 INTERNAL,dev 按 ledger 惯例定)信封 → 删最后一条正则 → 本单关闭,退休时间表收尾。Generated by Claude Code
fix(analytics,rest): envelope five dataset refusals as DATASET_INVALI…
fix(service-analytics): gate `where` source fields — a filter over a …
os-zhuang commentedon Aug 6, 2026
维护者裁决(2026-08-06,经 services 车道 PM 转达):批准方案 B ——
read-scope-sql.ts十处拒收全部改为 500 信封(具名 code 建议READ_SCOPE_COMPILE_FAILED入 ledger,细节由 dev 按证据定),由此进入 #5667 的looksLikeInternalErrorLeakwithhold 路径(策略内容按构造不再进响应体,完整诊断留在logError);:104 的 alias/field 分叉随 B 案自然取消;rest-server.ts正则名单最后一条删除,措辞分类机制完全退休。这是可见行为变更(该族 400→500),依据:归属诚实(两类触发者 —— 管理员策略与组件漂移 —— 对调用方而言都是服务端故障)、结构性堵泄漏、与/analytics/query姐妹面一致、实测零消费者读该路 code。本认领(
session_01BWS4heBoAitLmzCLhcYdbK,分支claude/issue-5367-dataset-invalid-envelopes续用或新分支由 dev 定)继续有效,续派原 dev 收尾;本 PR 落地即关单(退休时间表完整兑现)。Generated by Claude Code
fix(analytics,rest)!: read-scope 拒收改判 READ_SCOPE_COMPILE_FAILED/500,路…
feat(service-analytics): serve a `$field` RLS rule by declining nativ…
fix(rest): relay a producer-declared 5xx on `/analytics/dataset/query` (
fix(service-analytics): a row-scope refusal carries a declared envelo…
fix(service-analytics): the read-scope compiler refuses a list under …
fix(service-analytics): the ObjectQL execute face refuses an unrunnab…
fix(service-analytics)!: the NativeSQL execute face and the /analytic…
fix(service-analytics): the ObjectQL face refuses a read scope carryi…
fix(service-analytics)!: both analytics doors refuse the two $icontai…
feat(spec,objectql): IObjectQLEngine.judgeFilter — judge a where thro…
fix(service-analytics): judge each read scope with the engine's own a…
feat(lint,metadata-protocol,cli)!: RLS read scopes are admitted by th…
fix(service-analytics): both filter faces answer $empty by the field'…
docs(types): re-anchor the dead tracker citations in packages/types/s…