Skip to content

gen:openapi 的 base spec 用 7 条手写 path 描述路由面,与 rest 真实路由无任何对账 —— 漂移了不会红(#5168 的剩余那一半) #5456

Description

@os-zhuang

观察类发现,在 #5168(PR 见该单)实施中量到,越范围,未认领。基线:origin/main @ ed0d2aac0

今天没有用户会撞到(实测未漂移),所以按 #4949finding、不进 pm:queue,严重度交分诊定级。

背景:#5168 只补了「自洽」,没补「对账」

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 都要真的产出),接在生成器内部、写盘之前。这条 ledger 记的是另一件事——「与真实路由对账」——#5168 没有碰,本单单独记。

事实

packages/spec/scripts/build-openapi.tsgenerateCrudPaths / generateMetadataPaths / generateDiscoveryPaths 三个函数把路由面手写成 7 条 path:

/api/{object}                  get, post
/api/{object}/{id}             delete, get, put
/api/meta                      get
/api/meta/types                get
/api/meta/{type}               get
/api/meta/{type}/{name}        get
/api/.well-known/objectstack   get

这 7 条是模板;真实 boot 时 packages/rest 的 enrichment 把 {object} 展开成约 199 条 path 并并入声明式端点(#5078 实测)。也就是说模板本身是这份文档描述路由面的唯一事实来源,而它与 packages/rest 的实际路由注册之间没有任何一处代码或测试做对账。

后果是单向静默:rest 侧新增、改名或退役一条内建路由时,base spec 不会自动跟随,也不会有任何门禁发现两边不一致 —— 发布出去的 GET /api/v1/openapi.json 会少描述(或多描述)一条路由,而 pnpm buildcheck:generated、所有 rest 测试全绿。

当前未漂移:上面 7 条与今天的路由面一致,所以这是休眠缺口而不是在场缺陷。正因为没红过,它也从没被验证过能红。

顺带澄清一个提法(可能影响 #5078 旁注的定级)

#5168#5078 都把 gen:openapi 的缺口顺带描述成「产物是否最新」。实测:packages/spec/json-schema/.gitignore:61,产物不入库,每次 pnpm build(gen:schema && gen:openapi && tsup)重新生成,并通过 files + exports["./openapi.json"] 随包发布。

因此「最新性门」在这里没有对象 —— 没有入库快照可以相对源码变陈旧。gen:sbom 同理(ledger 自己的 why 就写了它是 release 时产物)。ledger 里 gen:openapi 那条 why 的措辞是准的(说的是 routes 对账),把它读成「最新性」是本仓另外两处旁注的失准点,建议分诊时按「对账」而不是「最新性」来定级。

(与 #5371 不同:那单是 gen:schemarmSync 抹掉 gen:openapi 产物导致 rest 路由测试假红,是产物生命周期问题;本单是内容与路由的一致性问题。)

可能的处置方向(未预设,供分诊)

  1. 让 base spec 从 packages/rest 的路由台账(rest-route-ledger.ts,该文件自述「唯一台账行一直是准的」)派生这 7 条模板,而不是手写 —— 单一事实来源,漂移在结构上不可能;
  2. 保留手写,但加一条对账断言:模板集合与台账声明的内建路由集合必须双向相等,不等即非零退出。比 1 便宜,但两处仍需各自正确;
  3. 判定这 7 条模板是「文档面刻意的简化视图」,把它显式写进注释并降级为不需要对账 —— 若是这个结论,ledger 里那条 why 应当一并改写,否则它会一直宣称一个没人打算补的缺口。

跨包(packages/spec 的生成器读 packages/rest 的台账)是否可接受、以及 1 与 2 之间怎么选,属于契约面的决定,本单不预设。

关联

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions