按 #5009 建议 3 顺带核对了邻居规则。validate-org-axis-red-lines.ts 的四条已在该单清掉;下面这些是同一形状、不同文件 的读法,按 Prime Directive #10 单独记账,不在 #5009 的 PR 范围内。
每一条都对着 spec 实际 .shape 核过。
packages/lint/src/validate-expressions.ts
行
读法
spec 现状
205 / 421
rule.expression ?? rule.predicate ?? rule.condition ?? rule.formula
跨字段校验规则声明的键是 condition。formula / expression 是 validation.zod.ts 里 aliases: { formula: 'condition', expression: 'condition' } 明确按名拒绝 的别名;predicate 连别名都不是。注意这里 canonical 的 condition 排在第三顺位 —— 前两个非法别名优先
414
obj.validations ?? obj.validationRules
ObjectSchema.shape 只有 validations,没有 validationRules
595
rule.condition ?? rule.criteria ?? rule.predicate
SharingRuleSchema 只声明 condition;criteria 正是 sharingRuleUnknownKeyError 里 → condition 的被拒别名(#4984 在另一个 文件里修的就是这一条)
packages/lint/src/validate-security-posture.ts
行
读法
spec 现状
94
obj.sharingModel ?? (obj.security)?.sharingModel
ObjectSchema.shape 有 sharingModel / externalSharingModel / publicSharing,没有 security
118
def.reference ?? def.reference_to
field.zod.ts:331 把 referenceTo / relatedTo / target 等映射为被拒别名 → canonical reference
为什么要记账
两个文件都是 input: 'parsed' 注册的 gating 规则(见 authoring-rules.ts),看到的是 ObjectStackSchema 解析后的产物:stack 根 strip 未声明键,.strict() 子 schema 直接整包拒绝 。所以这些别名 limb 对任何 spec 合法 stack 都不执行 —— 和 #4984 / #5009 完全同一种形状。
危险同样不在漏报(canonical limb 通常也在读),在于:
读代码的人会相信 objects[].validationRules、object.security.sharingModel 是真实的授权/校验面;
validate-expressions.ts:205/421 那条尤其糟 —— canonical 的 condition 排在两个被拒别名之后,只要作者写了被拒的 expression,规则读的就是它(在 normalized 层),而 os validate 会拒掉整个 stack。producer 和 consumer 对同一份元数据给出两套说法。
建议
三处收敛为声明键:condition、validations、sharingModel、reference。
复用 validateOrgAxisRedLines 仍留着三条 spec 合法 stack 到不了的别名分支(objects[].rowLevelSecurity / .rls / permissionSets)—— #4984 修了 sharing 那一半 #5009 落地的结构性 meta-guard:规则源码里从某个 surface 上读的每个键,必须出现在该 surface 自己的 Zod .shape 里(validate-org-axis-red-lines.test.ts 的 READ_SURFACES 表)。那条 guard 是通用的,搬过来即可,并且它扫的是源码 不是行为 —— 不可达分支没有行为可断言,这正是问题本身。
顺带把该 guard 推广成所有 input: 'parsed' 规则共用的一条测试,是更彻底的做法(成本更高,可另议)。
参考
按 #5009 建议 3 顺带核对了邻居规则。
validate-org-axis-red-lines.ts的四条已在该单清掉;下面这些是同一形状、不同文件的读法,按 Prime Directive #10 单独记账,不在 #5009 的 PR 范围内。每一条都对着 spec 实际
.shape核过。packages/lint/src/validate-expressions.tsrule.expression ?? rule.predicate ?? rule.condition ?? rule.formulacondition。formula/expression是validation.zod.ts里aliases: { formula: 'condition', expression: 'condition' }明确按名拒绝的别名;predicate连别名都不是。注意这里 canonical 的condition排在第三顺位 —— 前两个非法别名优先obj.validations ?? obj.validationRulesObjectSchema.shape只有validations,没有validationRulesrule.condition ?? rule.criteria ?? rule.predicateSharingRuleSchema只声明condition;criteria正是sharingRuleUnknownKeyError里 →condition的被拒别名(#4984 在另一个文件里修的就是这一条)packages/lint/src/validate-security-posture.tsobj.sharingModel ?? (obj.security)?.sharingModelObjectSchema.shape有sharingModel/externalSharingModel/publicSharing,没有securitydef.reference ?? def.reference_tofield.zod.ts:331把referenceTo/relatedTo/target等映射为被拒别名 → canonicalreference为什么要记账
两个文件都是
input: 'parsed'注册的 gating 规则(见authoring-rules.ts),看到的是ObjectStackSchema解析后的产物:stack 根 strip 未声明键,.strict()子 schema 直接整包拒绝。所以这些别名 limb 对任何 spec 合法 stack 都不执行 —— 和 #4984 / #5009 完全同一种形状。危险同样不在漏报(canonical limb 通常也在读),在于:
objects[].validationRules、object.security.sharingModel是真实的授权/校验面;validate-expressions.ts:205/421那条尤其糟 —— canonical 的condition排在两个被拒别名之后,只要作者写了被拒的expression,规则读的就是它(在 normalized 层),而os validate会拒掉整个 stack。producer 和 consumer 对同一份元数据给出两套说法。建议
condition、validations、sharingModel、reference。.shape里(validate-org-axis-red-lines.test.ts的READ_SURFACES表)。那条 guard 是通用的,搬过来即可,并且它扫的是源码不是行为 —— 不可达分支没有行为可断言,这正是问题本身。input: 'parsed'规则共用的一条测试,是更彻底的做法(成本更高,可另议)。参考