fix(lint): org-axis 红线读 spec 声明的 sharing-rule 键 —— ADR-0105 D6 两条门禁此前从不触发 (#4984) - #4992
Merged
xuyushun441-sys merged 1 commit intoAug 3, 2026
Merged
Conversation
`validateOrgAxisRedLines` 取 `rule.criteria ?? rule.filter` 与
`rule.sharedTo ?? rule.recipient`,而 `SharingRuleSchema` 是 `.strict()` 的、
声明的键是 `condition` / `sharedWith` —— 那四个名字只作为**被拒别名**存在于
`sharingRuleUnknownKeyError` 里。规则跑在 parse 之后(`input: 'parsed'`),
所以对任何 spec 合法的 stack 这四个属性恒为 undefined,
`parent_organization_id` 的判定恒为 false:一条 error 级红线在 sharing-rule
路径上从不触发。
改为只读 canonical 键。别名不在 consumer 侧用 `??` 容忍 —— schema 的拒收
信息已经给出处方,parse 就是那道门。`condition` 是 `ExpressionInput`,
三种形状(裸串 / `{dialect,source}` / 编译后 `{dialect,ast}`)都要能扫到。
结构性的一半在 fixture:原测试用的正是那些被拒别名,所以**测试全绿而规则全死**。
现在每个 sharing-rule fixture 先过 `SharingRuleSchema`、每个 object fixture 先过
`ObjectSchema` —— fixture 与 spec 漂移即在 fixture 处判红,而不是去测一个
作者写不出来的形状。
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 18:58
xuyushun441-sys
enabled auto-merge
August 3, 2026 18:58
xuyushun441-sys
deleted the
claude/issue-4984-org-axis-redlines-dead-keys
branch
August 3, 2026 19:11
This was referenced Aug 3, 2026
Closed
Open
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 #4984
死态复现(before 证据,最新 main)
validateOrgAxisRedLines注册为input: 'parsed',即跑在 Zod parse 之后。它取rule.criteria ?? rule.filter与rule.sharedTo ?? rule.recipient,而SharingRuleSchema是.strict()的、声明的键是condition/sharedWith—— 那四个名字只作为被拒别名出现在sharingRuleUnknownKeyError里(那是给报错信息用的处方,不是被接受的键)。在
c87ef7034(本分支的基点)上实测:即:一条声明为
error、以 ADR-0105 D6 红线为依据的门禁,在 sharing-rule 这条路径上对任何 spec 合法的 stack 永不触发;而它自己的测试 fixture 用的正是那些被拒的死键,所以测试全绿、规则全死。改了什么
1. 规则改读 canonical 键。
rule.condition/rule.sharedWith,不再有??别名兜底。别名已经在sharingRuleUnknownKeyError里有明确处方并被 parse 拒收 —— consumer 不该容忍 producer 契约拒绝的东西(Prime Directive #12)。新增一条测试把这个决定钉住:写criteria/filter/sharedTo/recipient的规则不判红,交给 spec 的拒收。2. 语义按 D6 原文逐条搬,不是只换名字。 别名与真键的形状确实不同:
criteria/filterconditionExpressionInput—— 裸串(作者态)/{ dialect, source }(parse 后)/{ dialect, ast }(compile 后),三种都要能取到文本,新增expressionText()sharedTo/recipientsharedWith.strict()的{ type, value };id也是被拒别名expressionText()刻意不读meta.rationale—— 那段散文完全可能正当地提到它正在解释「本规则不使用」的那个字段,error 级门禁不能被注释误伤。path从笼统的sharingRules[i]细化到sharingRules[i].condition/sharingRules[i].sharedWith,两个槽位各自点名。3. fixture/schema 漂移守卫(本单的结构性修复)。 只改键名的话,同样的漂移下次还来。现在每个 sharing-rule fixture 都过
sharingRule(),它先用真的SharingRuleSchemaparse 再交给 lint;object fixture 同理走objectFixture()→ObjectSchema。fixture 一旦与 spec 漂移就在 fixture 处判红,而不是去测一个作者写不出来的形状。元测试本身也自证不死:把 #4984 之前的两个 fixture 原样喂进去,断言它们抛错。反向验证
sharingRules[0].condition/.sharedWith改回死键时的失败清单:
真实元数据上是否有新红
没有。 D6 是 error 级,所以逐条核过:
examples/app-showcase/examples/app-crm的全部 sharing rule:没有任何condition或sharedWith提到parent_organization_id;tenancy.enabled: false或systemFields.tenant: false,所以 D6 ② 也无处触发;default-permission-sets.ts与examples/app-showcase/src/security/permission-sets.ts的 RLSusing/check:只有assignee == current_user.email/owner == current_user.email一类,无 org 轴引用。验证
顺手发现,已单独建单(未随本 PR 修)
objects[].rowLevelSecurity分支也是死路径:ObjectSchema根本不声明rowLevelSecurity,objects[0]带该键的 stack 被 parse 拒收。危害小于本单(permission-set 那段覆盖了 RLS 的唯一可授权落点,红线没有洞),但「删掉该段」还是「给 spec 加对象级 RLS 授权面」是 ADR 级取舍,不宜在本 PR 里替维护者决定。business_unit收件人,漏了unit_and_subordinates,而 ADR-0105 D6 ② 原文点名的正是后者,且它的授权面更大(整棵 BU 子树)。这是 error 级门禁的扩张,不随本单做;已核查按此扩张现有真实元数据不会产生新红。Generated by Claude Code