fix(cli): 启动 banner 的 Tenancy: 改读 resolveTenancyPosture(),不再打印被取代的布尔 (#4801) - #4994
Merged
Merged
Conversation
…egacy boolean (#4801) [ADR-0105 D1] `OS_TENANCY_POSTURE` is the authoritative tenancy knob and `OS_MULTI_ORG_ENABLED` survives only as the fallback `resolveTenancyPosture()` consults when the posture is unset. serve's runtime wiring already keys off the posture, but the banner's `Tenancy:` row printed a boolean sourced from `resolveMultiOrgEnabled()` — two sources for one fact. Booting with `OS_TENANCY_POSTURE=isolated` alone printed `Tenancy: single-tenant` one line above a plugin table listing `Organizations` (cloud#1020): the diagnostic surface contradicted the runtime it describes. - `ServerReadyOptions.multiTenant` (boolean) → `tenancyPosture: TenancyPosture`, printed verbatim (`single` / `group` / `isolated`). The boolean is removed rather than kept as a compat field: with the posture authoritative it could only be a field the printer ignores, and typing the replacement as `TenancyPosture` makes the old wiring a compile error instead of a plausible-looking wrong line. `group` was never expressible as a boolean. - serve passes `resolveTenancyPosture()` — the same call the wiring uses — and no longer imports `resolveMultiOrgEnabled` at all. - `format.tenancy.test.ts` pins the invariant "printed token IS `resolveTenancyPosture()`" across posture-set/boolean-unset, posture-unset/ boolean-true, both-set-and-contradicting (both directions), legacy `multi`, and `group`; two `@ts-expect-error` directives pin the shape at typecheck. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
xuyushun441-sys
marked this pull request as ready for review
August 3, 2026 19:06
xuyushun441-sys
enabled auto-merge
August 3, 2026 19:06
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 #4801
为什么读 posture 而不是布尔
ADR-0105 D1 之后,
OS_TENANCY_POSTURE是权威 knob,布尔OS_MULTI_ORG_ENABLED只是resolveTenancyPosture()在 posture unset 时的回退。serve的运行时接线(serve.ts里挂@objectstack/organizations的那段)早就读resolveTenancyPosture(),但 banner 的Tenancy:行读的是resolveMultiOrgEnabled()返回的布尔 —— 同一个事实两个来源,于是它们漂了:这不是显示美化。这是「声明与执行不一致」(ADR-0049 那一类)落在诊断面上 —— 最坏的落点:一个可能撒谎的 banner,会让此后每一次排障都多花一轮去确认它有没有撒谎。cloud#1020 里就是靠人工比对插件表才发现的。
Tenancy:现在直接打印 posture 名(single/group/isolated),来源是运行时接线用的同一个resolveTenancyPosture()调用。布尔字段的去留:删除,不保留兼容项
ServerReadyOptions.multiTenant?: boolean→tenancyPosture?: TenancyPosture。理由有三条,按重要性:multiTenant就填了个布尔进去,完全合理,而结果是错的。tenancyPosture的类型是TenancyPosture,resolveMultiOrgEnabled()返回boolean—— 现在把 banner 接回旧 knob 无法通过编译,而不是产出一行看起来很合理的错话。这是本仓「在源头就不给出错的机会」的取向:结构上防止,而不是消费端兜底。group的拼法 —— 一个group部署只可能被误报。压扁本身就是漂移藏身的地方。影响面为零:
format.ts没有从@objectstack/cli的入口 re-export,ServerReadyOptions是包内部接口;全仓printServerReady只有serve.ts一个调用点(已改齐,并顺手从 import 里去掉了因此不再使用的resolveMultiOrgEnabled)。测试:三种场景 + 反向验证
新增
packages/cli/src/utils/format.tenancy.test.ts。被断言的性质不是「这行看起来对」,而是 banner 与resolveTenancyPosture()不可能不一致:每个用例都从环境变量算出resolveTenancyPosture(),再断言打印出的 token 就是它。覆盖(前三条即议题点名的三种):
OS_TENANCY_POSTUREOS_MULTI_ORG_ENABLEDisolatedTenancy: isolatedtrueTenancy: isolatedsingletrueTenancy: singleisolatedfalseTenancy: isolatedgroupTenancy: groupTenancy: singlemultiTenancy: isolated外加:省略 posture 时整行不打印;任何 posture 下输出都不再出现
multi-tenant/single-tenant措辞(先断言该行存在再断言它不含旧措辞 —— 一个没有Tenancy:行的 banner 会让not.toMatch空转通过,那和本文件要抓的 bug 从外部看一模一样);以及两条@ts-expect-error,在pnpm typecheck而非 review 阶段钉住形状。反向验证(把
format.tsstash 回改前,只留新测试与调用点)(注:上面这轮跑的是加强前的版本,当时「never flattens」那条空转通过;已按上一段所述改成先断言行存在。)
改动在位后:
两条
@ts-expect-error也做了同样的反向验证 —— 去掉其中一条,tsc 立刻报出被它挡住的那个错,证明指令是承重的而非装饰:其它验证
npx eslint packages/cli/src/utils/format.ts packages/cli/src/utils/format.tenancy.test.ts packages/cli/src/commands/serve.ts→ 干净(无输出)。pnpm --filter @objectstack/cli typecheck会报一批TS2307: Cannot find module '@objectstack/runtime' | '@objectstack/core' | …,这是工作区未构建 dist 的既有环境噪音(在未改动的origin/main树上同样复现),与本改动无关。改动涉及的两个文件已用一份把@objectstack/spec/@objectstack/types映射到源码的 tsconfig 单独tsc --noEmit过,结果零错误;CI 会先构建再 typecheck,是权威一轮。src/utils/里 7 个测试文件在本地因同样的未构建依赖而 collect 失败,sqlite-occupancy.test.ts有 1 条环境相关失败 —— 均已通过 stash 全部改动、在等同origin/main的树上复跑确认为既有失败(Tests 1 failed | 14 passed,一字不差)。边界
只做 banner 这半块。未触碰
serve.ts里的 tenancy 守卫逻辑(#4818 / PR #4858 刚改过),也未触碰 cloud#1020 那边仍在等维护者拍板的许可闸门决策 —— 正如议题开头所写,banner 无论那个决策怎么落都该修。已附 changeset(@objectstack/clipatch,CLI 输出为用户可见变化)。Generated by Claude Code