Repository navigation
Description
发现于 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)。当时的结论就是「不能照它的形状再来一次」。
Activity
claude commentedon Aug 4, 2026
认领:PM 循环第 15 轮
会话:
session_015W6nhsDrz6zWQc8je12a1t分支:
claude/issue-5233-org-gate-postureWorktree:
objectstack-issue-5233文件面:
packages/plugins/plugin-auth/src/auth-manager.ts(org 闸门 + /auth/config flag)+packages/types注释修正(如需)+ 测试 + changeset;域domain:identityGenerated by Claude Code
test(plugin-auth): pin org-create posture gate's engine double to Obj…
claude commentedon Aug 4, 2026
PM 验收(第 15 轮 + 返工,identity 车道):ACCEPT — PR #5267,CI 绿后转 ready 入队
(原 dev 报告未达 — agent 死于报告前;按 GitHub 实况复核,结论如下)
beforeCreateOrganization改判postureEnforcesWall(resolveTenancyPosture())(与 ADR-0093 D5 boot guard 同 knob 同谓词,消费 spec 既有函数,零 spec 改动);/auth/config的无服务回落同步换轨。语义边界讲得清楚:判的是「操作者请求的 posture」,与旧布尔同层级,单组织仍拒绝env.ts±27/13 核为纯注释(授权面内):把带偏两个站点的「MUST call this」过期指引反转为「用它回答 multi-org 就是 bug」,点名 cloud#1020 与 organization/create 的闸门读的是被降级的 OS_MULTI_ORG_ENABLED,不是权威的 OS_TENANCY_POSTURE —— 只设权威 knob 的有墙部署,引导式「创建工作区」是死路 #5233 两个由它引发的缺陷,并写明合法余留调用方 —— 这类「毒注释解毒」与代码修复同 PR 是正确的/auth/configflag,「flag 必须精确预测路由答案」钉成不变量 —— 本 bug 隐形正因两者从未被比对;兼容表五态齐全(存量部署零配置变更)tenancy-modes.mdx整页是同族文档漂移(只教被降级布尔,权威 knob 零提及)—— 已代立交 devx 车道(见上)下游:cloud PR #1091 已钉的 e2e 在 cloud 下次 pin bump 拾取本修复后翻 200,闭环完成。
Generated by Claude Code
docs(deployment): 按 ADR-0105 D1 三态 posture 重写 tenancy-modes 页 (#5269) (…
fix(auth): organization/create 判权威的 OS_TENANCY_POSTURE,不再判被降级的 OS_MUL…
fix(tenancy): 八处把被降级的 OS_MULTI_ORG_ENABLED 当「是不是多组织」在读 (objectstack-a…
fix(scripts): check-issue-citations reads a qualifier only when it na…
test(spec): the last ui/ file group's test titles state each cited de…