feat(spec): ADR-0117 scoped 接受 —— owning_business_unit_id 规范名进入登记处 (#4611) - #5675
Merged
Conversation
…4611) ADR-0105 D13 的 promotion 工具要求「按子树的 scoping field 回填 organization_id」, 但没有任何元数据声明「哪个字段承载 BU 归属」。维护者裁定加速 ADR-0117 补上这一层。 本轮落地协议决定的名字面,不含运行时注入。 - ADR-0117 定稿为 `Accepted (D1/D3 scoped)`;D5/D2 默认值/D8/D4 仍为 Proposed - 新增 SystemFieldName.OWNING_BUSINESS_UNIT_ID,标注 open-core 暂不注入 - PUBLIC_FORM_SERVER_MANAGED_FIELDS 收该名(fail-closed,先于列存在) - 刻意不动 ownership 枚举:registry 的 wantOwner 是排除式判定,加值会让 business_unit 档照常注入 owner_id,与 D1 相反(ADR-0049 禁止的形态); 加 pin 钉住当前的响亮拒绝,防止后人顺手补全 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 109 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 5, 2026
#5677(engine-core:wantOwner 翻正面清单 + 列注入)、#5678(spec:枚举扩展), 并把 D2/D3/D4/D8 单列一行,标明其中四项尚未裁定。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fxLGQdatPbBUvCgiVxg6D
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 #4611
ADR-0105 D13 把 promotion 的第三步写成「按子树的 scoping field 回填
organization_id」,却没有任何元数据声明「哪个字段承载 BU 归属」。维护者 2026-08-05 裁定选 1 —— 加速 ADR-0117;PM 复审进一步裁定本轮取 Q1=D / Q2=(b)。本 PR 落地协议决定的名字面,不含运行时注入。维护者合并本 PR 即为接受 ADR-0117 的
Accepted (D1/D3 scoped)状态,即:ownership新增business_unit一档、owning_business_unit_id记录戳的命名与语义;record.organization_id == sys_business_unit(owning_business_unit_id).organization_id。以下四项仍为 Proposed,不随本次合并静默通过,需各自单独评审:
pinned是否适合作默认盖章策略(平台既有对象以 CRM 形态居多,直觉相反)allowTransfer还是新增allowChangeOwningUnit另:D6 是破坏性契约变更(
resolveOwnerIds→resolveScope,packages/spec/src/contracts/sharing-service.ts:415),不在本 PR 范围内,也不因本次 scoped 接受而获批。状态行的限定式写法对齐仓内既有先例(ADR-0022 / ADR-0025 / ADR-0038 都在 Status 行标注了范围)。
本轮落地了什么
Accepted (D1/D3 scoped),新增「落地状态」表(协议已接受 / 执行待实现),未决问题列表保留并标明已裁定的那一条。SystemFieldName.OWNING_BUSINESS_UNIT_ID(owning_business_unit_id)—— 明确标注 open-core 暂不注入。该表是名字登记处而非注入集合,tenant_id/user_id/deleted_at是既有三条同类先例。早登记是为了阻断消费方各造一个business_unit_id/bu_id/dept_id,即 cloud#982 用tenant_id/org_id/space付过学费的漂移形态。PUBLIC_FORM_SERVER_MANAGED_FIELDS收该名 —— 它是与owner_id/organization_id同类的归属锚点;一旦盖章,匿名面上被伪造的值会把记录推到别的部门墙后。在列存在之前拒收是零成本且 fail-closed 的,等列上线后再补名单,中间那个版本就是一个带着发布号的洞。scripts/adr-anchors.json锚点 —— 按 AGENTS.md [WIP] Add Chinese version of the documentation #13,一个「保留但不注入」的条目单独读会像死重量(而本仓正在主动清理死面),锚点把它站在哪个决策上写清楚。刻意不动
ownership枚举 —— 附实测packages/objectql/src/registry.ts:359-363的wantOwner是排除式判定:只排除
org/none。因此只加枚举值而不动 registry,ownership: 'business_unit'会照常注入owner_id—— 与 ADR-0117 D1 表格(该档owner_id❌、owning_business_unit_id✅)恰好相反。一次性探针实测(跑完即删,未入库),断言按 D1 写:即:那不是「惰性新增」,而是把今天的响亮 Zod 拒绝换成明天的静默错误 —— ADR-0049「spec 不得声明运行时不执行的东西」所禁止的形态,也是「让 AI 写的元数据难以出错」这条轴上最差的一档。故本轮不加枚举值,并加 pin 钉住当前的拒绝(且断言错误信息仍列出 user / org / none 三个合法值),注释指向 ADR-0117 与后续实施链,防止后人「顺手补全」。
pin 的方向说明(不套模板):
business_unit在本 PR 之前就已被拒绝,所以这条 pin 不改变行为,它固化的是一个既有的正确拒绝。它不是「先红后绿」型的回归证明 —— 真正的先证红在下一节。先证红
对闸门本身证红,证明这次登记是被门禁看守的、而非装饰性的。预测方向:把名字加进拒收名单、但不在 conformance 测试里归类,应当以「stray entry — classify it」失败。
归类到 documented-reserved 后转绿。
验证
pnpm --filter @objectstack/spec testpnpm --filter @objectstack/objectql testpnpm --filter @objectstack/rest testpnpm --filter @objectstack/plugin-security testpnpm --filter @objectstack/cli exec vitest run test/commands.test.tspnpm --filter @objectstack/spec typecheckcheck:api-surface/check:authorable-surface/check:liveness/check:dual-source-exportscheck:adr-anchors/check:nul-bytes消费半径已扫:
PUBLIC_FORM_SERVER_MANAGED_FIELDS的消费方在packages/rest(表单路由白名单)与packages/plugins/plugin-security(grant strip)—— 都不在被改动的包内,已单独跑绿。ownership枚举的消费方packages/cli/test/commands.test.ts:83同理已验(本轮枚举未动,故仍绿)。生成物
零生成物变动。
check:api-surface报 "public API surface + factory signatures unchanged" ——SystemFieldName本就是导出符号,新增成员值不进签名基线;authorable-surface.base.json未动,因为本 PR 没有碰object.zod.ts(authorable 面只在枚举真正落地那一 PR 才会合法移动)。spec-changes.json无ownership条目,不变。changeset:判为 minor(非 patch),理由
PM 建议 patch,但按仓内既有判例,
@objectstack/spec新增导出成员走 minor(见.changeset/action-alias-conflict-warning.md等)。本次除新增SystemFieldName成员外,还收紧了匿名公开表单面的行为(该名自此不再接受客户端提交值),两者都是用户可见的。patch 会让下游在补丁区间内静默收到一次安全面收紧,方向不对,故取 minor 并在 changeset 内写明行为变更提示。若维护者仍偏好 patch,改动仅一行。后续实施链(本 PR 不实现)
已立两单,均
Blocked-by本 PR:domain:engine-core):wantOwner由排除式翻为正面清单 + 注入owning_business_unit_id列 + conformance 归类迁移;domain:spec):ownership枚举扩展'business_unit',须与 ADR-0117 D1 执行面:applySystemFields 的 wantOwner 由排除式翻为正面清单 + 注入 owning_business_unit_id #5677 同 PR 或严格后置 —— 单独落 spec 侧即重现本 PR 所拒绝的形态。ADR-0117 D1 声明面:ownership 枚举扩展 'business_unit'(须与列注入同 PR 或严格后置) #5678 内已写明 CLI 枚举 pin(packages/cli/test/commands.test.ts:83)的消费半径与 authorable 生成物预期。D2 盖章策略、D3 不变量的运行时校验、D4 守卫、D8 迁移、D6 契约变更、D13 工具(cloud#874)均不在此链本轮范围;其中四项尚未裁定,实现时若无法回避应回报 needs_decision。