docs(deployment): 按 ADR-0105 D1 三态 posture 重写 tenancy-modes 页 - #5361
Merged
Conversation
整页此前按 ADR-0105 D1 之前的世界写:两态 tenancy mode、`OS_MULTI_ORG_ENABLED` 当开关、`TenancyService.mode`、只提 `isolated` 的降级 FATAL 文案;对权威 knob `OS_TENANCY_POSTURE` 全页 grep 零命中。 重写以 `single` / `group` / `isolated` 三态为主线,遗留布尔降为「posture 未设时 才读的回落输入」,并逐条对码核证: - posture 解析优先级表(posture 已设则完全不读布尔;`multi` 别名;非法值抛错不回落) - 两种有墙 posture 都需要企业版 `@objectstack/organizations` 才能激活,也都会降级 - `tenancy` 服务快照改为 `posture` / `requestedPosture` 双事实,`os:check` 块从 `@objectstack/spec/security` 导入真实的 `TenancyPosture`,漂移即编译失败 - `/auth/config` 的 `tenancyPosture` / `multiOrgEnabled` / `degradedTenancy`, 以及 `organization/create` 闸门读的是**生效** posture(#5233 / #5261) - 启动闸门区分 import 阶段(可被 `OS_ALLOW_DEGRADED_TENANCY` 放行)与 mount 阶段 (不可放行),降级告警是黄色而非原文所写的红色 - 环境变量表补 `OS_TENANCY_POSTURE` / `OS_AUTH_MEMBERSHIP_POLICY`,并修正 `OS_ORG_LIMIT` 的口径(计的是自己拥有的组织,被邀请加入的不计) 纯文档,不改任何 `packages/**` 源码;changeset 空 frontmatter,releases nothing。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FTszibd6C8sUCCZnM4VcrL
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
os-zhuang
marked this pull request as ready for review
August 5, 2026 00:51
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5269
前提复核(先于动手)
issue 正文的前提在
origin/main@c89d18c16上成立:content/docs/deployment/tenancy-modes.mdx对权威 knobOS_TENANCY_POSTUREgrep 零命中,整页按 ADR-0105 D1 之前的两态世界写。原文点名的三处(L21 「Enabled byOS_MULTI_ORG_ENABLED=true」、L41requested: boolean // OS_MULTI_ORG_ENABLED、L100/L109 的 FATAL 文案)逐条对上,行号未漂移。核证过程中另外查出四处原文与代码不符,一并修掉(详见下方逐断言核证表):
TenancyService的字段形状早已不是mode;降级告警是黄色不是原文写的红色;「wildcardtenant_isolationRLS is stripped」的说法在 ADR-0095 D1 之后不再准确;OS_ORG_LIMIT计的是自己拥有的组织而非「创建过的」。改了什么
单文件
content/docs/deployment/tenancy-modes.mdx,以single/group/isolated三态为主线重写,遗留布尔降为「posture 未设时才读的回落输入」:organization_id、是否需要企业版 runtime、默认组织归属、组织管理 UI。multi是isolated的旧拼法;布尔只有在 posture 未设时才读,且「除大小写不敏感的false以外的任何值」都算开;非法值抛错而不回落。@objectstack/organizations才能激活,org-scoping可用supportedPostures进一步收窄,开核对未列出的 posture fail closed。tenancy服务快照 —— 改为posture/requestedPosture双事实(原文的mode: 'single' | 'multi'字段已不存在),并说明「墙立不起来就不算墙」。该os:check代码块现在从@objectstack/spec/security导入真实的TenancyPosture,posture 集合一旦漂移就编译失败。/auth/config与组织创建闸门 ——tenancyPosture/multiOrgEnabled/degradedTenancy三个 feature,以及闸门读的是生效 posture(organization/create 的闸门读的是被降级的 OS_MULTI_ORG_ENABLED,不是权威的 OS_TENANCY_POSTURE —— 只设权威 knob 的有墙部署,引导式「创建工作区」是死路 #5233 / organization/create 的闸门判「请求的 posture」还是「实际生效的 posture」?降级部署(D5)下两者分叉,闸门放行而 /auth/config 隐藏 #5261),因此降级部署也会拒绝建组织。OS_ALLOW_DEGRADED_TENANCY可放行)与 mount 阶段(不可放行);FATAL 文案按serve.ts现文照抄;降级告警更正为黄色。defaultOrgId()在任何有墙请求(含降级)下都返回null的理由;策略来源补齐三处(AuthPlugin选项 /auth.membership_policy设置 /OS_AUTH_MEMBERSHIP_POLICY)。OS_TENANCY_POSTURE、OS_AUTH_MEMBERSHIP_POLICY,并修正OS_ORG_LIMIT口径。不碰
content/docs/references/**、content/docs/releases/、任何packages/**源码。content/docs/deployment/environment-variables.mdx只作参照,未编辑。逐断言对码核证(#1085 方法论,行号均为
origin/main@ c89d18c)packages/types/src/env.ts:145-162(posture 已设走normalizeTenancyPosture,未设才resolveMultiOrgEnabled() ? 'isolated' : 'single')false即开」、空串也算开packages/types/src/env.ts:119-122+readEnvWithDeprecationenv.ts:52-86(只有undefined才算未设)packages/types/src/env.ts:150multi旧拼法 =isolated;trim + 小写packages/spec/src/security/tenancy-posture.ts:107-112packages/types/src/env.ts:152-158packages/spec/src/security/tenancy-posture.ts:40-55, 80-82;packages/plugins/plugin-security/src/tenant-layer.ts:34-39, 99-119, 139-145plugin-security/src/tenant-layer.ts:103-112single下平台自带 tenant RLS 被剥、应用自写的保留并 fail closedplugin-security/src/security-plugin.ts:572-575(ADR-0105 D3)organization_id是企业版的活、校验留在开核packages/spec/src/security/tenancy-posture.ts:57-71;.changeset/adr-0105-group-posture-entitlement.mdplugin-auth/src/tenancy-service.ts:196-207supportedPostures收窄、未声明则两种都给packages/spec/src/security/tenancy-posture.ts:84-99;plugin-auth/src/tenancy-service.ts:200-202、auth-plugin.ts:478-489TenancyService字段形状plugin-auth/src/tenancy-service.ts:53-98, 209-239single+degradedplugin-auth/src/tenancy-service.ts:219-226/auth/config三个 featureplugin-auth/src/auth-manager.ts:3341-3344, 3368-3383single时 403plugin-auth/src/auth-manager.ts:1915-1937, 3249-3261single归 plugin-auth,有墙归企业版plugin-auth/src/auth-plugin.ts:807-813multiOrgEnabled决定plugin-auth/src/auth-manager.ts:3321-3328, 3373plugin-auth/src/reconcile-membership.ts:199-254;auth-plugin.ts:337-341defaultOrgId()在任何有墙请求下返回null(含降级)plugin-auth/src/tenancy-service.ts:78-97, 227-238plugin-auth/src/auth-manager.ts:2694-2712;auth-plugin.ts:1114-1122;reconcile-membership.ts:63-71, 199-216auto下跑,OS_SKIP_MEMBERSHIP_BACKFILL=1退出plugin-auth/src/reconcile-membership.ts:277-292;auth-plugin.ts:852-891packages/cli/src/commands/serve.ts:1842-1855packages/cli/src/commands/serve.ts:1876-1912packages/cli/src/commands/serve.ts:1860-1866(chalk.yellow)packages/cli/src/commands/serve.ts:1829-1841OS_ALLOW_DEGRADED_TENANCY接受1/true/on/yespackages/types/src/env.ts:175-179OS_ORG_LIMIT计自己拥有的组织plugin-auth/src/auth-manager.ts:1862-1880;packages/types/src/env.ts:296-309一处刻意收窄的措辞
environment-variables.mdx:85写「An unrecognized value refuses to boot」。静态追踪下来这句只对了一半:非法 posture 的第一次抛错落在serve.ts的 AuthPlugin 大try里(catch 在serve.ts:1942-1948,只打一句黄字警告就继续),真正的退出发生在 banner 阶段serve.ts:2716二次解析、经外层 catchserve.ts:2764-2773才exit(1)——那时runtime.start()早已绑定端口。所以本页写的是可证的窄断言:解析抛错、os serve报错并以非零码退出,没有替 ADR 说「fail-fast」这种代码没做到的话。顺序问题另开 #5359 记录,不在本 PR 修。验证
node scripts/check-nul-bytes.mjs→OK (scanned 5368 tracked text file(s) … no raw NUL bytes);另按控制字符纪律自扫grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]',零命中node scripts/check-doc-authoring.mjs→✓ 362 files cleannode scripts/docs-audit/check-audit-scope.mjs→✓ scope is in sync … 178 hand-written doc(s)node scripts/check-role-word.mjs→OK (43 baselined file(s), no new occurrences)(首版用了role: owner被这道门拦下,已改写)node scripts/check-adr-anchors.mjs→OK (26 anchored file(s))pnpm --filter @objectstack/spec run check:skill-examples→✅ 204 prose examples type-check against @objectstack/spec,其中包含本页新块content/docs/deployment/tenancy-modes.mdx:112TenancyPostureNOPE,同一道门变红并精确指到本页112:15——error TS2724: '"@objectstack/spec/security"' has no exported member named 'TenancyPostureNOPE'。证明这个os:check块是真的在对 spec 编译,而不是空过。已还原pnpm --filter @objectstack/spec run check:docs→✅ 239 generated files in sync with packages/spec(顺带产生的packages/spec/authorable-surface.base.json改动已还原,未提交)@mdx-js/mdx@3.1.1单文件编译通过(本页与参照页均 OK)Changeset
加了空 frontmatter changeset(
.changeset/tenancy-modes-doc-posture-rewrite.md):纯文档改动,不改任何包的行为,不该触发版本号;空 frontmatter 正是仓库认可的「本 PR releases nothing」声明,Check Changeset门只数本 PR 新增的.changeset/*.md,因此照样通过。顺带记录的框外发现(未在本 PR 修)
OS_TENANCY_POSTURE的「拒绝启动」实际发生在端口已监听之后 —— 第一次抛错被 serve.ts 的 AuthPlugin 宽 catch 吞掉 #5359 —— 非法OS_TENANCY_POSTURE的「拒绝启动」实际发生在端口已监听之后,第一次抛错被 AuthPlugin 的宽 catch 吞成「AuthPlugin failed to load」tenancy-service.ts的degraded注释仍说「只有 isolated 会降级」—— 与同文件 120 行后的实现和 ADR-0105 D12 修正相反 #5360 ——tenancy-service.ts:74-76的degraded注释仍说「只有 isolated 会降级」,与同文件196-226的实现和 ADR-0105 D12 修正相反(finding,纯注释)🤖 Generated with Claude Code
https://claude.ai/code/session_01FTszibd6C8sUCCZnM4VcrL
Generated by Claude Code