docs(runtime): ADR-0076 D11 四条在场锚点入账 —— registry + dispatcher 门序 + 两个代表域 (#5357) - #5940
Conversation
…代表域 (#5357) D11 的产物是一整片实打实的代码(14 个域模块 + `DomainHandlerRegistry` + 收缩后的 dispatcher),而 `scripts/adr-anchors.json` 里对 ADR-0076 零命中 —— 被治理的文件 自己不提它所遵从的决定,作者就无从知晓(#3723 的机制)。 按 `check-adr-anchors.mjs` 自己的纪律选点("a map of everything is a map of nothing,每条锚点必须挣得它的失败模式"),不锚全部 14 个域,只锚四处「单看文件会 觉得可以『优化』掉、而改了会静默逆转 D11」的落点,每处的失败模式互不重复: 1. `domain-handler-registry.ts` —— 端口本体:规范化 handler 而非框架特定路由 (从插件空间注册 Hono `app.route` 会让每个插件耦合 Hono,葬掉 http-conformance 验证的多适配器性质);无通配/无参数/无中间件是刻意的;注册权留在 dispatcher, 因为多数槽位是多提供方(i18n、analytics),搬进某一个提供方会 404 掉其它栈; `DomainHandlerDeps` 的每个读内核设施都先收请求(#5155 的跨租户读)。 2. `http-dispatcher.ts` —— `dispatch()` 里两处「像是可以省掉的开销」的次序: scope 解析 + ADR-0069 认证门 + 成员门跑在域注册表**之前**;注册表跑在 if 链 之前,而 if 链现在对域是空的、必须保持空的(one route, one owner)。 3. `domains/data.ts` —— 代表域之一,D11 的收尾一刀,也正是 ADR 点名的 god implementation 核心 `handleData`;失败模式是把域体折回 dispatcher 的薄委托。 4. `domains/i18n.ts` —— 代表域之二,注册权归属规则的具体实例:该槽位由 service-i18n 或 AppPlugin 内存兜底二者之一填充,把 `/i18n` 注册搬进 service-i18n 这个「看起来天然正确」的清理,会 404 掉另一提供方服务的每个栈。 失败文案携带不变量(违反了什么决定、为什么不能这么改),不是只写 ADR id。 代码面只加注释:`http-dispatcher.ts` 的门序不变量此前在门旁无任何文字(现有的 ADR-0076 提及都在别处),`domains/data.ts` 补一句「域体留在这里」。逻辑零改动。 `rest-server.ts` 的 7693 行实现问题按分诊不属本单,未触碰。 Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 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:
|
|
两点收尾更正/补充,记在这里而不是改正文:
另核对了一处选点时顺手起疑的地方,结论是无缺陷、不需要 issue: Generated by Claude Code |
Closes #5357
ADR-0076 在
scripts/adr-anchors.json中此前对0076零命中(实测锚点数 30,issue 正文记的 26 是 8-05 的快照;零命中这一前提在本 worktree 的基线origin/maina6b3ee7 上复核仍成立),而 D11 的产物是一整片实打实的代码:14 个域模块、DomainHandlerRegistry、收缩到约 1.9k 行的 dispatcher。缺的就是「在场门」这一层:被治理的文件自己不提它所遵从的决定,作者就无从知晓(#3723 的机制)。选点判据(判断题,不是清单题)
check-adr-anchors.mjs自己的纪律是 "Do not anchor everything; a map of everything is a map of nothing, and each entry must earn its failure mode."。所以不锚全部 14 个域,只锚四处满足「单看文件会觉得可以合理地『优化』掉,而改了会静默逆转 D11」的落点,且四处的失败模式互不重复:packages/runtime/src/domain-handler-registry.tspackages/runtime/src/http-dispatcher.tsstartsWith分支packages/runtime/src/domains/data.tsHttpDispatcher.handleData那个薄委托("这层间接没买到任何东西")packages/runtime/src/domains/i18n.ts/i18n的注册搬进 service-i18n("拥有该能力的包理应拥有自己的路由")四条失败文案都携带不变量——违反了哪条决定、为什么不能这么改——而不是只写一个 ADR id。要点分别是:
app.route会让每个插件耦合 Hono,葬掉packages/qa/http-conformance在第二个零依赖node:http适配器上验证过的多适配器性质);无通配、无参数、无中间件是刻意的,路由能力属于端口下方的适配器;注册权留在 dispatcher,因为多数槽位是多提供方(i18n由 service-i18n 或 AppPlugin 内存兜底填充,analytics由 service-analytics 或 ObjectQLPlugin 兜底填充),路由桥的是槽位不是包,搬进某一个提供方就 404 掉由另一个提供方服务的每个栈;DomainHandlerDeps的每个读内核设施都先收请求(HttpDispatcher 把「本请求解析出的 kernel」存在实例字段上(this.kernel),多租户 host 上并发请求会互相串改 #5155:一台主机只造一个 dispatcher,缓存"当前请求的内核"会让 await 之后恢复的请求读到另一租户的数据源)。GET /openapi.json与apis:的handleApiEndpoint当初是被删掉而不是被修好的,E6(#5040 执行器):endpoint 文档进 rest-server enrichment 管线 + 摘除 dispatchergenerateOpenApi死分支 + 修正台账注记(并入 #5078) #5093 / 声明式apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936)。domains/data.ts是 D11 step ③ 的收尾一刀,也正是 ADR 描述 god implementation 时点名的那个 handler;多租户的 428 属于域体本身而非上游门。domains/i18n.ts是注册权归属规则的具体实例(多提供方槽位),同时刻意保留了 legacy 的match: 'prefix'粗糙边(/i18nxx也匹配),规范化它是要由 http-conformance 重新钉的行为变更,不是能顺手塞进无关 diff 的整理。文件面(逻辑零改动)
scripts/adr-anchors.json:+4 条锚点(30 → 34)。packages/runtime/src/http-dispatcher.ts:仅注释。四个锚点文件本来都已提及ADR-0076(无需补头注),但门序不变量此前在三道门旁没有任何文字——本文件现有的 10 处 ADR-0076 提及都在别处,所以在dispatch()的门段补了一段注释把不变量写在它生效的地方。packages/runtime/src/domains/data.ts:仅注释,一句「域体留在这里」+ 折回薄委托的后果。rest-server.ts的 7693 行实现问题(分诊明令不属本单),未触碰content/docs/releases/**。验证
反向验证(方向先预判,再跑)
预判红:这道门是纯在场检查,
domains/data.ts恰好只有 1 处ADR-0076提及(新增注释里写的是 "D11 invariant",不含 id),删掉它必然红一条且只红一条。实测一致:失败输出把不变量整段带了出来(而非只叫人把字符串粘回去),这正是这道门的价值所在;恢复后复绿。
顺带实测了这道门的粒度,并如实记录:
domains/i18n.ts有 2 处提及(D11 头注 + 第 44 行的 D12),只删头注那处仍然绿,两处都删才红。也就是说在场门守的是"文件仍然指向这个决定",不是"某一行注释仍在原位"——它不能替代行为门,门序与路由归属的行为面仍由http-dispatcher.*.test.ts(multi-tenant-concurrency / kernel-resolver / requireauth)与route-ledger.conformance.test.ts守。这与脚本自己的声明一致:"It does NOT verify the code still obeys the ADR."无发布物
仅治理账本 + 注释行,不改任何包的行为,故不写 changeset,需要
skip-changeset标签(建 PR 后立即回读并写并集)。Generated by Claude Code