Skip to content

fix(lint,metadata): 撤销 http.server 豁免 —— 它的理由本身是错的 (#4251) - #4382

Merged
os-zhuang merged 1 commit into
mainfrom
claude/4251-http-server-exemption
Jul 31, 2026
Merged

fix(lint,metadata): 撤销 http.server 豁免 —— 它的理由本身是错的 (#4251)#4382
os-zhuang merged 1 commit into
mainfrom
claude/4251-http-server-exemption

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

清单里的

那条豁免的理由是错的

#4321http.server 写进 UNCONTRACTED_SLOTS,理由写的是"不存在 IHttpServer 契约"。该契约存在 —— packages/spec/src/contracts/http-server.ts —— 而且写下这条豁免时,已经有 8 个调用点在用 getService<IHttpServer>(…)

豁免和别的断言一样是一个 claim,而这一条建立在没人核过的前提上 —— 正是这条规则本身要抓的那种形状

撤销之后露出 9 处

从未入列的文件7
已入列文件的计数增长2

两种基线都不能合法吸收。全部类型化到 IHttpServer;packages/metadata/src/plugin.ts 因此整个清空,基线下降到 168 站点 / 36 文件,并少掉一个文件。

8 个测试站点调 getPort()(契约上是可选成员),按契约写成 getPort!() —— 它们刚 bootstrap 完自己的 server,这个断言是准确的。

另外两点:已确认,只报告不改

http.serverhttp-server 是同一个实例的两个注册名。 plugin-hono-server 和 qa 的 node-plugin 各自并排注册两行;runtime 的 config.server 路径只注册带点的那个。metadata/src/plugin.ts?? 同时读两个 —— 这就是它一直没暴露的原因。本 PR 不删任何注册 —— 那是运行时行为变更,该由决定规范名的人来做。

IHttpServer 有两份定义,而且已经分叉。packages/spec/src/contracts/http-server.ts(15 个导入方)声明了 write?()end?();packages/core/src/contracts/http-server.ts(8 个导入方)没有。spec 那份是超集,也是 ledger 指向的那份,所以它是源;core 那份是过期的近似复制,应当改为 re-export。单独一个变更 —— 合并一份重复契约不是 lint 修复。

给写更宽 HTTP 契约的人留一条证据

getRawApp() 现在有了第三个独立消费方(metadata 的 HMR 路由,加上 cloud-connection 的两个)。它刻意不在 IHttpServer 上 —— 契约框架无关,raw app 是框架自己的句柄 —— 所以每个消费方各自具名声明。三个足够用来判断这是不是仍然是对的答案了。

验证

  • pnpm check:slot-lookup 强制模式:✓ 168 unswept site(s) in 36 file(s), none new;no files added(对 d92c72d)
  • eslint --no-inline-config 全部改动文件 —— 干净
  • metadata dts build 成功(该包在 type-check DEBT 名单,build 才是类型门 —— 这是上个 PR 的教训)
  • runtime995 / 68client204 / 15metadata281 / 13http-conformance46 / 2 —— 全绿

🤖 Generated with Claude Code

#4321 put `http.server` in UNCONTRACTED_SLOTS on the ground that "no
IHttpServer contract exists". The contract does exist
(packages/spec/src/contracts/http-server.ts) and eight call sites were
already resolving the slot as getService<IHttpServer>(...) when the
exemption was written. An exemption is a claim like any other, and this
one rested on a premise nobody checked -- the same shape as the gaps the
rule exists to find.
Revoked. That surfaced 9 erasures the exemption had been hiding: 7 in
files never grandfathered, 2 as count growth inside grandfathered ones,
none of which the baseline could legally absorb. All typed to
IHttpServer; packages/metadata/src/plugin.ts came out clean entirely, so
the baseline ratchets DOWN to 168 sites in 36 files and loses a file.
Confirmed and reported, not changed: `http.server` and `http-server` are
the SAME instance under two names (plugin-hono-server and qa/node-plugin
each register it twice, two lines apart; runtime's config.server path
registers only the dotted one) -- removing a registration is a runtime
change and belongs with whoever picks the canonical name. And
`IHttpServer` is defined TWICE and has already diverged: spec's (15
importers) declares write?()/end?(), core's (8 importers) does not. Spec's
is the superset and the one the ledger points at; core's is a stale
near-copy that should re-export it, in its own change.
Verified: ratchet holds (168/36, none new, no files added vs d92c72d);
eslint clean; metadata dts build succeeds; runtime 995/68, client 204/15,
metadata 281/13, http-conformance 46/2.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercelBot commented Jul 31, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 31, 2026 10:02am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

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

  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/metadata)
  • content/docs/kernel/cluster.mdx(via packages/metadata)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/metadata)
  • content/docs/plugins/packages.mdx(via @objectstack/metadata)
  • content/docs/protocol/kernel/metadata-service.mdx(via @objectstack/metadata)
  • content/docs/releases/v12.mdx(via @objectstack/metadata)
  • 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.

@os-zhuang
os-zhuang merged commit 10575f3 into mainJul 31, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/4251-http-server-exemption branch July 31, 2026 10:14
os-zhuang added a commit that referenced this pull request Jul 31, 2026
…erver 定为 canonical 并入账 ledger (#4251) (#4393)
* fix(spec,core,cloud-connection,metadata): one HTTP contract, one canonical slot name (#4251)
packages/core/src/contracts/ was a dead near-copy of the real contracts --
zero importers (no relative import, no subpath export, not a tsup entry;
core's barrel has re-exported the spec versions all along) -- and it had
already DIVERGED (spec's IHttpResponse grew write?/end?, IHttpRequest grew
rawBody?; the copy never did). Anyone who grepped into it read a stale
contract nothing enforces -- the both-humans-and-AI failure mode behind
the false http.server exemption (#4382). Deleted; zero-risk by
construction.
`http.server` is the canonical slot name and the ledger now says so:
ServiceSlotContracts gains 'http.server': IHttpServer plus the deprecated
'http-server' alias entry (same instance -- hono-plugin, qa node-plugin
and cloud's two server entrypoints all register both, alias commented
"backward compatibility"). Canonical is the only name on EVERY provider
path -- runtime's config.server path registers no alias, so the three
cloud-connection plugins reading the alias alone found an empty slot
there. All readers now go canonical-first with the alias as a fallback
that dies with the alias registrations; registrations untouched this
release, both sites carry the deprecation note.
getRawApp?(): any joins IHttpServer -- the deliberate framework-handle
escape, declared once with the rationale; four consumers declared it
locally before (cloud-connection x2, metadata HMR, cloud node-server),
and the local RawAppHost / HttpServerWithRawApp types are deleted.
IMetadataService.bulkRegister/bulkUnregister declare the write options
their implementation always accepted (bulkRegister's contract dropped the
MetadataWriteOptions half it intersects in; bulkUnregister declared no
options at all). Same shape as B2's IDataEngine read-methods gap.
Baseline 168 -> 167 (marketplace-install-local's lookup typed while
touched). Ledger test pins both slot entries and the alias equality.
Verified: spec build (dts) + 7192 tests / 281 files; core, metadata,
cloud-connection, plugin-hono-server dts builds; runtime 1001/69, rest
539/36, plugin-auth 579/26, plugin-sharing 226/11, service-settings
196/14, metadata 281/13, hono-server 135/12, http-conformance 46/2;
ratchet holds 167/36 none new; eslint clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(cloud-connection,metadata): the canonical-first read needs a per-name try -- getService throws on an empty slot (#4251)
CI caught the shape my local run could not (I built cloud-connection but ran
only metadata's tests -- cloud-connection's own suites mock a kernel that
registers ONLY the alias): `getService` THROWS for an unregistered slot, so
try { a = getService('http.server') ?? getService('http-server'); } catch {...}
never reaches the alias -- the first name's throw exits the whole try. Split
into a per-name try (readServer helper) in all four readers.
Worth recording: the pre-existing alias-first read in metadata/plugin.ts had
the SAME shape, so its `?? getService('http.server')` fallback never once
fired either -- a decorative fallback, the declared-vs-actual gap this work
line keeps finding, now actually implemented in both directions.
Verified serially (the earlier 6-file FAIL was local vitest concurrency noise
while spec's dts build ran in parallel -- single-file and serial reruns green):
cloud-connection 64/12, metadata 281/13, both dts builds, eslint clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang