Repository navigation
Description
Found while implementing #4649 (PR #4761). Filed unassigned, not fixed there — #4649's ruling scoped itself to the object-level predicates, and widening it in the same PR would have mixed two blast radii.
What is still fail-open
packages/objectql/src/validation/rule-validator.ts:
checkFormat— aregexthatnew RegExp(...)throws on is logged and skipped:Validation rule '<name>' has an invalid regex — skippedcheckJsonSchema— a schemaajv.compile(...)throws on is logged and skipped:Validation rule '<name>' has an uncompilable JSON Schema — skipped
Both are the exact shape #4649 was filed about: the rule is declared, appears in the metadata, appears in any "what protects this object" listing, and enforces nothing — the only signal being a WARN in a log nobody reads. #4761 flipped the CEL predicates (script / cross_field / conditional.when) to fail closed and left these two deliberately unchanged, with a test pinning that they still fail open so the gap is visible rather than assumed closed:
packages/objectql/src/validation/rule-fail-closed.test.ts › #4649 — unchanged neighbours.
Why it is a smaller problem than #4649 was, but still a problem
A broken regex / schema is static — it is broken for every record, from the moment it is authored, not only for records of a particular shape. So it is far more likely to be noticed in dev than #4649's data-dependent fault was. That is an argument about when it is noticed, not about whether the rule enforces anything: on a deployed system it enforces nothing, silently, exactly as before.
Two ways to close it, and they are not exclusive
- Authoring/publish time (preferred, contract-first). A regex that does not compile and a JSON Schema ajv rejects are both decidable without a record. Rejecting them at publish —
packages/lint— kills the rule class outright and never risks bricking a running deployment. This is the "declared = enforced" fix rather than a runtime policy fix. - Write time, to match Script validation rules are silently skipped when their predicate fails to evaluate — fail-open is the wrong direction for a validation #4649. Reuse
unevaluableRuleErrorfromrule-validator.ts: reject withreason: 'unevaluable', naming the rule. Note the blast radius differs from Script validation rules are silently skipped when their predicate fails to evaluate — fail-open is the wrong direction for a validation #4649's in an important way — an unevaluable predicate rejects only writes whose data triggers the fault, whereas a broken regex would reject every write touching that field, for as long as the bad metadata is deployed. That is a strong argument for doing (1) first, and only then deciding whether (2) is still worth having as a backstop.
Acceptance sketch
- A
formatrule withregex: '(['is rejected at publish/lint with the rule name and the regex error. - Same for a
json_schemarule whose schema ajv cannot compile. - If (2) is also taken: the
#4649 — unchanged neighbourstests inrule-fail-closed.test.tsflip, and the module header's "Deliberately NOT changed here" paragraph is updated in the same PR — it is the record of this decision.
Activity
claude commentedon Aug 3, 2026
🔒 认领:PM 循环第 5 轮(跨域借用 —— 修复落点经裁定移至
packages/lint,domain:devx)会话:
session_01NrmBxj8rK2uGCnh9aipjwX(账号xuyushun441-sys,登记车道 {engine, services})分支:
claude/issue-4762-static-rule-publish-gateWorktree:
objectstack-issue-4762域:原标
domain:engine,裁定走 issue 路线 1 后落点为packages/lint—— 按 Domain lanes 借用条款认领:devx 车道 PM 未认领本单、文件面全量申报如下、全局在飞检查已跑。文件面:
packages/lint/src/validate-expressions.ts(或该包内更合适的规则校验入口,以现状为准)+ 同目录测试;packages/objectql/src/validation/rule-validator.ts零改动(路线 2 本单不做,既有 fail-open pin 保留)方案裁定:路线 1(publish 期拒绝)本单全量;路线 2(运行时 fail-closed)不做,理由用 issue 自己的话:坏 regex 的运行时拒绝会砸掉该字段全部写入,先关作者期大门;运行时背档是否还需要,留维护者定(不挂标签,低紧急度)。
⛔
spec/**零改动;releases/ 零触碰。@xuyushun441-sys 的 devx 会话若对本借用有异议,以你为准,我让行。Generated by Claude Code
claude commentedon Aug 3, 2026
🔁 接手记录:原 dev agent 因会话额度耗尽被杀(不可恢复),worktree
objectstack-issue-4762与未提交改动完好。按 worktree 接手协议派新 agent 继续 —— 同一认领、同一分支,本条为交接记录,原认领评论继续有效。会话:session_01NrmBxj8rK2uGCnh9aipjwX。Generated by Claude Code
fix(lint): cap `conditional` nesting depth in the rule-compilability …
claude commentedon Aug 4, 2026
✅ 验收通过 —— PR #5027;落地暂被 #5032 挡住(非本 PR 之过)
对照实际 diff 复核(9 文件,+880/-7,全部
packages/lint+ changeset + 3 行 lockfile;⛔ objectql / spec / protocol.ts / releases 零触碰 —— 运行时 #4649 pin 与模块头原样保留,逐一核实):ajv进 LAZY_DEPS(内核启动路径契约);MAX_RULE_NESTING_DEPTH=16防r.then = r挂死 lint(os lint 不 parse,walker 吃作者模块的任意对象)。json_schemavalidation rule'sformatkeyword is silently IGNORED — ajv runs withoutajv-formats, soformat: 'email'enforces nothing #5029(ajv 无 ajv-formats,format: email编译通过但不校验 —— 本 PR 的选项同参性天然抓不到「编译得过」的这半,单开正确);Validate Package Dependenciesis red onmain— 8 FIXABLE OSV advisories (undici / hono / fast-uri), so every PR inherits a red required-ish check #5032(见下)。落地条件:唯一红检是⚠️ 不可只 rerun —— rerun 复用旧 merge ref,拿不到修好的 lockfile),绿后入队。
Validate Package Dependencies,已证实是 main 侧的过期基线(该工作流 main 上每周日定时跑,上次绿于 OSV 通报发布之前;只有碰 lockfile 的 PR 会即时撞上)。#5032 修复合入后,本分支 merge origin/main 重跑该门禁(Generated by Claude Code
fix(lint): regex/JSON Schema 编译不过的校验规则改在发布期拒绝 —— 声明了却什么都不拦的两个静态产物 (ob…
fix(objectql,lint)!: `json_schema` 规则的 `format` 关键字真正生效(注册 ajv-format…
feat(lint): refuse a MISSPELLED `format` in a `json_schema` validatio…
docs(validating-metadata): the four-door table records the object run…