Skip to content

docs(adr): ADR-0117 记录级业务单元归属(owning business unit)提案 - #4392

Merged
os-zhuang merged 2 commits into
mainfrom
claude/rbac-org-structure-integration-uxg3f2
Jul 31, 2026
Merged

docs(adr): ADR-0117 记录级业务单元归属(owning business unit)提案#4392
os-zhuang merged 2 commits into
mainfrom
claude/rbac-org-structure-integration-uxg3f2

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

概要

集团管控设计的第一块地基规格:给记录归属补上缺失的中间一层。

今天一条记录只有 owner_id(人)和 organization_id(租户墙)两个归属戳,"属于哪个部门 / 哪个法人"是从所有者推导的——层级深度档位最终编译成 owner_id IN (…)plugin-sharing/src/sharing-service.ts:47,151,214)。这带来三个问题:归属漂移(所有者调动,历史单据的部门归属无声跟随)、无所有者语义的数据没有归属(库存、台账)、报表没有可聚合列。

决策要点

  • D1 字段owning_business_unit_id 挂靠既有 ownership 轴(spec/src/data/object.zod.ts:818),新增 business_unit 一档;org/none 与平台表照现有规则跳过;
  • D2 盖章策略pinned(默认,单据/凭证语义)/ follow_owner(CRM 语义)/ transferable;默认值来源为调用方显式值 → 所有者主 BU → 按 required 决定拒绝或留空;
  • D3 不变量org_id == BU 所属 org,服务端推导、伪造值覆盖(与现有 organization_id 盖章纪律一致);
  • D4 写入守卫:归属变更复用 allowTransfer,且目标 BU 必须落在调用方写作用域内pinned 下策略优先于权限位;
  • D6 契约变更(破坏性)IHierarchyScopeResolver.resolveOwnerIds(): Promise<string[]> 改为返回"按哪个戳过滤"的谓词规格,解除 sharing-service.ts:47OWNER_FIELD 硬编码,并为后续公司轴(organization_id 过滤)留出同形位置;
  • D7 豁免ownershiporg/none、关闭租户列、以及集团集中管控的配置/主数据对象不注入也不受 BU 轴约束;
  • D8 迁移:回填作业 + fail-closed 启用门,明确不做"空值回退到 owner 判定"的兼容层(AGENTS.md 契约优先);
  • D9 边界:列与盖章开源,层级解析归企业版 hierarchySecurity
  • D10 命名纪律:不得复用 sys_user.primary_business_unit_id(那是用户属性,不是记录戳)。

评审重点(ADR 内含五个未决问题)

  1. D5 的偏离:法人归属做成解析 helper 而非物化列(避免多态外键),是否接受?
  2. ownership: 'business_unit' 新档是否值得,还是让这类对象接受一个名义所有者?
  3. pinned 作为默认值——与平台既有 CRM 形态对象的直觉相反,但对 ERP 类对象更安全;
  4. D8 启用门粒度:按对象 vs 按部署一次性;
  5. 是否需要独立权限位 allowChangeOwningUnit 而非复用 allowTransfer

说明

仅新增一份 ADR 文档,无代码变更。D6 的契约变更需与企业版层级解析器同步发布,实现另行开 PR。

🤖 Generated with Claude Code

https://claude.ai/code/session_01BPXSoZoXtpQecCsQXwMYTK


Generated by Claude Code

为集团管控层补上记录归属的中间一层:部门/法人归属今天是从 owner 推导的
(深度档位编译为 owner_id IN …),带来归属漂移、无所有者数据无归属、
报表无可聚合列三个问题。

决策要点:
- owning_business_unit_id 挂靠既有 ownership 轴,新增 business_unit 一档;
- 盖章策略 pinned(默认,单据语义)/ follow_owner(CRM)/ transferable;
- 不变量 org_id 由 BU 链推导、服务端权威盖章,伪造值覆盖;
- 归属变更复用 allowTransfer,且目标 BU 必须在写作用域内;
- IHierarchyScopeResolver 改为返回谓词规格(破坏性),解除 OWNER_FIELD 硬编码;
- 迁移用回填 + fail-closed 启用门,不做空值回退兼容层;
- 开源拥有列与盖章,企业版拥有层级解析。

含五个提交评审的未决问题(法人归属是否物化、新枚举档是否值得、
pinned 默认是否正确、启用门粒度、是否独立权限位)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BPXSoZoXtpQecCsQXwMYTK
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 31, 2026 10:51am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation size/m labels Jul 31, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review July 31, 2026 11:03
@os-zhuang
os-zhuang merged commit 7924a27 into main Jul 31, 2026
15 checks passed
@os-zhuang
os-zhuang deleted the claude/rbac-org-structure-integration-uxg3f2 branch July 31, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants