Skip to content

NODE_ENV 未设置时,第二个 /discovery 生产者(metadata-protocol 的 getDiscovery,经 @objectstack/rest)仍广播 environment=development #5936

Closed

Description

@baozhoutao

发现于 #5673 的实施(界外发现,关键词 + 文件路径查重无命中,故新开)。

现象

/discovery 有两个生产者,#5673 的裁定只点名了其中一个:

生产者 服务方 NODE_ENV 未设置时 environment
HttpDispatcher.getDiscoveryInfo()(packages/runtime/src/http-dispatcher.ts) dispatcher-plugin.ts / packages/adapters/hono production(#5673 已改)
MetadataProtocol.getDiscovery()(packages/metadata-protocol/src/protocol.ts:2900) packages/rest/src/rest-server.ts:3050 development(未改)

第二个生产者把宿主真实的缺省值原样递给映射函数:

environment: resolveDiscoveryEnvironment(
    (globalThis as { process?: { env?: Record< string, string | undefined > } })
        .process?.env?.NODE_ENV,
),

resolveDiscoveryEnvironment(undefined) 走 typeof raw !== 'string' 分支返回 development(packages/spec/src/api/discovery.zod.ts:341-344),所以经 @objectstack/rest 暴露的 /discovery 在「忘记设 NODE_ENV 的生产部署」上仍然自称 development —— 正是 #5673 判定为危险方向的那一个。

为什么 #5673 没有一并解决

#5673 的 maintainer 裁定(2026-08-06)把落点明确限定在 packages/runtime/src/http-dispatcher.ts,并把 packages/metadata-protocol 标为跨域文件面、要求「若必须改它就 STOP + needs_decision」。派发单进一步禁止改 packages/spec / packages/metadata-protocol。所以 #5673 的 PR 在 runtime 侧就地翻默认,并在注释里如实写明本条残留,而不是悄悄绕过。

两条可能的落点(需要裁定,不要直接猜)

  1. 默认收进共享映射函数 —— resolveDiscoveryEnvironment 把「缺省」判为 production,两个生产者都不再各自带默认。契约优先,单点决策,两个 discovery 生产者都在线上返回 schema 未声明的顶层字段(scoping / features / endpoints),且 REST 形状永远无法通过 DiscoverySchema #4828 建这张共享表的初衷就是防两个生产者漂移;代价是动 packages/spec,且要同步改 NODE_ENV_TO_DISCOVERY_ENVIRONMENT 上方那张表格里「unset / anything else → development」那一行(该行现在对 runtime 调用方已经过时)。
  2. 只在 metadata-protocol 生产者就地补默认 —— 与 NODE_ENV 未设置时 /discovery 广播 environment=development,而 os start 默认 NODE_ENV=production、CLI doctor 也按 production 解析 #5673 的做法对称,不动 spec;代价是同一个「缺省语义」在仓里有两处副本,正是共享表要防的漂移。

倾向 1(单点决策、契约优先、AI 写元数据时不给消费方留宽容分支),但落点跨域,交 maintainer 裁。

附带的文档面漂移(同一处,顺带记录)

packages/spec/src/api/discovery.zod.ts 映射表上方注释仍写:

| unset / anything else | development | preserves the pre-existing getEnv('NODE_ENV', 'development') default…

#5673 之后 runtime 调用方已不再传该默认,这句话对映射函数自身仍为真、对调用方已不为真。无论走上面哪条路,这行都要一起改。

参考:#5673(runtime 侧 + doctor 提示行)、#4828(枚举映射的由来)、Prime Directive #9(NODE_ENV 是第三方边界上的既有例外)。

Activity

  1. claude commented on Aug 6, 2026

    @claude
    Contributor

    分诊:needs-user-decision + domain:spec(路由标签,方向未定)。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. claude commented on Aug 7, 2026

    @claude
    Contributor

    Disposition (2026-08-07): returned to the queue — the semantics were already ruled on in #5673.

    The maintainer decided on 2026-08-06 that a deployment with NODE_ENV unset must not call itself development; the runtime producer was fixed, and metadata-protocol's getDiscovery was left behind only because that dispatch forbade touching it. What is left is a placement question, not a semantic one — which is engineering judgement.

    Direction 1: fold the default into resolveDiscoveryEnvironment (unset → production) so both producers inherit it, drop their local defaults, and fix the now-false comment at discovery.zod.ts:314 in the same pass. Direction 2 (patch metadata-protocol locally) would leave a second copy of the default — exactly the drift the shared table was created to prevent (#4828).

    Single-point default also means the next discovery producer gets the right answer without anyone remembering to copy a line.

    Operator: PM session session_01GcjbQLUQKysMU9uXB34iyv; maintainer ruling 2026-08-07 (decision-inbox round 2). Veto window open — comment or reopen to overturn.


    Generated by Claude Code

  3. hotlong commented on Aug 7, 2026

    @hotlong
    Contributor

    Release-board audit (maintainer-directed re-audit of non-board domain:spec items, 2026-08-07): adding target:v17 — criterion ①: with NODE_ENV unset, the second /discovery producer still broadcasts environment=development — the exact direction #5673 ruled dangerous; the ruled fix (fold unset→production into the shared mapper) is recorded. Triage seat may veto.


    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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions