Skip to content

docs(runtime,metadata,rest): 摘除已失真的「structurally unreachable until the E7 flip」注释族 + 多租户 decline 分支补零覆盖 (#5399) - #5404

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5399-e-series-comment-truth
Aug 5, 2026
Merged

docs(runtime,metadata,rest): 摘除已失真的「structurally unreachable until the E7 flip」注释族 + 多租户 decline 分支补零覆盖 (#5399)#5404
baozhoutao merged 1 commit into
mainfrom
claude/issue-5399-e-series-comment-truth

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes #5399

父单 #5231 的实施子单(另一子单 #5244 已随 PR #5395 落地)。两节工作:纯注释修真(零行为变更) + E5b decline 分支补测

前提复核(逐处按 origin/main 核对,行号已全部漂移)

issue 立案时给的行号无一命中,#5385 重排过 runtime。翻转本身也复核了:issue 写的 d21c001 在本仓 无法解析(git log 报 unknown revision),但翻转确已落地 —— 权威在 packages/spec/src/api/endpoint-publish-gate.ts 开篇自述 "This module is that flip",并写明 #4936 的整体拒绝已被逐条形状把关取代。

issue 列出 origin/main 实际 判定
route-ledger.ts:298 :298-300 失真,已改
endpoint-executor.ts:31-34 :23-34(含 ## Nothing calls this yet 标题) 失真,已改
api-endpoint-step.ts:24-27 :20-26 失真,已改
endpoint-policy.ts:49-53 :49-53 失真,已改
dispatcher-plugin.ts:1430 :1428-1431 失真,已改
metadata-manager.ts:1551 :2163-2166 失真,已改
openapi-endpoints.ts:60,332 :58-63、:330-334 失真,已改

openapi-endpoints.ts 的「Today it emits nothing」确被 PR #5230 P9 反证:packages/qa/dogfood/test/showcase-declarative-endpoints.dogfood.test.ts:287-323 以真实 boot 断言 /openapi.jsonpaths 含 showcase 两条声明端点。

家族扫荡:7 处是抽样,实际 13 处

按 issue 要求做了全仓 grep(E7 flip / Structurally unreachable / til the #5040),列表外又找到 6 处同族,一并闭环:

  • packages/runtime/src/api-endpoint-step.test.ts:9
  • packages/runtime/src/api-mapping.test.ts:17
  • packages/runtime/src/dispatcher-plugin.endpoint-fallback.integration.test.ts:23
  • packages/runtime/src/dispatcher-plugin.tselse 分支(:1434-1439,见下)
  • packages/rest/src/openapi-endpoints.test.ts:13
  • packages/rest/src/rest-openapi-route.test.ts:81
  • packages/rest/src/rest-server.ts:2865

核过但不改的两处(措辞已是过去时,本来就成立):examples/app-showcase/src/coverage.ts:127(「the waiver stood from #4936 until the #5040 executor landed」)、packages/qa/dogfood/.../showcase-declarative-endpoints.dogfood.test.ts:8(「was built E1–E7 ... BEHIND a publish gate that made it structurally unreachable」)。

改写口径:描述当前事实并给出权威出处(发布闸门文件 / 真实 boot 探针),周围仍成立的散文原样保留。

⚠️ 一处越界,已另立 #5400 而非在本 PR 修

dispatcher-plugin.tselse 分支(适配器不暴露 setFallbackHandler 时)注释原文写着:

debug, not warn: no stack can declare an endpoint yet ... When that flip lands, THIS is where absence must become loud

这个条件句的触发条件已经发生。翻转后声明真实存在,该传输上它们静默不可服务,而唯一信号是默认 info 级别根本不打印的 debug。要让这条注释成真只有一条路 —— debugwarn —— 那是行为变更,超出本单(纯注释)范围。

故本 PR 只把该注释改写为「当前仍是 debug、且这是低估、由 #5400 跟进」的真话,级别本身留给 #5400。相关:#5122(runtime 的 HttpServer 包装器丢弃可选成员,使这个分支实践中更易走到)。

第二节:E5b decline 分支补测

新增 packages/runtime/src/dispatcher-plugin.multi-tenant-endpoint.integration.test.ts(4 例)。零覆盖属实:isMultiTenantHost 全仓仅 data-path-object.test.ts() = false 打桩,decline 分支无任何引用 —— 因为 kernel-resolver 提供方在 cloud,本仓只有消费者。

#5385 姿态以桩 resolver 驱动,但上移一层:该分支活在 plugin 的 setFallbackHandler 闭包里(不在 dispatcher 上),没有任何接缝能把它交出来,所以走 LiteKernel + 真 Hono + 真 socket,而不是复刻组合(ADR-0076「who serves this path」/ #4073 的教训)。已按 #5385 写在 context.kernel 的当前形状。

  • 解析成功:带 X-Environment-Id 的请求在自己的租户内核上执行,servedBy 只可能来自该租户;
  • 解析不出:裸 404 + warn + 完全不探 declaration(decline 必须发生在 match 之前,否则一个租户的声明会决定另一个租户的 URL)。

反向验证(先定方向再跑,结果与预测一致)

第一版是伪绿,已修正并记录在测试文件抬头。 初稿只在租户内核上声明端点;删掉 decline 分支重跑,预测「全红」而实际只有 warn 断言变红:宿主没有 metadata 槽位,该步会因另一个无关原因再次弃权,于是 404 与「未探测」两条断言恒真、什么也没证明。

改成宿主也声明同一条路径(并占住 automation)后再删分支重跑:

× answers the transport's own 404 and never probes the declaration
× declines an UNKNOWN environment the same way — a header is not a placement
AssertionError: expected 200 to be 404
Tests  2 failed | 2 passed (4)

红的正是该分支要挡的那件事 —— 无法归属的请求被从宿主内核答成了 200。恢复分支后 4/4 全绿。

验证

重活全走 flock /tmp/os-heavy-verify.lock + 4G 堆上限、scoped filter、--workspace-concurrency=2 前置。

pnpm --filter '@objectstack/runtime^...' build                                  # 新 worktree 先建依赖
pnpm --workspace-concurrency=2 --filter @objectstack/runtime --filter @objectstack/rest --filter @objectstack/metadata test
  → runtime  Test Files 92 passed (92) / Tests 1341 passed (1341)
  → rest     Test Files 43 passed (43) / Tests  652 passed (652)
  → metadata Test Files 22 passed (22) / Tests  478 passed (478)
pnpm ... typecheck  → runtime: tsc --noEmit 零错误(rest/metadata 无 typecheck 脚本,走覆盖率台账豁免)
node scripts/check-nul-bytes.mjs → OK (5418 files)
git diff --name-only | xargs grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]' → 无命中

消费半径:route-ledger 的 note:packages/client 的 ledger 覆盖测试消费(#5046 的教训:改动包之外的 fixture 才是漏网处),故一并跑了 client —— 首轮 3 个文件 collection 失败(Failed to resolve entry for package "@objectstack/runtime"),是新 worktree 未建依赖的 AGENTS.md §9 陷阱、非本改动;补 '@objectstack/client^...' build 后 Test Files 17 passed / Tests 222 passed

changeset

未加 changeset,请打 skip-changeset 标签 —— 与 PR #5395 同一口径。纯注释 + 纯测试,对包消费者零可见变更(AGENTS.md 也写明纯修正类不强制);不选空 frontmatter changeset 是因为 release.yml 记着 #4898:main 上只剩空 changeset 时 changesets 会打印 "All changesets are empty; not creating PR" 并白吃一轮发布。

边界


Generated by Claude Code

…able until the E7 flip" comment family + cover the multi-tenant decline branch (#5399)

The #5040 E7 publish flip landed (packages/spec/src/api/endpoint-publish-gate.ts
opens with "This module is that flip"), and E8 moved endpoints back into the
OpenAPI document. Thirteen comments across runtime/metadata/rest still asserted
the pre-flip world -- "Structurally unreachable today", "Nothing calls this yet",
"Today it emits nothing" -- which is exactly the #5078 defect: a comment that
contradicts the code in front of it.

Each site is rewritten to describe current reality and cite the authority
(the publish gate, or the real-boot probe in
packages/qa/dogfood/test/showcase-declarative-endpoints.dogfood.test.ts, whose
/openapi.json case disproves "emits nothing" directly). Surrounding still-true
prose is preserved. Pure comment change: the only non-comment line touched is a
descriptive `note:` string in the route ledger.

Also adds dispatcher-plugin.multi-tenant-endpoint.integration.test.ts, covering
the E5b branch "multi-tenant resolution finds no environment -> decline + warn",
which had zero test references repo-wide because the kernel-resolver PROVIDER
ships in the cloud distribution. A stub resolver drives a real boot over a real
socket: a placed request executes on its own tenant kernel; an unplaced one gets
the transport's bare 404, the warn, and no probe of any declaration.

The host kernel deliberately declares the same path too. Without that, the
decline cases pass vacuously -- verified by deleting the branch and re-running:
with tenant-only declarations only the warn assertion moved, because the step
declined a second time for an unrelated reason. With the host copy in place,
deleting the branch turns both decline cases red with "expected 200 to be 404",
the cross-tenant answer the branch exists to prevent.

Out of scope, filed as #5400: the sibling `else` branch still logs `debug` when
an adapter exposes no setFallbackHandler. Its own comment scheduled a move to
`warn` "when that flip lands" -- it has landed, so declared endpoints are now
silently unservable there -- but changing the level is a behavior change, so
this commit only makes the comment truthful and names the tracking issue.

Refs #5231, #5040, #5078, #5230, #5385

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VkPSGsX9o17MsGv3Lbxu2w
@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 8:11am

Request Review

@github-actions github-actions Bot added the tests label Aug 5, 2026
@baozhoutao baozhoutao added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed tests labels Aug 5, 2026 — with Claude
@github-actions github-actions Bot added the size/m label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/metadata, @objectstack/rest, @objectstack/runtime.

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

  • content/docs/ai/connect-mcp.mdx (via @objectstack/rest)
  • content/docs/api/client-sdk.mdx (via packages/runtime)
  • content/docs/api/error-handling-server.mdx (via @objectstack/rest)
  • content/docs/api/index.mdx (via @objectstack/rest, @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/metadata, @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 packages/metadata, @objectstack/runtime)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/metadata)
  • content/docs/permissions/authentication.mdx (via @objectstack/rest, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime)
  • content/docs/plugins/index.mdx (via @objectstack/rest)
  • content/docs/plugins/packages.mdx (via @objectstack/metadata, @objectstack/rest, @objectstack/runtime)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/rest, @objectstack/runtime)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/rest)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/metadata-service.mdx (via @objectstack/metadata)
  • content/docs/releases/implementation-status.mdx (via @objectstack/rest, @objectstack/runtime)
  • content/docs/releases/v12.mdx (via @objectstack/metadata, @objectstack/rest)
  • content/docs/releases/v17.mdx (via @objectstack/rest, @objectstack/runtime)
  • content/docs/releases/v9.mdx (via @objectstack/metadata)

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

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E 系列收尾本体:摘除已失真的「structurally unreachable」注释族 + 多租户 decline 分支补零覆盖(#5231 的实施子单)

2 participants