You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
于是同一路径有两个属主:rest 侧真能答,dispatcher 侧永远答不了。这正是 ADR-0076「路由与属主」第 1 条点名的形状 —— 「Never add a second implementation of a path that another package already serves… A shadowed duplicate is code that grep finds and the runtime never runs — the exact input that makes an agent (or a human) reason confidently from dead code.」
台账注记本身不准确
packages/runtime/src/route-ledger.ts:252:
{ route: 'GET /openapi.json', domain: '/openapi.json', disposition: 'server-only',
note: 'docs tooling; falls through when metadata service lacks a generator' },
「when metadata service lacks a generator」读起来像是有时有、有时没有。实际是从来没有任何 metadata service 提供过 generateOpenApi,所以是 100% fall through。ADR-0076 第 4 条(machine-readable surfaces must not lie)同样适用于这张台账。
判定这一点需要按 ADR-0076 结尾那句做:「boot the real composition with its real services, or do not claim an answer」—— 起一个真实 showcase boot,curl /api/v1/openapi.json,看返回的是文档还是 404。#4936 正是用这种实测(而非 grep 推断)定的性,建议本单沿用同法再定级。
在 #4936 / #4939 的实施(PR #5065)中,摘除
handleApiEndpoint死分支时,在紧邻的上一段代码里发现同一形状的第二处,记录备查,未认领。基线:
origin/main@a1a855a(PR #5065 的 merge 基线)。事实(逐条 grep 可复核)
packages/runtime/src/http-dispatcher.ts:1610起:generateOpenApi作为方法,全仓 + 两个兄弟仓零实现。 精确名 grep 命中仅 4 处:http-dispatcher.ts:1613/:1614packages/spec/src/api/documentation.zod.ts:481generateOpenApi: z.boolean(),一个配置布尔键,不是方法packages/spec/src/api/documentation.test.ts:475,544MetadataManager/NodeMetadataManager均无此方法;cloud、objectui两仓零命中。所以该if恒为 false —— 与 #4936 的matchEndpoint是同一类:grep 找得到、运行时永不执行。但这条路由并非无人服务 —— 这才是重点
packages/rest/src/rest-server.ts:2523起真实提供该路由,而且实现是完整的:GET {basePath}/openapi.json→ enriched OpenAPI document;@objectstack/spec/openapi.json惰性加载(rest-server.ts:2683拼json-schema/openapi.json),该产物由gen:openapi生成、并在 spec 的exports里作为./openapi.json导出;packages/rest/src/rest-route-ledger.ts:79有对应台账行(source: 'route-manager')。于是同一路径有两个属主:rest 侧真能答,dispatcher 侧永远答不了。这正是 ADR-0076「路由与属主」第 1 条点名的形状 —— 「Never add a second implementation of a path that another package already serves… A shadowed duplicate is code that
grepfinds and the runtime never runs — the exact input that makes an agent (or a human) reason confidently from dead code.」台账注记本身不准确
packages/runtime/src/route-ledger.ts:252:「when metadata service lacks a generator」读起来像是有时有、有时没有。实际是从来没有任何 metadata service 提供过
generateOpenApi,所以是 100% fall through。ADR-0076 第 4 条(machine-readable surfaces must not lie)同样适用于这张台账。我没有验证的一点(不要当成已证事实)
两个属主在真实 composition 下谁先接到请求,我没有实测。这决定了严重度:
if后直接落到this.routeNotFound(cleanPath)(handled: true的语义 404),用户拿到 404,而 rest 侧那份文档根本没机会出场 —— 这就是用户可见缺陷。判定这一点需要按 ADR-0076 结尾那句做:「boot the real composition with its real services, or do not claim an answer」—— 起一个真实 showcase boot,
curl /api/v1/openapi.json,看返回的是文档还是 404。#4936 正是用这种实测(而非 grep 推断)定的性,建议本单沿用同法再定级。建议处置(供分诊,未预设)
无论上面哪种结果,dispatcher 那段都应删除 —— 它没有任何情况下是正确属主,
/openapi.json的真实实现在packages/rest。随之:route-ledger.ts的/openapi.json行与LEGACY_CHAIN_PREFIXES条目一并处理(它们描述的是 dispatcher 侧,而非 rest 侧那张已有台账);关联
apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936 /ApiRegistry/api-registryplugin 只在packages/core/examples/里被装配,无任何真实 composition 挂载 ——ApiEndpointRegistrationSchema因此整面零执行 #4939 / PR feat(spec,core,runtime)!: 声明式apis:响亮拒绝 + ApiRegistry 整面退役 (#4936, #4939) #5065 —— 同一类(声明 ≠ 执行)的相邻实例,本单在其实施中发现;dispatcher 的handleApiEndpoint已在该 PR 删除,本段是它紧邻的上一个if,未在该 PR 范围内(feat(spec,core,runtime)!: 声明式apis:响亮拒绝 + ApiRegistry 整面退役 (#4936, #4939) #5065 的 scope 严格限定为apis:与ApiRegistry)。gen:openapi是 AGENTS.md 点名的「两个完全无门禁的生成器」之一(另一个是gen:sbom),即没有任何检查确认json-schema/openapi.json是最新的 —— 与本单相关但属独立问题。Generated by Claude Code