由 #7019 的区域测量顺带看到(PD #10 另立卡)。⛔ 不要捎带在能力门 PR 里改 —— 混进去会让那个 PR 的评审面失控。
三种形状(全部在 packages/rest/src/rest-server.ts,逐条实测)
handler
代码
信封
POST /meta/_migrate-stored
:3765-3770
{ error: { code: 'FORBIDDEN', message } } —— 嵌套,符合 ADR-0112
DELETE /meta/:type/:name
:4697
{ error: 'Reset operation not supported by protocol implementation' } —— 裸字符串,无 code
PUT /meta/:type/:section/:name
:4996
{ error: 'Save operation not supported by protocol implementation', code: 'NOT_IMPLEMENTED' } —— code 是兄弟键,不是嵌套
三个 handler 在同一个文件 里,彼此相隔数百行,同属 /meta 前缀。
实测原文:
:4996 res.status(501).json({ error: 'Save operation not supported by protocol implementation', code: 'NOT_IMPLEMENTED' });
:4697 res.status(501).json({
error: 'Reset operation not supported by protocol implementation',
});
为什么这不只是「不好看」
对调用方而言,读 code 的客户端代码在这三条路由上要写三种取法:err.error.code、(取不到)、err.code。任何一种统一写法都会在另外两条上静默取到 undefined —— 而 undefined 走的是「没有 code」分支,不是报错分支。这正是 Prime Directive #12 说的「生产者即契约」被破坏的形状:消费者被迫用 ?? 容忍生产者的不一致。
分级建议:finding,今天没有用户会撞到
两条不合规的都是 501 分支 —— 只在 protocol 实现缺方法时才走到。出厂 protocol 实现两个方法都有,所以默认部署上这两个分支不可达。但 它们是模板:下一个照抄相邻 handler 的人会照抄哪一种,取决于他滚到了哪一行。
收口方向(留给 triage,不预设)
只把两条 501 改成 ADR-0112 嵌套形状(最小,不动别处)。
顺带查 rest-server.ts 里其余 res.status(...).json({ error: ... }) 的全部命中点,一次性收口(规模未测,该文件 8500+ 行 —— 见 [finding] ADR-0076 D11 的第二半从未落地:packages/rest/src/rest-server.ts 已 8593 行(ADR 记录约 5.1k),且无 issue 承接 #5949 )。
让信封有一个共享构造函数,把手写 res.status().json() 从这些路由里消掉(结构性,规模最大)。
未实测(勿当事实引用)
关联
#7019 (本 finding 的来源;那张卡只 加能力门,不 改信封)· #6603 / #7027 · ADR-0112(错误信封与标准码目录)· Prime Directive #12 · #5949 (rest-server.ts 体量)
由 #7019 的区域测量顺带看到(PD #10 另立卡)。⛔ 不要捎带在能力门 PR 里改 —— 混进去会让那个 PR 的评审面失控。
三种形状(全部在
packages/rest/src/rest-server.ts,逐条实测)POST /meta/_migrate-stored:3765-3770{ error: { code: 'FORBIDDEN', message } }—— 嵌套,符合 ADR-0112DELETE /meta/:type/:name:4697{ error: 'Reset operation not supported by protocol implementation' }—— 裸字符串,无codePUT /meta/:type/:section/:name:4996{ error: 'Save operation not supported by protocol implementation', code: 'NOT_IMPLEMENTED' }——code是兄弟键,不是嵌套三个 handler 在同一个文件里,彼此相隔数百行,同属
/meta前缀。实测原文:
为什么这不只是「不好看」
对调用方而言,读
code的客户端代码在这三条路由上要写三种取法:err.error.code、(取不到)、err.code。任何一种统一写法都会在另外两条上静默取到undefined—— 而undefined走的是「没有 code」分支,不是报错分支。这正是 Prime Directive #12 说的「生产者即契约」被破坏的形状:消费者被迫用??容忍生产者的不一致。分级建议:
finding,今天没有用户会撞到两条不合规的都是 501 分支 —— 只在 protocol 实现缺方法时才走到。出厂 protocol 实现两个方法都有,所以默认部署上这两个分支不可达。但它们是模板:下一个照抄相邻 handler 的人会照抄哪一种,取决于他滚到了哪一行。
收口方向(留给 triage,不预设)
rest-server.ts里其余res.status(...).json({ error: ... })的全部命中点,一次性收口(规模未测,该文件 8500+ 行 —— 见 [finding] ADR-0076 D11 的第二半从未落地:packages/rest/src/rest-server.ts已 8593 行(ADR 记录约 5.1k),且无 issue 承接 #5949)。res.status().json()从这些路由里消掉(结构性,规模最大)。未实测(勿当事实引用)
NOT_IMPLEMENTED更合适的既有码,以及NOT_IMPLEMENTED是否已在目录中 —— 未查。packages/runtime/src/domains/meta.ts的 dispatcher 侧信封形状看起来又是第三种(finding:POST /packages/:id/publish-drafts整包 draft 批量转正,零能力的已认证调用方即可调用(实测 200 vs 同族_migrate-stored403) #7023 普查记为{code:'PERMISSION_DENIED', httpStatus:403},code在顶层且带httpStatus)。本卡未实测 dispatcher 侧,只记 REST 侧三条;若要一次收口需先把 dispatcher 侧也量一遍。关联
#7019(本 finding 的来源;那张卡只加能力门,不改信封)· #6603 / #7027 · ADR-0112(错误信封与标准码目录)· Prime Directive #12 · #5949(
rest-server.ts体量)