Skip to content

fix(runtime): 无 setFallbackHandler 的适配器改以 warn 宣告声明式端点不可达 (#5400) - #5409

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5400-dispatcher-fallback-warn
Aug 5, 2026
Merged

fix(runtime): 无 setFallbackHandler 的适配器改以 warn 宣告声明式端点不可达 (#5400)#5409
baozhoutao merged 1 commit into
mainfrom
claude/issue-5400-dispatcher-fallback-warn

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5400

前提核对(先于实现)

issue 引用的是 f417863fc,已过时 —— 今晨 #5404(#5399)刚改写过这处注释。以 origin/main(4b61cf3)为准逐条核对,前提全部成立:

即:声明能发布、能被声明的端点在无接缝的适配器上永久不可服务、而唯一信号不打印 —— 三段齐备。

改了什么

setFallbackHandler 是 metadata 声明的 apis: 端点抵达 handler 的唯一接缝,且在 IHttpServer 上是可选成员(契约明写消费者用 typeof === 'function' 探测)。适配器不暴露它时没有第二条路:所有声明的端点永久不可服务,调用方只拿到传输层的裸 404 —— 与拼错路径毫无区别。

一行级别改动,并按 AGENTS.md「Absence must be loud」(Route & surface ownership §3)的要求让这条日志同时带上两半:

  • 后果 —— 该传输上任何 metadata 声明的 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「级别由门禁焊住」姿态:

  1. 缺接缝时发一条、且级别为 warn —— 退回 debug 或误升 error 都红;
  2. 文案含后果(metadata-declared / `apis:` / UNREACHABLE / bare 404);
  3. 文案含补救(setFallbackHandler / @objectstack/plugin-hono-server);
  4. meta 带受影响挂载前缀;
  5. 反向用例 —— 适配器暴露接缝时这条完全不出声(保证 warn 是信号而非启动噪音,改发的是 Declarative endpoint dispatch step armed)。

反向验证(方向先于执行预判)

预判为常规 Red 方向,理由写在测试文件头:断言读的是发出级别这一谓词,而非可能「因为什么都没产出而通过」的计数。实测两个方向都焊住:

  • 改回 ctx.logger.debug4 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.tsTest Files 1 passed (1) / Tests 5 passed (5)
  • runtime 全量 npx vitest run --maxWorkers=2Test Files 93 passed (93) / Tests 1346 passed (1346)(92 → 93 即本 PR 新增文件)
  • pnpm --filter '@objectstack/runtime' typecheck → exit 0
  • 门禁:check:durability-log-level / check:nul-bytes / check:startup-registry-verdict / check:wildcard-fallthrough / check:route-envelope 全 PASS

范围

packages/runtime/src/dispatcher-plugin.ts + 新增测试 + changeset。⛔ 未触碰 #5122HttpServer 包装器本体(相邻但独立,另单处理)。无 API / schema / 路由变更;已在合规适配器上的部署看不到任何新增输出。

🤖 Generated with Claude Code

https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh


Generated by Claude Code

`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
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 5, 2026 9:03am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/runtime.

21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via packages/runtime)
  • content/docs/api/index.mdx (via @objectstack/runtime)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/runtime)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx (via packages/runtime)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/runtime)
  • content/docs/kernel/cluster.mdx (via @objectstack/runtime)
  • content/docs/permissions/authentication.mdx (via @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime)
  • content/docs/plugins/packages.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime)
  • content/docs/releases/implementation-status.mdx (via @objectstack/runtime)
  • content/docs/releases/v17.mdx (via @objectstack/runtime)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E7 翻转后,「适配器无 setFallbackHandler」仍只记 debug —— 声明式端点静默不可达,而代码注释自己写明此时应转 warn

2 participants