发现于 cloud#1012 的端到端验收(cloud 侧 pin bump 到 586d6f70 之后,真实 objectstack serve + 真实 HTTP 探针)。这是 cloud#1020 那个缺陷形状的原样重演,只是换了一个站点。
缺陷
packages/plugins/plugin-auth/src/auth-manager.ts 的 organizationHooks.beforeCreateOrganization 用 resolveMultiOrgEnabled() 判断「本部署是不是单组织」:
beforeCreateOrganization : async ( ) => {
if ( ! resolveMultiOrgEnabled ( ) ) {
throw new APIError ( 'FORBIDDEN' , {
message : 'Creating additional organizations is disabled on this deployment.' ,
} ) ;
}
} ,
而 packages/types/src/env.ts 里这两个函数的关系是(ADR-0105 D1):
export function resolveMultiOrgEnabled ( ) : boolean {
const raw = readEnvWithDeprecation ( 'OS_MULTI_ORG_ENABLED' , [ ] ) ;
return String ( raw ?? 'false' ) . toLowerCase ( ) !== 'false' ; // 只读被降级的布尔,缺省 false
}
export function resolveTenancyPosture ( ) : TenancyPosture {
// OS_TENANCY_POSTURE 是 canonical knob;只有它 unset 时才回落到上面那个布尔
...
return resolveMultiOrgEnabled ( ) ? 'isolated' : 'single' ;
}
OS_TENANCY_POSTURE 是权威 knob,OS_MULTI_ORG_ENABLED 是被它取代、只在前者 unset 时才生效的遗留布尔。于是一个只设权威 knob 的部署:
组织墙整套挂上(OrganizationsPlugin 注册、tenancy 服务 isolated、ADR-0093 D5 不报警、许可闸门通过);
但 POST /api/v1/auth/organization/create 依然 403 “Creating additional organizations is disabled on this deployment.”
resolveMultiOrgEnabled() 的文档注释还写着「the auth manager's /auth/config feature flag and org-create guard … MUST call this」—— 那句话写在 ADR-0105 D1 把该布尔降级之前 ,闸门是照着过期契约走的。
复现(真实 serve,非推断)
apps/objectos-ee(cloud 仓)+ 真实 Ed25519 企业许可,两次真实 POST /api/v1/auth/sign-up/email,第二个用户走引导式建工作区:
配置(其余相同)
组织墙
organization/create
OS_TENANCY_POSTURE=isolated
挂上
403 disabled on this deployment
OS_TENANCY_POSTURE=isolated + OS_MULTI_ORG_ENABLED=true
挂上
200 → 用户成为该组织 owner;随后 invite-member / accept-invitation 全部 200,两个自助注册用户互相看不见对方的组织
即:遗留 knob 能用,权威 knob 不能用 ——正好是声明的契约的反面。
为什么这条要紧(不是纸面洁癖)
cloud#1012 的维护者决策(方案 B)是:自助注册不 自动开通组织,org-less 用户由 console 的 RequireOrganization 导到引导式「Create your workspace」自己命名。那条路径就是这个 403。 所以在一台按文档只设 OS_TENANCY_POSTURE=isolated 的 objectos-ee 上,新注册用户既没有组织、也无法创建组织——平台对「新注册之后怎么办」的唯一答案是死路。
sys_member 侧一切正常(membership_policy 的 #5152 落地经复核工作正常),坏的只有这一个闸门。
建议修法
beforeCreateOrganization 改判 resolveTenancyPosture() !== 'single'(意图完全不变——「单组织模式下拒绝创建」——只是改成读权威 knob)。顺带把 resolveMultiOrgEnabled() 那段「every site … MUST call this」的注释订正到 ADR-0105 D1 之后的事实,并普查同一文件/包内其它读该布尔当作「是不是多组织」的站点 (objectql/src/registry.ts:735、runtime/src/app-plugin.ts:1045 至少要各自判一次是不是同一类误读)。
对 cloud 控制面无影响:它的 worker 本来就显式设 OS_MULTI_ORG_ENABLED=true,两种读法同解。
出处
探针与判定:cloud#1012 本轮开发(会话 session_015W6nhsDrz6zWQc8je12a1t),未指派,按 Prime Directive chore: version packages #10 归档到本仓。
同形状前案:cloud#1020(EE 许可闸门写 OS_MULTI_ORG_ENABLED 而 serve 读 posture)。当时的结论就是「不能照它的形状再来一次」。
发现于 cloud#1012 的端到端验收(cloud 侧 pin bump 到
586d6f70之后,真实objectstack serve+ 真实 HTTP 探针)。这是 cloud#1020 那个缺陷形状的原样重演,只是换了一个站点。缺陷
packages/plugins/plugin-auth/src/auth-manager.ts的organizationHooks.beforeCreateOrganization用resolveMultiOrgEnabled()判断「本部署是不是单组织」:而
packages/types/src/env.ts里这两个函数的关系是(ADR-0105 D1):OS_TENANCY_POSTURE是权威 knob,OS_MULTI_ORG_ENABLED是被它取代、只在前者 unset 时才生效的遗留布尔。于是一个只设权威 knob的部署:OrganizationsPlugin注册、tenancy 服务isolated、ADR-0093 D5 不报警、许可闸门通过);POST /api/v1/auth/organization/create依然 403 “Creating additional organizations is disabled on this deployment.”resolveMultiOrgEnabled()的文档注释还写着「the auth manager's /auth/config feature flag and org-create guard … MUST call this」—— 那句话写在 ADR-0105 D1 把该布尔降级之前,闸门是照着过期契约走的。复现(真实 serve,非推断)
apps/objectos-ee(cloud 仓)+ 真实 Ed25519 企业许可,两次真实POST /api/v1/auth/sign-up/email,第二个用户走引导式建工作区:organization/createOS_TENANCY_POSTURE=isolatedOS_TENANCY_POSTURE=isolated+OS_MULTI_ORG_ENABLED=true即:遗留 knob 能用,权威 knob 不能用——正好是声明的契约的反面。
为什么这条要紧(不是纸面洁癖)
cloud#1012 的维护者决策(方案 B)是:自助注册不自动开通组织,org-less 用户由 console 的
RequireOrganization导到引导式「Create your workspace」自己命名。那条路径就是这个 403。 所以在一台按文档只设OS_TENANCY_POSTURE=isolated的 objectos-ee 上,新注册用户既没有组织、也无法创建组织——平台对「新注册之后怎么办」的唯一答案是死路。sys_member侧一切正常(membership_policy的 #5152 落地经复核工作正常),坏的只有这一个闸门。建议修法
beforeCreateOrganization改判resolveTenancyPosture() !== 'single'(意图完全不变——「单组织模式下拒绝创建」——只是改成读权威 knob)。顺带把resolveMultiOrgEnabled()那段「every site … MUST call this」的注释订正到 ADR-0105 D1 之后的事实,并普查同一文件/包内其它读该布尔当作「是不是多组织」的站点(objectql/src/registry.ts:735、runtime/src/app-plugin.ts:1045至少要各自判一次是不是同一类误读)。对 cloud 控制面无影响:它的 worker 本来就显式设
OS_MULTI_ORG_ENABLED=true,两种读法同解。出处
session_015W6nhsDrz6zWQc8je12a1t),未指派,按 Prime Directive chore: version packages #10 归档到本仓。OS_MULTI_ORG_ENABLED而serve读 posture)。当时的结论就是「不能照它的形状再来一次」。