从 #5233 的修复中分出来的一个需要维护者定夺的语义问题,#5233 本身没有改动它(那是纠正 knob,不是改能力边界)。
事实
修好 #5233 之后,packages/plugins/plugin-auth/src/auth-manager.ts 的两个站点读的是两个不同的事实,在一种部署形状下会分叉:
| 站点 |
读什么 |
语义 |
organizationHooks.beforeCreateOrganization |
postureEnforcesWall(resolveTenancyPosture()) |
操作者请求的 posture |
/auth/config 的 features.multiOrgEnabled |
tenancy?.posture ?? resolveTenancyPosture() |
实际生效的 posture(ADR-0093 D4) |
只有一种形状让两者不同 —— ADR-0093 D5 的降级态:请求了 isolated/group,但企业包 @objectstack/organizations 不在(org-scoping 服务缺席),于是 tenancy.posture 解析为 single 且 degraded=true。此时:
- 闸门:放行(请求的是
isolated);
/auth/config:multiOrgEnabled=false,console 把「创建组织」入口藏起来;
- 结果:UI 不给按钮,但 API 打得通,并且创建出来的组织没有任何引擎强制的墙。
降级前闸门读 resolveMultiOrgEnabled(),那同样是一个纯 env 读,在这里同样返回 true、同样放行。#5233 只是把 knob 从被降级的布尔换成权威的 posture,分叉是原样保留的。已在 packages/plugins/plugin-auth/src/org-create-posture-gate.test.ts 里作为当前行为钉住(用例名带 "pinned as CURRENT behaviour"),所以无论怎么定夺,都必须是有意识地改这条断言。
两个选项
A. 保持现状 —— 闸门判「请求的 posture」。
- 与
serve.ts 的 D5 boot guard 同源(它也是 resolveTenancyPosture() !== 'single'),两处口径一致。
- 降级本来就已经是显式选择:
serve 在降级时默认拒绝启动,要 OS_ALLOW_DEGRADED_TENANCY=1 才走;既然操作者已经明说「我接受没有墙」,那么再单独禁掉建组织意义不大。
- 代价:
/auth/config 藏按钮而 API 放行,这个分叉长期存在;而且降级部署里建出来的组织边界是「声明了但没强制」——ADR-0049 最讨厌的那一类。
B. 闸门改判「实际生效的 posture」(tenancy?.posture ?? resolveTenancyPosture())。
倾向
倾向 A(即现状),因为降级已经是 OS_ALLOW_DEGRADED_TENANCY 的显式选择,B 的收益主要落在一个已经被 boot guard 拦住的形状上,却要付「OSS 部署失去建组织能力 + 丢掉 #3624 的 e2e 覆盖」这两笔。若要选 B,建议同时给 dogfood 一条别的开路方式(例如 verify harness 提供可注入的 tenancy stub),别让 #3624 的覆盖为此消失。
不指派 —— 按 Prime Directive #10 归档,等维护者定夺。
出处:#5233 的开发(会话 session_015W6nhsDrz6zWQc8je12a1t)。
从 #5233 的修复中分出来的一个需要维护者定夺的语义问题,#5233 本身没有改动它(那是纠正 knob,不是改能力边界)。
事实
修好 #5233 之后,
packages/plugins/plugin-auth/src/auth-manager.ts的两个站点读的是两个不同的事实,在一种部署形状下会分叉:organizationHooks.beforeCreateOrganizationpostureEnforcesWall(resolveTenancyPosture())/auth/config的features.multiOrgEnabledtenancy?.posture ?? resolveTenancyPosture()只有一种形状让两者不同 —— ADR-0093 D5 的降级态:请求了
isolated/group,但企业包@objectstack/organizations不在(org-scoping服务缺席),于是tenancy.posture解析为single且degraded=true。此时:isolated);/auth/config:multiOrgEnabled=false,console 把「创建组织」入口藏起来;这不是 #5233 引入的
降级前闸门读
resolveMultiOrgEnabled(),那同样是一个纯 env 读,在这里同样返回true、同样放行。#5233 只是把 knob 从被降级的布尔换成权威的 posture,分叉是原样保留的。已在packages/plugins/plugin-auth/src/org-create-posture-gate.test.ts里作为当前行为钉住(用例名带 "pinned as CURRENT behaviour"),所以无论怎么定夺,都必须是有意识地改这条断言。两个选项
A. 保持现状 —— 闸门判「请求的 posture」。
serve.ts的 D5 boot guard 同源(它也是resolveTenancyPosture() !== 'single'),两处口径一致。serve在降级时默认拒绝启动,要OS_ALLOW_DEGRADED_TENANCY=1才走;既然操作者已经明说「我接受没有墙」,那么再单独禁掉建组织意义不大。/auth/config藏按钮而 API 放行,这个分叉长期存在;而且降级部署里建出来的组织边界是「声明了但没强制」——ADR-0049 最讨厌的那一类。B. 闸门改判「实际生效的 posture」(
tenancy?.posture ?? resolveTenancyPosture())。packages/qa/dogfood/test/org-create-default-team.dogfood.test.ts(org creation over HTTP 500s when teams are enabled: better-auth 1.7.0-rc.1 default team carries memberCount, sys_team lacks the column/mapping #3624 的回归)靠的正是「boot 之后翻 env、闸门 live 读」这个技巧来打开路由;它跑在没有企业包的 workspace 里,选 B 之后任何 env 组合都过不了这道闸门,该 dogfood 只能改写或删掉,org creation over HTTP 500s when teams are enabled: better-auth 1.7.0-rc.1 default team carries memberCount, sys_team lacks the column/mapping #3624 的端到端覆盖随之丢失。倾向
倾向 A(即现状),因为降级已经是
OS_ALLOW_DEGRADED_TENANCY的显式选择,B 的收益主要落在一个已经被 boot guard 拦住的形状上,却要付「OSS 部署失去建组织能力 + 丢掉 #3624 的 e2e 覆盖」这两笔。若要选 B,建议同时给 dogfood 一条别的开路方式(例如 verify harness 提供可注入的 tenancy stub),别让 #3624 的覆盖为此消失。不指派 —— 按 Prime Directive #10 归档,等维护者定夺。
出处:#5233 的开发(会话
session_015W6nhsDrz6zWQc8je12a1t)。