fix(lint): 删除 validateOrgAxisRedLines 里 spec 合法 stack 到不了的四条分支 (#5009) - #5018
Merged
Merged
Conversation
该规则注册为 `input: 'parsed'`,看到的是 `ObjectStackSchema` 解析后的产物。 #4984 修掉了 sharing rule 字段层的 `??` 别名读法,同一文件里还留着四条同形 分支,读的键 spec 都不声明 —— 逐条对着 schema 的 `.shape` 与 `safeParse` 实测核过: - `cfg.permissions ?? cfg.permissionSets` → `cfg.permissions`。 `ObjectStackSchema.shape` 无 `permissionSets`;stack 根 strip 未声明键, 实测 `safeParse({ manifest, permissionSets: [...] })` 成功但 `data` 里 没有该键 —— 规则看到 stack 之前它已经不存在。 - `cfg.sharingRules ?? cfg.sharing`(两处)→ `cfg.sharingRules`。同上。 - `str(rule.object ?? rule.objectName)` → `str(rule.object)`。 `SharingRuleSchema` 是 `.strict()`,`objectName` 被按名拒绝 ("Unrecognized key(s) on this sharing rule: `objectName`");`object` 又是必填,解析过的规则上不可能缺。 - `asArray(object.rowLevelSecurity ?? object.rls)` 整段遍历(约 20 行) **删除**。依据:`ObjectSchema.shape` 两个键都没有(实测键表里只有 `sharingModel` / `access` / `tenancy` 等,无 `rowLevelSecurity`、无 `rls`), 且 `ObjectSchema` 是 `.strict()` —— 带对象级 RLS 的 stack 在 `os validate` / `os build` 被整包拒绝,报 "Unrecognized key(s) on this object: `rowLevelSecurity`"。对象级 RLS 从来不是可授权面 (`authorable-surface.json` 里只有 `security/PermissionSet:rowLevelSecurity`)。 对任何 spec 合法的 stack,判定结果不变 —— 反向验证:新测试跑在改动前的 实现上,29 条由 `safeParse` fixture 驱动的断言全绿,8 条转红的全部是 (a) 扫源码的 meta-guard,或 (b) 喂非 spec 合法 stack 的新钉子测试。 代价从来不是漏报,是误导:那段死代码连 `objects[N].rowLevelSecurity[M].using` 的诊断 path 都写好了,足以让下一位作者相信对象级 RLS 是真实授权面并照着写 (#5008 差点如此)。别名容忍属于 producer 的拒绝,不属于 consumer(Prime Directive #12)。 meta-guard(#4992 模式),让下一条死分支在 review 前就红: - declared-key guard:规则源码里从 stack / permission set / RLS policy / object / sharing rule 上读的每个键,必须出现在对应 schema 自己的 `.shape` 里。扫源码而非行为是刻意的 —— 不可达分支没有行为可断言。 - reachability guard:每个 `findings.push` 调用点都必须被至少一条过 `safeParse` 的 fixture 触达(现存三个点,全覆盖)。 - 规则 ① 的 fixture 现在也走 `PermissionSetSchema.safeParse`。 四条分支各自做过变异验证:加回任意一条,至少两条测试转红。 真实元数据零新红:examples/ 与 default-permission-sets 中无 `parent_organization_id`,唯一的 `rowLevelSecurity` 用法在 permission set (保留的那条分支)上,`sharing:` 出现在 view 定义内而非 stack 根。 邻居规则同形别名读法已另行记账为 #5017(未认领),不在本 PR 范围。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
xuyushun441-sys
marked this pull request as ready for review
August 3, 2026 20:44
This was referenced Aug 4, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5009
validate-org-axis-red-lines.ts注册为input: 'parsed'—— 它看到的是ObjectStackSchema解析后的产物。#4984 修掉了 sharing rule 字段那一层的??别名读法,同一文件里还留着四条同形分支(议题点名三条,核对时又发现第四条),读的键 spec 都不声明。逐条核实与处置
每一条都用真实 schema 的
.shape与safeParse实测核过,不是靠读注释。cfg.permissions ?? cfg.permissionSetsObjectStackSchema.shape无permissionSets。stack 根 strip 未声明键:safeParse({ manifest, permissionSets: [...] })成功,但返回的data里没有该键cfg.permissionscfg.sharingRules ?? cfg.sharing(两处)sharing也被 stripcfg.sharingRulesstr(rule.object ?? rule.objectName)(议题未列,同形第四条)SharingRuleSchema是.strict(),按名拒绝:Unrecognized key(s) on this sharing rule:objectName``;而object是必填,解析过的规则上不可能缺str(rule.object)asArray(object.rowLevelSecurity ?? object.rls)整段(约 20 行)ObjectSchema.shape两个键都没有,且ObjectSchema是.strict()—— 带对象级 RLS 的 stack 在os validate/os build被整包拒绝:Unrecognized key(s) on this object:rowLevelSecurity``对象级 RLS 从来不是可授权面:
authorable-surface.json里唯一一条是security/PermissionSet:rowLevelSecurity。删除依据(schema 名 + 该键不存在的证明)已写进 commit message 和规则自己的## Scope段。危险不在死代码,在误导
这四条对任何 spec 合法 stack 都不执行,所以漏报为零。真正的代价是:那段死代码连
objects[N].rowLevelSecurity[M].using的诊断 path 都写好了,足以让下一位作者(人或 AI)相信对象级 RLS 是真实授权面并照着写更多代码 —— #5008 的 dev 差点就照它复制了一条同样惰性的遍历。别名容忍属于 producer 的拒绝,不属于 consumer(Prime Directive #12)。它还把一条指名道姓的 schema 拒绝,悄悄换成了一条永不触发的 gate。
反向验证
safeParsefixture 驱动的断言全绿,8 条转红的全部是 (a) 扫源码的 meta-guard 或 (b) 喂非 spec 合法 stack 的新钉子测试。即:删除前后对全部 spec 合法 fixture 行为完全一致,它本来就死。??的第一顺位,spec 合法的违规 stack 改动前已经判红。别名 limb 只是额外在 schema 会拒绝的形状上可达。所以正确的反向验证是反过来的:改动前对permissionSets/objectName拼法的非法 stack 会判红,改动后判绿,并由钉子测试证明 schema 才是那道门。(validate-expressions.ts:205那条就没这么幸运 —— canonical 排第三顺位,见 validate-expressions / validate-security-posture 也有同形的 spec 不声明键的??别名读法(#5009 建议 3 的核对结果) #5017。)meta-guard 全覆盖(#4992 模式)
留下的每条遍历分支都要有过
safeParse的 fixture 能走到;走不到的不允许存在。.shape里。扫源码而不是扫行为是刻意的:不可达分支根本没有行为可断言,这正是问题本身。计算键(policy[clause])另用一条断言把['using', 'check']钉在RowLevelSecurityPolicySchema上。findings.push调用点的rule:与path:模板,断言现存三个点各自被至少一条过safeParse的 fixture 触达;并反向断言没有 fixture 产出源码未声明的 path。加回删掉的第四个点会同时触发数量断言和可达性断言。PermissionSetSchema.safeParse(此前只有 sharing rule 和 object fixture 有这层保护)—— 顺带暴露出旧 fixture 缺objects/operation,并不 spec 合法。真实元数据零新红
examples/与default-permission-sets.ts中没有parent_organization_id,规则 ① 无从触发;rowLevelSecurity用法在 permission set 上(app-showcase/src/security/permission-sets.ts:57),正是保留的那条分支;sharing:都在 view 定义内(inquiry.view.ts/lead.view.ts),不是 stack 根键,本规则从不读它。改动纯粹是减法,findings 集合单调不增,不可能新增红。
顺带核对(不在本 PR)
议题建议 3 要求核对邻居规则。
validate-expressions.ts(三处)与validate-security-posture.ts(两处)有同形别名读法,其中validate-expressions.ts:205/421更糟 —— canonical 的condition排在两个被拒别名之后。已按 Prime Directive #10 记为 #5017(未认领),不在本 PR 修。验证
Changeset:
.changeset/org-axis-dead-alias-branches.md(@objectstack/lintpatch)。改动限于packages/lint。Generated by Claude Code