Skip to content

artifact 下载的 error 槽混装本地铸造与平台分类码 —— error === "cancelled" 是同形第三实例 #970

Description

@jinjunnn

这是什么

#963(alpha-cloud-schedules)与 #965(model-recovery)修的是同一类缺陷:控制流拿另一个仓决定的错误字符串比字面量。修法都是把控制流接到结构化的 res.status 上,让呈现字符串只管展示。

ac#965 的实施计划原本断言这一类「已枚举闭合、production 里恰好两个实例」,并把 alpha-artifact-download.ts 的 error === "cancelled" 列为「不属于该类 —— 那个字符串由本地铸造,是我们自己拥有的封闭集」。

这半句不成立,对抗审计把它证伪了,#965 的 PR 已按实话改写。本票登记真实情况。

事实(实读 alpha@41a408218 后代)

同一个 error 字段有两个铸造来源:

  • 本地铸造:packages/ui-mac/src/main/alpha-artifact-download.ts:294 / :323 / :329 / :383 / :401 → { ok: false, error: "cancelled" }
  • 咽喉铸造(平台决定):packages/ui-mac/src/main/alpha-artifact-download.ts:455
    if (!res.ok) return discardAnd(res, { ok: false, error: await httpErrorCode(res) })

而 cancelled 完全匹配 platform-error-code.ts:15 的 CLASSIFICATION_CODE = /^[a-z][a-z0-9_]{2,63}$/。

消费方是两处用户可见的控制流,形状与 #965 逐字同构:(订正 2026-08-14:实为一处,且漏了第三个读取点 —— 见文末订正块)

  • packages/ui-mac/src/renderer/alpha-ui/artifact-workbench/artifact-workbench.tsx:274 — } else if (r.error === "cancelled") {
  • packages/ui-mac/src/renderer/alpha-ui/session-rail/artifacts/session-rail-artifacts.tsx:215 — } else if (result.error === "cancelled") {

⇒ 这是该类的第三个实例,不是「不属于该类」。

今天可达吗

不可达。 要踩到它,alpha-platform 必须在 artifact content 路由上回一个带 code: "cancelled" 的拒绝 —— 与 #965 同级的「还没被踩到的雷」。用户会看到的坏结果:一次服务端拒绝被显示成「你取消了」,下载静默消失而没有错误提示。

为什么单独开票

#965 只覆盖 account 面,把 artifact 面一起改会超出那张 P3 的 S 票。真正的代价是记录为假:一份写成「已闭合」的枚举正是下一个实例隐形的机制(枚举对新成员默认放行),而这一类已经实证发生过两次(#918→#940、#963→#965)。

AC

  1. alpha-artifact-download.ts 的失败信封在 HTTP 拒绝臂带出结构槽 status(照 #963/#965 已合入的 { error, status? } 同形),本地铸造的 "cancelled" 不带 status。(订正 2026-08-14:改为「本地取消由只有 main 写得进的结构槽 cancelled?: true 表达」—— 见文末订正块)
  2. 两个 renderer 消费点区分「服务端拒绝」与「本地取消」的依据不再是 error === "cancelled" 这个字符串可被平台伪造的比较。
  3. 判据从假 fetch 驱动生产函数一路跑到消费点的分流结果(只断纯函数会漏掉分流层);正向夹具是~~「平台回 403 且 code: "cancelled"」~~「平台回 409 且 code: "cancelled"」(订正 2026-08-14:403 产生不了碰撞 —— 见文末订正块),期望不是取消态。
  4. 绕过演练:删掉结构槽 ⇒ 判据翻红。

Refs #965


订正块(2026-08-14,PR #989 实测)

本票原文有三处被执行证伪。按仓内约定:原文划掉保留,订正写在这里,其余各处由本块点名覆盖。

① AC3 的正向夹具「403 + code:"cancelled"」产生不了碰撞。
403 被 packages/ui-mac/src/main/alpha-artifact-download.ts:451 提前拦成 {error:"forbidden"},根本到不了咽喉。实测 12 个状态码:只有 400/409/410/416/429/5xx 到得了咽喉并碰撞;401/403/404/413 各自被本地早退臂吃掉。
照原文写出来的判据改前改后都绿——PR #989 的绕过演练 ③ 直接跑出来了:把夹具换回 403 且删掉前置断言 ⇒ 32 pass / 0 fail。
已改用 409(该路由今天真的在这个状态上带 code:alpha-platform packages/gateway/src/routes/cloud-jobs.ts:383 的 artifact_digest_mismatch)。

② 「消费方是两处用户可见的控制流」实为一处;另外漏了第三个读取点。
ArtifactWorkbench 组件自 #662(a44c3decf,2026-07-28 下线整页工作台)起零 importer、零挂载点 —— 两条独立检索轴(符号名 + 模块路径)在 packages/ docs/ scripts/ 全域各只命中它自己的定义行。⇒ artifact-workbench.tsx:274 是死代码,今天用户到不了;真正用户可达的只有 session-rail-artifacts.tsx:215。
漏掉的第三个读取点:packages/ui-mac/src/main/alpha-cloud-jobs.ts:220 的 outcome.error !== "cancelled"(日志抑制)也在比同一个字符串,PR #989 一并修。
死组件的删除另开 #990。

③ AC1 的修法从 status 改成「只有 main 写得进的结构槽 cancelled?: true」(编排者裁决)。
两个方案都挡得住今天这个缺陷。选后者的理由:status 方案的消费判据仍是合取式(status === undefined && error === "cancelled"),控制流依旧拴在字符串上,且不闭合「本地铸造被改名」那个方向;结构槽方案修完连判据都消失。
反方向如实记下(不藏起这个取舍):status 是咽喉形 —— 在 :449-455 一处函数里凡由 HTTP 派生的分类码全体被打标,新成员默认受保护;cancelled?: true 是枚举形,只保护这一件事实。其余同样能通过 CLASSIFICATION_CODE 的单词形本地名(network / disk / forbidden / unauthorized / retryable)哪天被拿来做控制流,就是第四个实例 —— 整类的咽喉闸已另开 #991(blocked-by #962/#968)。

仍然成立的:缺陷本体真实存在(两个信封逐字节相同,用执行证明);「今天不可达」成立(alpha-platform@61a9b09 gateway 两轴枚举无 cancelled);「第三个实例、不属于该类那半句不成立」成立;AC2、AC4 原文不变。

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions