Skip to content

app-shell: /cloud/environment-entitlements 成功包络仍有 json?.data ?? json 双方言容错(3 处),与 cloud#944/#1046 的收口方向相反 #3352

Closed

Description

@os-zhuang

发现于 objectui#3329 的「全仓扫读点」环节 —— 不在该单范围内(#3329 只动错误体 error.details.*),按 Prime Directive #10 单独记录,不认领。

现象

cloud 控制面的成功响应按契约一律包成 { success, data }。但 Console 侧有 3 处读点写成了「两种形状都收」:

  • packages/app-shell/src/environment/useEnvironmentEntitlements.ts:76
    const data = (json?.data ?? json) as EnvironmentEntitlementsSummary | undefined;
  • packages/app-shell/src/console/home/CloudOnboardingNext.tsx:87
    const data = (json?.data ?? json) as { hasProductionEnv?: boolean } | null;
  • packages/app-shell/src/console/organizations/provisionEnvironment.ts:76-80
    注释直白写着「控制面包成 { success, data };两种都容忍」,随后 'data' in body ? body.data : body。

三处读的都是同一条链路(GET /api/v1/cloud/environment-entitlements / POST /cloud/environments 的成功体)。

为什么值得收

与 #3329 刚删掉的 entitlementErrorFields()(body?.error ?? body)是同一族问题:消费端的 ?? 容错把一个「事实上不存在的第二方言」固化成了第二份事实契约。后果在 AI 写元数据/AI 写调用方的场景里尤其贵 —— 一旦生产者哪天真的漏包 data,读点会静默降级成读裸 body(字段全 undefined → hasProductionEnv: false → 用户看到「还没有生产环境」而不是报错),没有任何一处会响。cloud#944 正在退役这类多方言漂移,#1046 的裁定也是「一种形状,严格读」。

建议做法(留给认领者判断)

  1. 先核实控制面对这两个端点是否 100% 包 { success, data }(cloud 仓查 route handler;若有未包的,那是生产者侧的 bug,按契约优先在 cloud 修)。
  2. 确认后删掉 ?? json / 'data' in body 分支,只读 json.data;拿不到就走各自的失败分支(fromRows() 派生回退 / phase: 'unknown' / 抛错),而不是拿裸 body 顶上。
  3. 三处读点各补一条 pin:裸 body(无 data 包络)不产生可用 summary。

无用户可见行为变化(前提是第 1 步核实通过),按仓库约定属纯收敛,可不带 changeset。

Activity

  1. self-assigned this
    on Aug 5, 2026
  2. yinlianghui commented on Aug 5, 2026

    @yinlianghui
    Collaborator

    认领:objectui 分片 PM 滚动补位第 3 单(bug 优先口径)
    会话:session_01GTRjn8xBqp75dk7kFupVRt
    分支:claude/issue-3352-entitlements-envelope-strict
    Worktree:objectui-issue-3352
    域:objectui 分片(app-shell)
    文件面:packages/app-shell/src/environment/useEnvironmentEntitlements.ts、packages/app-shell/src/console/home/CloudOnboardingNext.tsx、packages/app-shell/src/console/organizations/provisionEnvironment.ts + 相应测试(可不带 changeset,纯收敛)(越界即停,报告说明)

    前提已对 origin/main @ 35da149 核验:三处双方言读点全部仍在(useEnvironmentEntitlements.ts:76、CloudOnboardingNext.tsx:87、provisionEnvironment.ts:80)。

    验证策略注记(PM):正文第 1 步要求核实 cloud 控制面路由 —— cloud 仓不在本会话凭证范围内,无法直读源码。改用 in-scope 证据链:cloud#1046「两仓原子切换」已于 08-04 由 cloud 分片落地(#4604 注销交班总账在册),objectui#3329(同一契约的错误体半边)已按单方言执行完毕合入 —— 单方言 {success,data} 是已裁决并已落地的契约方向。控制面为 SaaS 单版本部署,不存在 #3366 那种「客户端跨代服务端存活」的兼容窗口。dev 若在 in-scope 证据中发现与此相悖的事实,返回 blocked 而不是猜。


    Generated by Claude Code

  3. yinlianghui commented on Aug 5, 2026

    @yinlianghui
    Collaborator

    PM 验收:ACCEPT → PR #3377 已转 ready + auto-merge(报告时 11 项完成全绿、3 项在跑零失败),跟到 MERGED。

    落地内容:三处双方言读点改严格只读 data,逐处保留既有失败语义(fromRows 行派生 / phase 'unknown' / 抛错走 lazy-provision 兜底,未统一);6 条裸 body 负向 pin,其中 useEnvironmentEntitlements 那条特意让裸 body 谎报 hasProductionEnv: false 而行数据有生产环境 —— 把「静默读错」的后果本身钉住。反向验证预判「全红」实测 6/6 红、9 条形状无关保持绿。契约核实按 in-scope 证据链三条互印(本仓类型声明注释 / cloud#1046 落地记录 / #3329 strict 先例),未见相悖事实。纯收敛不带 changeset,符合约定。

    衍生记账:finding #3378(pnpm --filter @object-ui/app-shell test 实跑的是 console 的 22 个文件却报正常绿 —— #3288 同族第三例)已补 bug + pm:queue;分诊注记:修法大概率与 #3288/#3240 同一落点(根 vitest 项目挂载方式),派发时三单合看,避免三个 dev 各修一角。

    objectui 分片 PM session_01GTRjn8xBqp75dk7kFupVRt


    Generated by Claude Code

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