Skip to content

fix(spec,metadata-protocol,runtime): one place decides the unset-NODE_ENV discovery environment - #6554

Merged
qq9340100 merged 1 commit into
mainfrom
claude/issue-5936-discovery-environment-default
Aug 8, 2026
Merged

fix(spec,metadata-protocol,runtime): one place decides the unset-NODE_ENV discovery environment#6554
qq9340100 merged 1 commit into
mainfrom
claude/issue-5936-discovery-environment-default

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes #5936

裁决方向 1(2026-08-07 决策箱第二轮)落地。前提对 origin/main 3a1d9c7 逐条复核成立:discovery.zod.ts:341 对非字符串输入返回 developmentprotocol.ts:2900(getDiscovery)原样递传 process.env.NODE_ENVhttp-dispatcher.ts:1331 带着本地默认 getEnv('NODE_ENV', 'production') 和「本条残留待 #5936」的注释、:314 的过时映射行仍在。缺陷可复现:同一台忘设 NODE_ENV 的部署,dispatcher 的 /discovery 宣称 production,经 @objectstack/rest 服务的同一端点宣称 development —— 同一个问题,两个答案。

改动

缺省判定收进共享映射:resolveDiscoveryEnvironment 对 absent 值解析为 production,两个生产者都原样递传操作员的值。dispatcher 删本地默认;metadata-protocol 本无默认、随映射自动纠正。#4828 的规则不动、方向依旧相反 —— set 而不识别的拼写(qapreview)降级 development(那是猜测),absent 是宿主拒答(默认 production)。原「unset / anything else」一行拆成两行各述其理。

裁决未明说、按其理据自判的一点(否决窗口):空串算 unset。NODE_ENV= 导出空串;runtime 的 getEnv 一向用 || 折进默认,#5673 的 pin 已断言该情形为 production;若映射把空串归「anything else」,两个生产者会在这一个输入上继续分歧 —— 正是本次收敛要消灭的漂移。已写进 TSDoc、changeset,两侧生产者各 pin 一条。

验证与逆向验证(方向先判后跑)

界外发现(已记录、未夹带)

  1. packages/rest 自有 conformance 套件但无 NODE_ENV 块 —— 它组合在 getDiscovery() 之上,新 pin 已覆盖其行为;若将来长出第三个形态值得留意。
  2. getEnv(core/src/utils/env.ts:15)用 || 把空串折进默认是仓级策略,合法为空串的 OS_* 变量无法表达;本改动在一个调用点依赖该行为,未触碰。

交付通道注记

云端工头 B 会话(session_011btrhv6sHn6JkN93YRtGQp)无 GitHub 工具,走交付降级通道:dev 实现并 push 分支,PM(session_011M7UwH25Unfi73UHim7ajY)代开本 PR 并跟进 CI 至合并。完整交付摘要见分支 commit message。


Generated by Claude Code

…_ENV discovery environment (#5936)

Fixes #5936. Direction 1 of the maintainer's 2026-08-07 ruling (decision-inbox
round 2), which returned the issue to the queue as a placement question after
#5673 had already settled the semantics on 2026-08-06.

## Premise, re-verified against origin/main (3a1d9c7)

Every line the issue cites is where it says, and the defect reproduces:

- `resolveDiscoveryEnvironment` at `packages/spec/src/api/discovery.zod.ts:341`
  returned `development` for a non-string input — so `undefined` in.
- `packages/metadata-protocol/src/protocol.ts:2900` (`getDiscovery`) passed
  `process.env.NODE_ENV` in raw, with no default of its own. Served by
  `packages/rest`.
- `packages/runtime/src/http-dispatcher.ts:1331` carried the #5673 default at
  its own call site as `getEnv('NODE_ENV', 'production')`, with a comment
  stating this exact residue and naming #5936 as the follow-up.
- The mapping table's `unset / anything else -> development` row at
  `discovery.zod.ts:314` was still there, and had been false for the runtime
  caller since #5673.

Net effect on main: a production deployment whose operator forgot `NODE_ENV`
was advertised `production` on the dispatcher's `/discovery` and `development`
on the one served through `@objectstack/rest`. Same question, two answers.

## What lands

The default moves INTO the shared mapper: an absent value resolves to
`production`, and both producers pass the operator's value through as read.
The dispatcher's local default is deleted; metadata-protocol never had one to
delete and simply inherits the corrected mapper. #4828's rule is untouched and
still points the other way — a set-but-unrecognised spelling (`qa`, `preview`)
degrades to `development`, because absence is the host declining to answer
while an unrecognised spelling is a guess.

One judgement call the ruling did not spell out, decided and recorded rather
than left implicit: **"unset" includes a blank value**. `NODE_ENV=` exports an
empty string; the runtime's `getEnv` has always folded that into its default
(it tests with `||`), and #5673's own pin already asserts the dispatcher answers
`production` for it. Had the mapper treated blank as "anything else", the two
producers would have gone on disagreeing about exactly that input — the drift
this consolidation exists to end — so blank is unset. Stated in the TSDoc, in
the changeset, and pinned on both producers.

Direction 2 (patch metadata-protocol locally) was the alternative and is what
the ruling rejected: it would have left a second copy of the default, which is
what the shared table was created to prevent (#4828).

## Documentation, both faces of it

- `discovery.zod.ts`: the `unset / anything else` row splits into two rows,
  one per rule, each with its reason, plus the note that the unset default
  moved here in #5936 and why blank counts as unset.
- `http-protocol.mdx` already carried the corrected table from #5673 — but it
  describes the dispatcher, and until now the table was true of that producer
  only. It now states that the mapping and the default are shared by every
  `/discovery` producer, and names the behaviour change for anyone reading
  `environment` from a REST-served response.
- `http-dispatcher.ts`: the comment block that explained *why the default sits
  at this call site* is replaced by one explaining why it no longer does, and
  telling the next author not to re-add one.
- `protocol.ts`: a short comment at the call site making the same point from
  the other side — this producer adds no default; the mapper decides.

## Reverse verification — two revert shapes, opposite outcomes, both predicted first

Predicted, then measured:

- **Full revert to main's shape** (mapper back to `development` for a
  non-string AND the dispatcher back to `getEnv('NODE_ENV', 'production')`):
  metadata-protocol's two unset rows go RED, runtime stays **23/23 GREEN**.
  That asymmetry IS the bug this issue reports, reproduced on demand.
  Measured: `Tests 2 failed | 17 passed (19)` in metadata-protocol,
  `Tests 23 passed (23)` in runtime, `Tests 1 failed | 77 passed (78)` in
  spec's mapper suite.
- **Mapper-only revert** (dispatcher keeps its local default deleted): BOTH
  producers go red — measured `2 failed | 17 passed (19)` and
  `2 failed | 21 passed (23)`. That is the consolidation stated as a test
  outcome: the dispatcher no longer has a second place to be right.

The unrecognised-spelling rows stayed green under both reverts, as predicted —
they are #4828's rule and this change does not touch it. Both source files were
restored and verified byte-identical with `diff` afterwards.

## Tests

- `packages/spec/src/api/discovery.test.ts`: the single case "never CLAIMS
  production for an unset or unrecognized value" split into two, because the
  two rules now point opposite ways. The unset case covers `undefined`, `null`,
  `''` and `'   '`.
- `packages/metadata-protocol/src/discovery-schema-conformance.test.ts`: a new
  block driving the REAL producer — unset and blank advertise `production`,
  unrecognised spellings still `development`, and the shared table
  (`test`/`staging`/`production`) reproduced end-to-end so the two producers'
  suites assert the same facts.
- `packages/runtime/src/discovery-schema-conformance.test.ts`: pins unchanged
  and still green (this producer's behaviour does not move); its comment is
  rewritten, since the sentence explaining that a spec-side test "cannot see"
  the default stopped being true the moment the default moved there.

Two end-to-end pins rather than one mapper test on purpose: a local default
re-added at either call site would satisfy the mapper's own test and still be
the drift #5936 removes. Only a producer-level assertion separates them.

## Verification (all foreground, real readings)

- `pnpm --filter @objectstack/spec test` -> 340 files, **8727 passed**
- `pnpm --filter @objectstack/metadata-protocol test` -> 55 files, **571 passed**
- `pnpm --filter @objectstack/runtime test` -> 110 files, **1606 passed**
- `pnpm --filter @objectstack/rest test` -> 64 files, **884 passed**
- `pnpm --filter @objectstack/objectql test` -> 146 files, **2448 passed**
- `pnpm --filter @objectstack/client test` -> 21 files, **263 passed**
- `pnpm --filter @objectstack/hono test` -> 2 files, **73 passed**
- `turbo run typecheck --filter=./packages/* --filter=./packages/*/*` ->
  **119 successful, 119 total**
- `pnpm --filter @objectstack/spec check:generated` -> **10/10 up to date**
  (nothing regenerated: no `.describe()`, no export and no authorable key moved)
- `pnpm --filter @objectstack/spec gen:openapi` -> ran (ungated generator);
  writes only the gitignored `json-schema/openapi.json`, no tracked diff
- `pnpm lint` -> clean
- `check:nul-bytes` / `check:empty-changeset` / `check:adr-0087-registration` /
  `check:route-envelope` / `check:error-code-casing` /
  `check:wildcard-fallthrough` / `check:adr-anchors` / `check:doc-authoring` /
  `check:docs-audit-scope` / `check:quick-reference-counts` /
  `check:startup-registry-verdict` / `check:service-providers` /
  `check:spec-parsed-alias` -> all green

`check:adr-0087-registration` confirms no declared-breaking changeset, so no
disposition marker is owed. The changeset covers all three packages at `patch`
and states the behaviour change an operator can observe.

One first-run red that was NOT this change: `@objectstack/client` reported
3 failed suites with "Failed to resolve entry for package
`@objectstack/runtime`" — a fresh worktree with runtime's `dist` unbuilt
(AGENTS.md §9's stale-artefact trap in mirror image). `pnpm --filter
'@objectstack/client...' build` fixed it and the suite went 21/21.

## Ruling mapping

| Ruling clause | Where it lands |
|:---|:---|
| unset -> `production`, folded into `resolveDiscoveryEnvironment` | `discovery.zod.ts` — the mapper body |
| producers drop their local defaults | `http-dispatcher.ts` (deleted); `protocol.ts` had none and now says so |
| correct the stale mapping-table comment | `discovery.zod.ts` — one row becomes two, each with its rule |
| pin both producers under unset `NODE_ENV` | new block in metadata-protocol's conformance suite; runtime's #5673 pins kept and re-commented |
| one PR across spec + metadata-protocol + runtime | this commit |
| changeset covering the three packages, patch | `.changeset/discovery-environment-single-default.md` |

## Out-of-scope findings (recorded, not fixed)

1. `packages/rest` carries its own `discovery-schema-conformance.test.ts` and is
   the SERVER for the metadata-protocol producer, but it has no NODE_ENV block
   of its own — it composes over `getDiscovery()`, so the new pins do cover the
   behaviour it serves. Worth knowing if a third shape ever grows there.
2. `getEnv` (`packages/core/src/utils/env.ts:15`) collapses an empty string into
   its default via `||`, which is right for `NODE_ENV` but is a repo-wide
   policy applied to every variable — an `OS_*` value that is legitimately the
   empty string cannot be expressed. Not touched here; noted because this change
   depends on that behaviour at one call site.

## 交付摘要(PM 开 PR 素材)

- **前提**:对 origin/main 3a1d9c7 逐条复核成立 —— `discovery.zod.ts:341` 非字符串返回 `development`、`protocol.ts:2900` 原样递传、`http-dispatcher.ts:1331` 本地默认连同「本条残留待 #5936」的注释俱在、:314 那行过时表格行仍在。缺陷可复现:同一台忘设 NODE_ENV 的部署,两个生产者给出两个答案。
- **落地**(裁决方向 1):缺省判定收进共享映射(unset → `production`),runtime 删本地默认,metadata-protocol 本无默认、随映射自动纠正;#4828 的「不在猜测上宣称 production」不动,两条规则拆成两行各述其理。
- **裁决未明说而必须定的一点**:空串算 unset。`NODE_ENV=` 导出空串,runtime 的 `getEnv` 一向用 `||` 把它折进默认,#5673 的 pin 也已断言该情形为 production;若映射把空串归入「anything else」,两个生产者就会在这一个输入上继续分歧 —— 正是本次收敛要消灭的漂移。已写进 TSDoc、changeset 并在两侧各 pin 一条。
- **反向验证**:两种回退形态,方向先判后跑,结果相反且都命中 —— 整体回退到 main 形态:metadata-protocol 红 2、runtime 23/23 全绿(**这就是 #5936 报告的不对称本身**);仅回退映射:两侧各红 2(说明 runtime 已无第二处可依赖)。未识别拼写行在两种回退下均保持绿。两个源文件事后 diff 验证逐字节还原。
- **文档面**:`discovery.zod.ts` 表格行订正;`http-protocol.mdx` 原表自 #5673 起就是对的,但只对 dispatcher 成立 —— 现补明该表对**所有** `/discovery` 生产者成立,并写清经 `@objectstack/rest` 读 `environment` 的调用方会看到的行为变化。
- **验证读数**:spec 8727、metadata-protocol 571、runtime 1606、rest 884、objectql 2448、client 263、hono 73 全绿;`turbo typecheck` 119/119;生成物 10/10 且本次无一需要重生成;lint 与门禁族全绿。client 首跑 3 个 suite 红是新 worktree 未建 runtime dist(AGENTS §9 陈旧产物陷阱的镜像),补建后 21/21,与本改动无关。
- **界外发现**两条见上,均未夹带。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011btrhv6sHn6JkN93YRtGQp
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 4:30am

Request Review

@qq9340100
qq9340100 enabled auto-merge August 8, 2026 04:30
@github-actions github-actions Bot added the size/m label Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/metadata-protocol, @objectstack/runtime, @objectstack/spec.

118 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via packages/runtime, @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/runtime, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/metadata-protocol, @objectstack/runtime, packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/runtime, @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/tenancy-modes.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/metadata-protocol, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authentication.mdx (via @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime, @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/metadata-protocol, @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/metadata-protocol, @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 8, 2026
@qq9340100
qq9340100 added this pull request to the merge queue Aug 8, 2026
Merged via the queue into main with commit 2a2a9fb Aug 8, 2026
26 checks passed
@qq9340100
qq9340100 deleted the claude/issue-5936-discovery-environment-default branch August 8, 2026 05:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants