import Spec.Prelude /-! # Organization —— SaaS tenant root (ADR-0020) 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` 独立决定。 -/ namespace Spec.System variable (I : Identifiers) /-- 课程项目的租户归属(`PINNED`, ADR-0020):每个 project 必须有一个 organization。 -/ structure ProjectTenancy where /-- 被归属的课程项目(`PINNED`, ADR-0020)。 -/ project : I.ProjectId /-- project 所属 organization(`PINNED`, ADR-0020)。 -/ organization : I.OrganizationId /-- Hub team 的租户归属(`PINNED`, ADR-0020):team 是 org-scoped principal。 -/ structure TeamTenancy where /-- 被归属的 Hub team(`PINNED`, ADR-0020)。 -/ team : I.TeamId /-- team 所属 organization(`PINNED`, ADR-0020)。 -/ organization : I.OrganizationId /-- Team 对 project 的授权作用域(`PINNED`, ADR-0020):`PermissionGrant` 可以把 TEAM principal 授给 PROJECT resource,但该 grant 必须同 org。role 本身仍由 `PermissionGrant`/`Permission` 定义,这里仅刻画 tenant well-scopedness。 -/ structure TeamProjectGrantScope where /-- 被授权的 project(`PINNED`, ADR-0020)。 -/ project : I.ProjectId /-- 获得授权的 team principal(`PINNED`, ADR-0020)。 -/ team : I.TeamId /-- Team-project grant 是良构的 iff project 与 team 解析到同一 organization (`PINNED`, ADR-0020)。`projectOrg`/`teamOrg` 由平台提供(表示 `OPEN`);本谓词钉死 跨 org team grant 必须被拒绝。 -/ def TeamProjectGrantScope.WellScoped (grant : TeamProjectGrantScope I) (projectOrg : I.ProjectId → Option I.OrganizationId) (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`。 -/ inductive ProviderCredentialMode where | byok | platformManaged /-- Organization 的 model provider connection(`PINNED`, ADR-0021):connection 必须 归属一个且仅一个 organization,并明确采用哪一种凭据模式。key/base URL 的加密表示、 轮换与 resolver 机制由后续 secret-control-plane 决策规定。 -/ structure OrganizationProviderConnection where /-- connection 所属 organization(`PINNED`, ADR-0021)。 -/ organization : I.OrganizationId /-- connection 的凭据归属模式(`PINNED`, ADR-0021)。 -/ mode : ProviderCredentialMode end Spec.System