feat(spec): add three-tier subject hierarchy and org role lattice

- Hierarchy.lean: Platform/Organization/User struct, 三层主体层级
- User.lean: FeishuProfile, 飞书身份是绑定不是本体
- User struct: id/displayName/passwordHash/feishu
- Organization.lean: OrganizationRole(owner/admin/member) + 成员管理规则
- Prelude.lean: UserId/FeishuOpenId/FeishuConnectionId

实现偏离: spec 钉 User 为独立实体, 实现 User.id 由飞书身份派生

lake build 35/35 全绿
This commit is contained in:
2026-07-12 00:20:09 +08:00
parent 53998d2651
commit 3a50ed0ce2
5 changed files with 122 additions and 14 deletions
+35 -13
View File
@@ -3,16 +3,9 @@ import Spec.Prelude
/-!
# Organization —— SaaS tenant root (ADR-0020, ADR-0024)
ADR-0020:Hub 长期按 SaaS 形态演进,`Organization` 是客户侧 tenant root
`Project` 与 `Team` 都必须归属且只归属一个 organization;team 对 project 的授权
必须在同一 organization 内。平台运营控制面(platform staff / break-glass / 账单)
不复用 project 的 `read/edit/manage` 角色格,而是另一个控制面。
本模块只钉死会造成实现分歧的不变量:tenant root 存在、project/team 单归属、team grant
不得跨 org,以及 model provider connection 的凭据归属模式。用户身份、外部目录
provider 细节仍为 `OPEN`;平台控制面身份/角色/审计已由 ADR-0023 与
`Spec.System.PlatformAdministration` 独立决定。连接凭据的本地主密钥信封、不可变版本、
writer authority 与 fail-closed resolver 由 ADR-0024 固定。
组织是租户根。project/team 必须归属且仅归属一个 org;team→project grant 必须同 org
组织实体见 `Hierarchy.Organization`;用户见 `Spec.System.User`;平台控制面见
`PlatformAdministration`(ADR-0023)。凭据信封见 ADR-0024。
-/
namespace Spec.System
@@ -51,9 +44,8 @@ def TeamProjectGrantScope.WellScoped
(teamOrg : I.TeamId Option I.OrganizationId) : Prop :=
o, projectOrg grant.project = some o teamOrg grant.team = some o
/-- Organization 的 model provider 凭据归属模式(`PINNED`, ADR-0021):BYOK 由 org
管理员提供和管理;platform-managed 由平台管理员为该 org 单独提供和管理。两种模式
都不允许无关 org 共用 process-global provider key。模式切换过程仍为 `OPEN`。 -/
/- BYOK 由组织所有者/管理员管理;platform-managed 由平台管理员管理。两种模式都不允许
跨 org 共用 process-global key。模式切换 `OPEN`。 -/
inductive ProviderCredentialMode where
| byok
| platformManaged
@@ -104,4 +96,34 @@ def OrganizationSecretResolvable
organizationActive && connectionActive &&
(binding.organization == requestedOrganization) && authenticatedEnvelope
/-- 组织成员角色(`PINNED` 封闭三档)。与项目层 `Role`、平台层 `PlatformRole` 互不相交。 -/
inductive OrganizationRole where
/-- 组织所有者(`PINNED`):bootstrap,独家管 owner 群体,受最后所有者保护。 -/
| owner
/-- 组织管理员(`PINNED`):管成员/policy/BYOK,不能管 owner 群体。 -/
| admin
/-- 组织成员(`PINNED`):普通成员。 -/
| member
/-- 组织成员关系(`PINNED`)。 -/
structure OrganizationMembership where
/-- 成员(`PINNED`;独立实体,见 `Hierarchy.User`)。 -/
user : I.UserId
/-- 组织(`PINNED`)。 -/
organization : I.OrganizationId
/-- 角色(`PINNED`)。 -/
role : OrganizationRole
/-- 只有组织所有者能管 owner 群体(`PINNED`)。 -/
def CanManageOwnerGroup (actorRole : OrganizationRole) : Prop :=
actorRole = .owner
/-- 最后所有者保护(`PINNED`):撤销 owner 时同 org 必须还有一个不同的 owner。 -/
def LastOwnerProtected
(target : OrganizationMembership I)
(otherOwnersInOrg : List I.UserId) : Prop :=
target.role .owner
other, other otherOwnersInOrg other target.user
end Spec.System