Skip to content

[finding] ProvisionEnvironmentResponseSchema declares a REQUIRED credential the quoted handler does not send — and ProvisionOrganizationResponseSchema embeds it, so two response contracts carry the divergence #13381

Description

@os-trump

Filed unassigned by the domain:cli 执行 PM 席位(#6024),会话 session_01TvqBFLRzXdSPcbusDoED9k。⛔ 未定级为紧急,⛔ 未判。

出处:#12883 / PR #13379 的 dev 按派发令报回而不是顺手修⚠️ 路由到 domain:spec 而不是留在本车道 —— packages/spec/** 是那个车道的,⛔ 不该因为本席的卡碰巧撞见就留下(先例:#12624 由本族卡路由到 domain:devx)。

分歧

packages/spec/src/cloud/environment.zod.ts:342 起的 ProvisionEnvironmentResponseSchema 声明:

export const ProvisionEnvironmentResponseSchema = lazySchema(() => z.object({
  environment: EnvironmentSchema…,
  credential: EnvironmentCredentialSchema.describe('Freshly-minted credential for the environment DB'),  // ⇐ 必填
  durationMs: z.number(),                    // 必填
  warnings: z.array(z.string()).optional(),  // 可选
  hostnameAssignment: z.object({ requestedHostname, assignedHostname }).optional(),
}));

#12883 卡面引用的 handler 体(objectstack-ai/cloud · packages/service-cloud/src/routes/environment-lifecycle.ts · POST ${prefix}/cloud/environments)送的是:

ok({ environment, warnings, durationMs, ...(hostnameAssignment ? { hostnameAssignment } : {}) })

credential 是必填声明,但那段 handler 引用里没有它。

⭐ 新读数:血影范围是两个响应契约,不是一个

这一条是 PR #13379 的 dev 加出来的,此前两个席位都没记:ProvisionOrganizationResponseSchema:406整体内嵌ProvisionEnvironmentResponseSchema。⇒ 任何更正会同时传播到两个契约。⛔ 取卡者不要按"改一个 schema"去估工作量。

三种可能,⛔ 未判,且本席位无法分辨

  1. handler 确实送 credential,卡面的引用不完整
  2. spec 声明了一个线上不送的必填键 —— 这是 spec 侧的独立缺陷,environments.create() declares one response key; the control plane sends four (warnings / durationMs / conditional hostnameAssignment undeclared) #12883 本身更重(它让每个绑定该 schema 的消费者都相信一个不存在的必填键);
  3. 两者都对,只是走的不是同一条出口。

⚠️ 仓内那一半已经量满了:344 的必填声明确实存在,:406 的内嵌确实存在。线上那一半量不了 —— objectstack-ai/cloud 不在这些会话的仓库范围内。⇒ 需要一个能读 cloud 仓的席位,一次读取即可定案。

为什么它没有在 #12883 里被踩到

2026-08-29 的裁决(verbatim 「同意」,option 甲)明确 ⛔ 不绑 spec、只写内联 wire 形状。⇒ #12883 的执行路径绕开了这个陷阱。

⭐ 但 PR #13379 还额外钉住了它:packages/client/src/client.environments-namespace.test.ts 里有一条

// @ts-expect-error `POST /cloud/environments` is not declared to answer a `credential`
void created.credential;

⇒ 谁若日后把 credential 补进 SDK 声明,那条 @ts-expect-error 会变成未使用而变红。⛔ 这只是防止本卡的缺陷被反向再犯,不构成对上面三种可能的任何判定

⚠️ 取卡者的 tier 提醒

修复本条会动 packages/spec/src/**条款② 的路径肢触发。熔断常量按符号读(⛔ 不要按行号,它今天从 :5507 移到了 :5572):

scripts/pm/dispatch-gates.mjs
export const CONTRACT_REVIEW_TIER = 'claude-fable-5';

⇒ 低于该 tier 的席位 ⛔ 不得入队、⛔ 不得自清。本卡因此不是随便哪个席位都能落地的。

去重申报

⚠️ NOT MEASURED,⛔ 不是零读数:MCP search_issues 正在返回假零#13326,p1,三席两仓复现且会话中途退化)。若已有同形状的卡,请合并本卡并留痕。

Refs

⚠️ 本卡正文被修复过一次

立卡时正文以 --- 水平线 + attribution footer 结尾,平台把从那条线开始的一切都吃掉了,footer 静默丢失。本次更新按实测的修法重写:footer 保留、去掉前面那条规则。机制与五个实例记在 #13384。⛔ 正文内容未作任何其它改动,标签也未改动(本卡已被另一席位调整为 pm:blocked,本次不碰)。

Generated by Claude Code

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