发现于 #5112 (#5040 E8 收官验收)的真实 boot 探针,不在该单文件面内 ,按 Prime Directive #10 单独立项。
事实(showcase 真实 boot,objectstack dev --fresh,47 plugins)
通过 Studio 的元数据写入口写一条 api 条目 —— 注意这是匿名且未计量 的形状(ADR-0121 D6 明令禁止的那一种):
PUT /api/v1/meta/api/e8_backdoor
{"name":"e8_backdoor","path":"/api/v1/apps/showcase/backdoor","method":"GET",
"type":"object_operation","target":"showcase_task",
"objectParams":{"object":"showcase_task","operation":"find"},"authRequired":false}
→ HTTP/1.1 200 OK
{"success":true,"version":"sha256:9ad721f4...","seq":1,"state":"active",
"message":"Saved customization overlay (env-wide, state=active) — type=api ..."}
写入成功。随后:
GET /api/v1/apps/showcase/backdoor (匿名) → 404 {"error":"Not found"}
GET /api/v1/apps/showcase/backdoor (已鉴权) → 404 {"error":"Not found"}
GET /api/v1/meta/api → 三条,含
- e8_backdoor GET /api/v1/apps/showcase/backdoor authRequired=False
GET /api/v1/openapi.json → paths 含 /api/v1/apps/showcase/backdoor:
{"get":{"operationId":"e8_backdoor","responses":{"200":{"description":"Success"}},"security":[]}}
路由 404,而两个机器可读面都在宣告它存在 —— 且 OpenAPI 用 security: [] 明确把它描述成「不需要凭据」的公开端点。
为什么会这样(不是 E7b 的门在挡)
两边读的是两个不同的库 :
所以这条路由死掉不是 因为 #5189 /#5203 的装载期门把它拒了 —— 那道门压根没被走到(dev 日志里没有 [EndpointMatcher] ... EXCLUDED 那行)。E7b 的门依然正确且必要;这里是它下面还有一层看不见。
影响的两个方向
面在说谎(本条的主症) :/openapi.json 是 SDK / codegen / AI 客户端直接生成代码的契约面(Route & surface ownership 第 4 条、ADR-0076 D12)。一个被宣告为匿名可达、实际 404 的端点,会传播进所有基于它构建的东西。
反方向同样成立 :一条合法的、本应服务的 端点如果是通过 Studio / 运行时写入(而非 stack artifact)落库的,匹配器同样看不见 —— 作者被告知 "Saved",面上也能看到,唯独请求 404。当前净行为是 fail-closed(安全),但「声明了却不生效」正是 声明式 apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint 全仓无实现 #4936 这条线一直在还的债。
建议的判断轴(不预设结论)
三条的长期代价不同,请维护者裁决 —— 中间那条最省,但它把「面不说谎」变成了「面自己去问匹配器」,是唯一不引入第二真相源的形状。
复现
pnpm dev:showcase -- --fresh -p 39720 --seed-admin
# 登录取 token,然后照上面三条 curl
关联:#5040 (执行器立项)、#5112 (E8 验收,发现于此)、#5189 /#5203 (E7b 兜底门)、ADR-0076 §1/§4、ADR-0121 D6。
发现于 #5112(#5040 E8 收官验收)的真实 boot 探针,不在该单文件面内,按 Prime Directive #10 单独立项。
事实(showcase 真实 boot,
objectstack dev --fresh,47 plugins)通过 Studio 的元数据写入口写一条
api条目 —— 注意这是匿名且未计量的形状(ADR-0121 D6 明令禁止的那一种):写入成功。随后:
路由 404,而两个机器可读面都在宣告它存在 —— 且 OpenAPI 用
security: []明确把它描述成「不需要凭据」的公开端点。为什么会这样(不是 E7b 的门在挡)
两边读的是两个不同的库:
IMetadataService.matchEndpoint→EndpointMatcher→MetadataManager.listForIndex('api'),只读 manager 自己的registry+ 已注册 loader。dev/serve 的 manager 上 loaders 是["filesystem","memory"],sys_metadata行根本不在其中(实测:registry.get('api')为 undefined,list('api')长度 0,而同一时刻/meta/api返回 2 条)。/meta/:type与/openapi.json(17.x 立项:建设声明式 ApiEndpoint 执行器(挂载 + matchEndpoint + authRequired/cacheTtl/inputMapping/outputMapping 逐键接线) #5040 E6 的 enrichment)都走protocol.getMetaItems,读的是 ObjectQL SchemaRegistry +sys_metadata。所以这条路由死掉不是因为 #5189/#5203 的装载期门把它拒了 —— 那道门压根没被走到(dev 日志里没有
[EndpointMatcher] ... EXCLUDED那行)。E7b 的门依然正确且必要;这里是它下面还有一层看不见。影响的两个方向
/openapi.json是 SDK / codegen / AI 客户端直接生成代码的契约面(Route & surface ownership 第 4 条、ADR-0076 D12)。一个被宣告为匿名可达、实际 404 的端点,会传播进所有基于它构建的东西。apis:(ApiEndpoint)入站面全链路零执行:元数据装载成功、路由从未挂载、matchEndpoint全仓无实现 #4936 这条线一直在还的债。建议的判断轴(不预设结论)
matchEndpoint的取数与getMetaItems收敛到同一个源(一条路由一个所有者的元数据版本);/meta/api走匹配器的索引);api条目(与 MetadataManager.publishPackage 不经 E7 端点门 —— ADR-0121 D6「匿名须限流」在 Studio 发布路径上不成立 #5189 的 publish 门同侧)。三条的长期代价不同,请维护者裁决 —— 中间那条最省,但它把「面不说谎」变成了「面自己去问匹配器」,是唯一不引入第二真相源的形状。
复现
关联:#5040(执行器立项)、#5112(E8 验收,发现于此)、#5189/#5203(E7b 兜底门)、ADR-0076 §1/§4、ADR-0121 D6。