在 #4910 (入站 rateLimit 接执行)的开工核查中发现,记录备查,未认领 。
基线:origin/main @ 2e284b2546。证据是真实 boot,不是 grep 推断 (pnpm dev -- --fresh -p 39147,showcase,47 plugins)。
事实
showcase 声明了两个 ApiEndpoint(examples/app-showcase/src/system/apis/index.ts),经 defineStack({ apis }) → ARTIFACT_FIELD_TO_TYPE.apis = 'api' 装进元数据。元数据端一切正常 :
$ curl -b cookies 'http://localhost:39147/api/v1/meta/api'
{"type":"api","items":[
{"name":"showcase_task_feed","path":"/api/v1/showcase/tasks","method":"GET",
"type":"object_operation","objectParams":{"object":"showcase_task","operation":"find"},
"authRequired":true,"cacheTtl":30, ...},
{"name":"showcase_inquiry_purge_api","path":"/api/v1/showcase/inquiries/purge","method":"POST",
"type":"flow","target":"showcase_inquiry_purge","authRequired":true, ...}]}
HTTP 200
执行端零命中 —— 同一个 boot、同一个会话 cookie:
GET /api/v1/showcase/tasks → HTTP 404 {"error":"Not found"}
POST /api/v1/showcase/inquiries/purge → HTTP 404 {"error":"Not found"}
GET /api/v1/data/showcase_task?top=1 → HTTP 200 ← 阳性对照,同 cookie 同 prefix
两处断链(任一都足以致死,现在两处同时存在)
① 路径从未挂载。 dispatcher-plugin.ts 逐条显式注册路由(/data、/meta、/ai/* 通配等),元数据声明的任意路径没有任何 catch-all 。/api/v1/showcase/tasks 根本进不了 dispatcher.dispatch(),直接落到 Hono 的 notFound —— 上面那个裸 {"error":"Not found"} 就是它,不是 dispatcher 的语义 404(routeNotFound)。
② 即便进得去,匹配器不存在。 http-dispatcher.ts:1646 的 handleApiEndpoint 这样开头:
const metaSvc = await this . resolveService ( 'metadata' , context . environmentId ) ;
if ( ! metaSvc || typeof ( metaSvc as any ) . matchEndpoint !== 'function' ) {
return { handled : false } ;
}
全仓 matchEndpoint 只有 3 处命中,全在 http-dispatcher.ts 自己身上 (1650 判断、1653 调用、1713 注释)。MetadataManager / NodeMetadataManager 都没有这个方法,任何 plugin 也没有补。所以这个分支恒等于 { handled: false } —— 是 grep 找得到、运行时永不执行的死代码,正是 ADR-0076「一条路由一个属主」小节点名的那类输入。
波及面:不止 rateLimit 一个键
ApiEndpointSchema(packages/spec/src/api/endpoint.zod.ts)的每一个键 都因此是 declared ≠ enforced,不只是 #4686 盯的 rateLimit:
键
声明语义
实际
path / method
路由地址
从未挂载
type / target / objectParams
执行目标
从未执行
authRequired
要求认证
零执行 (注意:这条是安全语义)
cacheTtl
响应缓存
零执行
inputMapping / outputMapping
出入参映射
零执行
rateLimit
限流
零执行(#4686 / #4910 )
summary / description
文档
未进 /openapi.json
examples/app-showcase/src/coverage.ts:181 目前写着这套「executed by the runtime dispatcher (handleApiEndpoint)」并把它记作已覆盖能力 —— 这是 Prime Directive #10 明令禁止的「advertise a capability the runtime doesn't deliver」,同 PR 要一并修正。
建议(协议级,留给维护者裁决,不要顺手做)
接上执行 :补 catch-all 挂载 + 在元数据服务上实现 matchEndpoint,并把 authRequired / cacheTtl / inputMapping / outputMapping 逐键接到执行器 —— 工作量远大于 「v17」入站 rateLimit 接执行:ApiEndpoint / HttpServer 的 RateLimitConfig 推导为 runtime token bucket 配置,dispatcher 生效(#4686 拆向之一) #4910 的设想,且 authRequired 的默认值(true)一旦真生效就是 breaking 面。
按 ADR-0049 整面摘除 :apis: 从 stack.zod.ts 退役,走完整退休套件,showcase 的两个端点改为已经能跑的 code-mounted 形式(src/system/server/ 里已有一个)。
先摘执行残骸 :保留声明面待日后实现,但删掉 handleApiEndpoint 这段永不执行的死代码 + LEGACY_CHAIN_PREFIXES 里的 /__api-endpoint 条目 + coverage.ts 的失实声明,让「未实现」变成响亮的缺席而不是看起来已实现。
⚠️ 这条阻塞 #4910 :#4910 要求「授权 rateLimit 配置经真实 dispatcher 路径产生 429」,而端点本身根本不经过 dispatcher。详见 #4910 的核查评论。
关联:#4686 、#4910 、ADR-0049、ADR-0076、Prime Directive #10 。
在 #4910(入站 rateLimit 接执行)的开工核查中发现,记录备查,未认领。
基线:
origin/main@2e284b2546。证据是真实 boot,不是 grep 推断(pnpm dev -- --fresh -p 39147,showcase,47 plugins)。事实
showcase 声明了两个
ApiEndpoint(examples/app-showcase/src/system/apis/index.ts),经defineStack({ apis })→ARTIFACT_FIELD_TO_TYPE.apis = 'api'装进元数据。元数据端一切正常:执行端零命中 —— 同一个 boot、同一个会话 cookie:
两处断链(任一都足以致死,现在两处同时存在)
① 路径从未挂载。
dispatcher-plugin.ts逐条显式注册路由(/data、/meta、/ai/*通配等),元数据声明的任意路径没有任何 catch-all。/api/v1/showcase/tasks根本进不了dispatcher.dispatch(),直接落到 Hono 的notFound—— 上面那个裸{"error":"Not found"}就是它,不是 dispatcher 的语义 404(routeNotFound)。② 即便进得去,匹配器不存在。
http-dispatcher.ts:1646的handleApiEndpoint这样开头:全仓
matchEndpoint只有 3 处命中,全在http-dispatcher.ts自己身上(1650 判断、1653 调用、1713 注释)。MetadataManager/NodeMetadataManager都没有这个方法,任何 plugin 也没有补。所以这个分支恒等于{ handled: false }—— 是 grep 找得到、运行时永不执行的死代码,正是 ADR-0076「一条路由一个属主」小节点名的那类输入。波及面:不止 rateLimit 一个键
ApiEndpointSchema(packages/spec/src/api/endpoint.zod.ts)的每一个键都因此是 declared ≠ enforced,不只是 #4686 盯的rateLimit:path/methodtype/target/objectParamsauthRequiredcacheTtlinputMapping/outputMappingrateLimitsummary/description/openapi.jsonexamples/app-showcase/src/coverage.ts:181目前写着这套「executed by the runtime dispatcher (handleApiEndpoint)」并把它记作已覆盖能力 —— 这是 Prime Directive #10 明令禁止的「advertise a capability the runtime doesn't deliver」,同 PR 要一并修正。建议(协议级,留给维护者裁决,不要顺手做)
matchEndpoint,并把authRequired/cacheTtl/inputMapping/outputMapping逐键接到执行器 —— 工作量远大于 「v17」入站 rateLimit 接执行:ApiEndpoint / HttpServer 的 RateLimitConfig 推导为 runtime token bucket 配置,dispatcher 生效(#4686 拆向之一) #4910 的设想,且authRequired的默认值(true)一旦真生效就是 breaking 面。apis:从stack.zod.ts退役,走完整退休套件,showcase 的两个端点改为已经能跑的 code-mounted 形式(src/system/server/里已有一个)。handleApiEndpoint这段永不执行的死代码 +LEGACY_CHAIN_PREFIXES里的/__api-endpoint条目 + coverage.ts 的失实声明,让「未实现」变成响亮的缺席而不是看起来已实现。关联:#4686、#4910、ADR-0049、ADR-0076、Prime Directive #10。