fix(objectql): wantOwner 翻为正面清单 + 注入 owning_business_unit_id (ADR-0117 D1) (#5677) - #5802
Merged
Merged
Conversation
…s_unit_id (ADR-0117 D1) (#5677) `applySystemFields` decided owner injection with a DENY-list — only 'org' and 'none' opted out — so ANY fourth `ownership` value fell through to the default branch and was stamped with `owner_id`. ADR-0117 D1's new `business_unit` tier means the opposite ("owned by a UNIT, not a person"): owner_id no, owning_business_unit_id yes. #4611's one-shot probe measured the inversion. The judgement is now a positive list (`undefined | 'user'`), which is behaviour-identical for the three values that exist today and stops a new tier from inheriting the owner branch by accident. A second anchor covers the union of the owner tiers with `business_unit` and injects `owning_business_unit_id` (lookup to sys_business_unit). The column is shaped after `organization_id` (server-stamped scope anchor), not after `owner_id` (user-assignable field): readonly, hidden, nullable, unindexed. None of those presumes ADR-0117 D2's undecided stamping policy — they grant no capability, so every D2 outcome stays reachable; the column is provisioned but inert until the stamping middleware (D2/D4) and backfill (D8) land. The objectql conformance test migrates the name from the documented-reserved group to Group A, where it is derived from the live injection code — the migration #4611 left a note for. Scope is the issue's work items 1-3. The spec-side JSDoc/description sync is #5767 and the `ownership` enum member is #5678, both strictly after this PR. Fixes #5677 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V7WetGmnfoXNn8cLieKKmx
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…t-owner-positive-list
os-zhuang
marked this pull request as ready for review
August 6, 2026 07:52
This was referenced Aug 6, 2026
baozhoutao
pushed a commit
that referenced
this pull request
Aug 6, 2026
队列把本 PR 踢出:@objectstack/objectql 记 333,队列基实测 334。333 是在 07:41 的 main 上冻结的,而 #5802(registry.test.ts +116 行)与 #5850 在 07:52 之后才 落地。合并当前 main 后实测 335,两条增量都能逐一归因: - +1 TS2339 在 src/registry.test.ts —— #5802 新增的 registry 测试; - +1 TS2554 在 src/engine-update-prior-read-scope.test.ts —— #5850(#5284) 新建的文件。 tests 125 -> 126。其余 33 条纹丝不动(总计 2018 raw errors,无一超出记录值)。 先证伪了另一种解释:同一棵树连跑两次 --re-measure,输出逐字节相同,所以不是 tsc 计数不确定,校准就是正确处置(不需要谈容差)。 顺带把队列这一面写进 MEASURED 的文档块:队列是按「合并到队首」构建的,队首会随 前面的条目落地而移动,所以重跑失败的 job 无法自愈(重跑复用同一个 merge ref, 量的还是那个旧基),唯一修法是推新提交;以及排在后面的 PR 会被连坐,红了要先撤出 队列再修。双跑证伪法也一并写下,免得下一个人重新推导。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
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 #5677
ADR-0117 D1 的执行面。范围严格是 issue 工作面第 1-3 项,全部落在
packages/objectql。为什么先动引擎
applySystemFields判定是否注入owner_id的wantOwner是排除式的:只排除org/none,于是任何第四个ownership值都会掉进默认分支并被盖上owner_id—— 与 D1 表格恰好相反(
business_unit档的全部含义就是「归属于组织单元而非个人」)。#4611 的一次性探针已实测确认过这个反向结果。所以顺序是:先翻面,枚举扩展才安全。
改了什么
1.
wantOwner翻为正面清单 ——ownership === undefined || ownership === 'user'(
managedBy平台表与sys_命名空间的跳过规则原样保留,并抽成两个锚点共用的ownershipEligible,避免二者日后漂移)。对今天存在的三个值行为完全不变;唯一变化是新档位不再靠「落进默认分支」继承 owner 语义。
2. 注入
owning_business_unit_id—— lookup 到sys_business_unit,按 D1 表格:ownershipowner_idowning_business_unit_idundefined/userbusiness_unitorg/none3. conformance 归类迁移 ——
system-managed-fields-conformance.test.ts中该名从documented-reserved 组移入 Group A(由实时注入代码推导)。#5675 在测试注释里埋的
就是这一步;不迁会以 stray entry 失败。迁移后额外把该名写进 Group A 的
「非空洞」守卫列表,把这次搬家钉住:否则将来若注入回退,Group A 会悄悄缩回去、
测试转而要求把它重新列回 reserved —— 一个描述着与已接受决定相反事实的绿色套件。
列的形态,以及它为什么不依赖未裁定的 D2
比照
organization_id(服务端盖章的作用域锚点)而非owner_id(用户可指派的业务字段):
readonly: true+hidden: true+required: false,不建索引。readonly—— D3 要求该值服务端推导并校验,客户端传入的值一律被覆盖;改动它是D4 的 transfer 类操作,而 D4 尚未落地,因此现在不得存在任何客户端写入路径。
hidden—— 盖章中间件未落地(D2 未裁、D8 未写),列是已提供但惰性的。在每个业务对象的布局上摆一个恒为 NULL 的 lookup,等于展示运行时并不提供的能力
(Prime Directive chore: version packages #10)。另外
FIELD_GROUP_SYSTEM_FIELDS在packages/spec,本单不碰,
hidden让渲染面无需 spec 改动即可正确。required: false—— 可空。D2 的owningBusinessUnit.required是插入时拒绝的规则,不是列的可空性,读不出来也不该从这里读。
pinned/follow_owner/transferable:它们不授予任何能力,因此 D2 的每一种结论都仍然可达。未触发 needs_decision。
与相邻单的时序
SystemFieldNameJSDoc +object.zod.ts描述)不在本 PR,已按车道边界转办 [spec] ADR-0117 D1 执行面落地后的声明同步:OWNING_BUSINESS_UNIT_ID JSDoc 翻面 + object.zod.ts systemFields 注入清单描述 #5767 —— 本 PR 不碰
packages/spec。ownership枚举加business_unit是 ADR-0117 D1 声明面:ownership 枚举扩展 'business_unit'(须与列注入同 PR 或严格后置) #5678,严格后置于本 PR。因此合并后短暂存在「运行时已就绪、声明尚未开放」的状态:该值今天仍被
ObjectSchema响亮拒收,方向是运行时多于声明,不是 ADR-0049 所禁止的形状。测试因此用 duck-typing
构造 fixture(与本套件既有的 opt-out 用例写法一致);ADR-0117 D1 声明面:ownership 枚举扩展 'business_unit'(须与列注入同 PR 或严格后置) #5678 落地后
as any可直接删掉而不动任何断言。
就不可由匿名面客户端提供 —— 这正是当初提前登记的目的。
验证
business_unit档误得owner_id,恰好一条断言转红,其余(owning_business_unit_id、org/none、user)保持绿」。实测完全一致,且复现了 ADR-0105 D13's "scoping field" has no metadata home — the 0105↔0117 linkage gap #4611 探针的原样输出:AssertionError: expected { type: 'lookup', …(6) } to be undefined/+ Received: { "reference": "sys_user", "label": "Owner", … },Tests 1 failed | 93 passed。registry.test.ts的org/noneopt-out 用例未改一字且保持绿 —— 这是「翻面没有改变既有语义」的证据。
pnpm --filter @objectstack/objectql test→ 123 files / 2043 tests 全绿;typecheck干净。turbo run test→ 135/135 tasks 成功(含 dogfood 85 files / 513 tests、showcase、crm);
turbo run typecheck→ 125/125 成功。check:query-options-erasure(84 unswept / test surface 267 —— 恰在天花板,未引入新豁免)、
check:engine-double-contract、check:adr-anchors、check:nul-bytes全过;改动文件 eslint 干净,并做了控制字符自检。Generated by Claude Code