Skip to content

发布出去的 /api/v1/openapi.json 描述的 built-in 路由一条都不存在 —— 10 个 operation 真实 boot 全部 404(证伪 #5456 的「当前未漂移」) #5588

Description

@baozhoutao

发布出去的 GET /api/v1/openapi.json 里,built-in 路由那一段描述的每一条路径都不存在。真实 boot 逐条探测,文档里的路径全部 404;真实路由在另一个前缀上。任何人拿这份文档生成客户端,生成出来的客户端每一个数据调用都会 404。

基线:origin/main @ 5acb93add。在 #5456 的前提复核中量到(#5456 的 body 断言「当前未漂移,7 条与今天的路由面一致」——该断言被本单证伪),按 Prime Directive #10 单独立单。

真实 boot 实测

pnpm dev:crm -- --fresh -p 39177
GET /api/v1/openapi.json  →  200, 151 paths({object} 已按 CRM 对象展开)

逐条探测文档描述的路径 vs 真实路由:

文档里的(展开后)路径                     真实结果
/api/crm_contact                       404   {"error":"Not found"}
/api/meta                              404   {"error":"Not found"}
/api/meta/types                        404   {"error":"Not found"}
/api/.well-known/objectstack           404   {"error":"Not found"}

真实路由                                  结果(401 = 路由在,鉴权挡住)
/api/v1/data/crm_contact               401   {"error":"UNAUTHENTICATED",...}
/api/v1/meta                           401
/api/v1/discovery                      200
/.well-known/objectstack               200   ← dispatcher 在根上服务,不在 /api 下

动词也错。文档写 PUT {object}/{id},真实是 PATCH——服务器对 PUT 明确回 405:

PUT   /api/v1/data/crm_contact/xyz   →  405
PATCH /api/v1/data/crm_contact/xyz   →  401

逐条对照

packages/spec/scripts/build-openapi.tsgenerateCrudPaths / generateMetadataPaths / generateDiscoveryPathsbasePath = '/api' 手写出 7 条 path / 10 个 operation:

base spec operation 真实 rest 路由 判定
GET /api/{object} GET /api/v1/data/:object 路径错(缺 /v1、缺 /data)
POST /api/{object} POST /api/v1/data/:object 路径错
GET /api/{object}/{id} GET /api/v1/data/:object/:id 路径错
PUT /api/{object}/{id} PATCH /api/v1/data/:object/:id 路径错 且动词错(PUT 回 405)
DELETE /api/{object}/{id} DELETE /api/v1/data/:object/:id 路径错
GET /api/meta GET /api/v1/meta 路径错(缺 /v1)
GET /api/meta/types 全仓没有这条路由 描述了一条谁都不服务的路由(最接近的是 GET /api/v1/meta,它返回 types)
GET /api/meta/{type} GET /api/v1/meta/:type 路径错(缺 /v1)
GET /api/meta/{type}/{name} GET /api/v1/meta/:type/:name 路径错(缺 /v1)
GET /api/.well-known/objectstack rest 没有这条路由 dispatcher(packages/runtime/src/dispatcher-plugin.ts:658)在根路径 /.well-known/objectstack 上服务;rest 的 discovery 是 GET /api/v1 + GET /api/v1/discovery

字面比对:0/10 命中。补 /v1/data 之后仍有 3/10 对不上。

反方向同样不等:RestServer.getRoutes() + 两个 direct-mount registrar 枚举出 91 条真实路由;即使只看 base spec 自称覆盖的三个 ledger family(crud 6 + metadata 17 + discovery 2 = 25 条),文档也只描述了 10 个 operation。

为什么没被发现

serve 期的 enrichment(rest-server.ts registerOpenApiEndpoints)只做四件事:覆写 servers[0](只写 origin,不含 basePath)、展开 {object}、合并声明式端点、覆写 info.version没有任何一步重写 path 前缀。而 check:generated 的收尾台账把 gen:openapi 记为无门禁({ gen: 'gen:openapi', why: 'the OpenAPI document is generated but no check gate compares it to the routes' }),#5168 补的是产物自洽门($ref 能解析、schema 不降级),不看路由。所以两边各自「正确」,合起来全错,全绿。

现有测试还把错误形状钉住了:packages/rest/src/rest-openapi-route.test.ts:125 断言 body.paths['/api/{object}']['x-template'] === true —— 它证明了服务出去的文档字面上就带着 /api/{object}

处置需要一次契约裁决(本单不预设)

注意 apiPath可配置的(api.apiPath ?? api.basePath + '/' + api.version,rest-server.ts:2830),所以 packages/spec 里的静态 JSON 原则上无法对所有部署写对前缀——今天写 /api 只是错得更彻底,写死 /api/v1 也只是对默认部署正确。

关联

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions