fix(runtime): 无 setFallbackHandler 的适配器改以 warn 宣告声明式端点不可达 (#5400) - #5409
Merged
Conversation
`setFallbackHandler` 是 metadata 声明的 `apis:` 端点抵达 handler 的**唯一**接缝, 且在 `IHttpServer` 上是可选成员。适配器不暴露它时,所有声明的端点永久不可服务, 调用方只拿到传输层的裸 404 —— 与拼错路径毫无区别。 此前这条只记 `debug`。该级别曾经是对的:在非空 `apis:` 于发布期被整体拒绝(#4936) 的年代,没有任何部署可能"缺"什么,因为没有任何部署能声明什么。#5040 E7 发布翻转 终结了这个前提 —— 声明现在能发布,stack 也确实在发。而默认 `level: 'info'` 根本 不打印 `debug`(`packages/core/src/logger.ts` 的 `isEnabled`),运维侧等于零信号, 正是 AGENTS.md「Absence must be loud」(Route & surface ownership §3)点名要避免的 「留一个裸 404 让人去诊断」。 因此升为 `warn`,并按该节要求让这一行同时带上两半: - **后果** —— 该传输上任何 metadata 声明的 `apis:` 端点都不会被服务,只会回裸 404; - **补救** —— 换用实现了 `setFallbackHandler` 的 HTTP 适配器 (如 `@objectstack/plugin-hono-server`)。 刻意是 `warn` 而非 `error`:按「Degradation log levels」那个唯一判据 —— 降级后系统 对外看着正常,而它声称已持久化的东西其实没落盘吗? —— 答案是否,这里没有任何持久化 承诺。属功能性降级(某能力没挂上,下一个调用它的人自然会发现),与参考文案 「scheduled flows will not run until a job service is registered」同形。 新增 `dispatcher-plugin.fallback-absence-warn.test.ts` 把级别焊死(参照 #5226 「级别由门禁焊住」姿态):级别退回 `debug` 或误升 `error` 都会红,并另钉一条反向 用例 —— 合规适配器上这条完全不出声,保证 warn 是信号而非启动噪音。 反向验证(方向先于执行预判,属常规 Red 方向,因断言读的是发出级别这一**谓词**, 而非可能"因为什么都没产出而通过"的计数): - 改回 `debug` → 1-4 号用例红(`expected 'debug' to be 'warn'`),5 号仍绿; - 升到 `error` → 同样 1-4 号红(`expected 'error' to be 'warn'`)。 仅运维可见:无 API / schema / 路由变更,已在合规适配器(默认 `@objectstack/plugin-hono-server`)上的部署看不到任何新增输出。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh
|
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:
|
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 #5400
前提核对(先于实现)
issue 引用的是
f417863fc,已过时 —— 今晨 #5404(#5399)刚改写过这处注释。以origin/main(4b61cf3)为准逐条核对,前提全部成立:packages/runtime/src/dispatcher-plugin.ts该else分支仍是ctx.logger.debug,注释自述「Stilldebug, and that is now UNDER-STATED — tracked by E7 翻转后,「适配器无 setFallbackHandler」仍只记 debug —— 声明式端点静默不可达,而代码注释自己写明此时应转 warn #5400」;packages/spec/src/api/endpoint-publish-gate.ts开篇即「This module is that flip」,非空apis:不再被整体拒绝;packages/core/src/logger.ts的isEnabled为LEVEL_ORDER[level] >= LEVEL_ORDER[this.config.level],默认level: 'info'下debug根本不打印。即:声明能发布、能被声明的端点在无接缝的适配器上永久不可服务、而唯一信号不打印 —— 三段齐备。
改了什么
setFallbackHandler是 metadata 声明的apis:端点抵达 handler 的唯一接缝,且在IHttpServer上是可选成员(契约明写消费者用typeof === 'function'探测)。适配器不暴露它时没有第二条路:所有声明的端点永久不可服务,调用方只拿到传输层的裸 404 —— 与拼错路径毫无区别。一行级别改动,并按 AGENTS.md「Absence must be loud」(Route & surface ownership §3)的要求让这条日志同时带上两半:
apis:端点都不会被服务,只会回裸 404;setFallbackHandler的 HTTP 适配器(如@objectstack/plugin-hono-server)。附带
{ mount, declarativeEndpoints: 'unreachable' }结构化 meta,便于机读。原处注释一并改写为翻转后的真话(不留 #5404 那版「当前仍是 debug」的过期叙事),并记下级别选择的理由。
为什么是
warn而不是error按「Degradation log levels」那个唯一判据 —— 降级后系统对外看着正常,而它声称已持久化的东西其实没落盘吗? —— 答案是否:这里没有任何持久化承诺。属功能性降级(某能力没挂上,下一个调用它的人自然会发现),与该节参考文案「scheduled flows will not run until a job service is registered」同形。故
warn,不升error。钉级别的测试
新增
packages/runtime/src/dispatcher-plugin.fallback-absence-warn.test.ts(5 例,均显式}, 60_000)),参照 #5226「级别由门禁焊住」姿态:warn—— 退回debug或误升error都红;metadata-declared/`apis:`/UNREACHABLE/bare 404);setFallbackHandler/@objectstack/plugin-hono-server);Declarative endpoint dispatch step armed)。反向验证(方向先于执行预判)
预判为常规 Red 方向,理由写在测试文件头:断言读的是发出级别这一谓词,而非可能「因为什么都没产出而通过」的计数。实测两个方向都焊住:
ctx.logger.debug→4 failed | 1 passed,AssertionError: expected 'debug' to be 'warn',5 号(合规适配器静默)仍绿 —— 符合预判;ctx.logger.error→ 同样4 failed | 1 passed,AssertionError: expected 'error' to be 'warn'。随后已还原为
warn并复跑全绿。消费半径巡检
按「按规则的消费半径扫 fixture」逐一核过所有装载 dispatcher 的用例:走真实 Hono 适配器的(接缝存在,不进该分支)与用假 server 的(logger 为 no-op,无 warn 断言)均不受影响;全仓无第二处引用旧文案。
验证
npx vitest run --maxWorkers=2 src/dispatcher-plugin.fallback-absence-warn.test.ts→Test Files 1 passed (1)/Tests 5 passed (5)npx vitest run --maxWorkers=2→Test Files 93 passed (93)/Tests 1346 passed (1346)(92 → 93 即本 PR 新增文件)pnpm --filter '@objectstack/runtime' typecheck→ exit 0check:durability-log-level/check:nul-bytes/check:startup-registry-verdict/check:wildcard-fallthrough/check:route-envelope全 PASS范围
仅
packages/runtime/src/dispatcher-plugin.ts+ 新增测试 + changeset。⛔ 未触碰 #5122 的HttpServer包装器本体(相邻但独立,另单处理)。无 API / schema / 路由变更;已在合规适配器上的部署看不到任何新增输出。🤖 Generated with Claude Code
https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh
Generated by Claude Code