Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions .claude/skills/wdl-deploy/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,39 @@ authoritative, and agent-facing references use the English set.

New Wrangler configs should use `compatibility_date = "2026-06-17"` unless a
project feature requires a newer target or the operator gives a different
target. WDL follows Wrangler config priority (`wrangler.json`, then
`wrangler.jsonc`, then `wrangler.toml`); both JSON filenames use Wrangler's
JSONC syntax, including comments and trailing commas. The control plane is
canonical for unsupported runtime shapes such as unsupported workerd
experimental compatibility flags and WDL-reserved injected module names; the
CLI still fails fast for cheap local cases such as Python Workers modules,
unmapped top-level or selected-env Wrangler runtime/deploy keys (`[site]`,
`workers_dev`, `pages_build_output_dir`, `observability`, `limits`,
target. Control rejects explicit dates before `2026-04-01`, invalid or future
dates, dates newer than the bundled workerd supports, upstream experimental
enable flags, `legacy_error_serialization`, and
`allow_irrevocable_stub_storage`. WDL follows Wrangler config priority
(`wrangler.json`, then `wrangler.jsonc`, then `wrangler.toml`). Both JSON
filenames use Wrangler's JSONC syntax, including comments and trailing commas.
The control plane is canonical for unsupported runtime shapes such as
unsupported workerd compatibility flags and WDL-reserved injected module
names. The CLI still fails fast for cheap local cases such as Python Workers
modules, unmapped top-level or selected-env Wrangler runtime/deploy keys
(`[site]`, `workers_dev`, `pages_build_output_dir`, `observability`, `limits`,
`placement`, etc.), and ambiguous runtime `env` name collisions between
`[vars]`, explicit bindings, and the implicit `ASSETS` binding.
WDL-only `[[exports]]`, `[[platform_bindings]]`, `[[triggers.schedules]]`, and
`[[services]].ns` are parsed by the CLI and removed from Wrangler's temporary
bundle config; other fields retain their existing Wrangler passthrough
behavior. Wrangler's object-shaped declarative `exports` config is unsupported.
The dry-run child hides Wrangler's banner (and its normal update check) and
disables anonymous telemetry. Wrangler may still consult the configured npm
registry when reporting an unknown configuration field; project build hooks
retain their normal network access.
For `[[services]]` and `[[exports]]`, read `docs/deploy.md`: tenant JSRPC may
delegate service or Durable Object class stubs as opaque capabilities, but the
receiver cannot rewrite their host-authored caller properties. Keep delegated
stubs in memory; long-term irrevocable stub storage is unsupported.

Never recommend setting `CONTROL_CONNECT_HOST` outside local development: it
overrides the TCP target the admin token connects to (Host header + TLS SNI
still track `CONTROL_URL`), and a stale value in a CI or production shell could
route the token to an unintended host. A URL-form override uses its scheme only
to choose the default TCP port; transport still follows `CONTROL_URL`. GUIDE
covers the details.
covers the details. Local deploy output also derives the public Worker scheme
and port from `CONTROL_URL`, never `CONTROL_CONNECT_HOST`.

`wdl deploy` runs the project's Wrangler dry-run and build hooks as the user, so
they can read the on-disk token store (`~/.config/wdl/credentials`); only deploy
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@

## Unreleased

### Changed

- `wdl workers` now reports workflow-definition state (`unknown` when an older
control omits it), `wdl workflows list` marks retired definitions, and
`wdl delete worker --dry-run` reports worker-secret and workflow-definition
presence without overstating blocked deletion.
- Local deploy output now derives the Worker URL scheme and port from
`CONTROL_URL` instead of assuming `http://...:8080`.
- Platform capability docs now cover the current compatibility-date, Durable
Object RPC, Workflows, R2 metadata, secret-key, D1 error, and JSRPC contracts.
- The packaged deploy toolchain now pins Wrangler 4.112.0 and uses
jsonc-parser 3.3.1 and smol-toml 1.7.0. Unmapped Wrangler `addresses` and
`dependencies_instrumentation` fields now fail loudly instead of being
silently dropped.
- `wdl deploy` hides Wrangler's banner (and its normal update check) and
disables anonymous telemetry for its dry-run subprocess. Wrangler can still
consult the configured npm registry when explaining unknown config fields;
project build hooks retain their normal network access.

### Fixed

- `wdl deploy` now gives an actionable hint when control returns
`compatibility_flag_unsupported`.

## 1.4.1

### Fixed
Expand Down
26 changes: 21 additions & 5 deletions GUIDE-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ CLI 只会从 `.env` 读取 WDL 平台变量:`ADMIN_TOKEN`、`CONTROL_URL`、`

`wdl deploy` 在上传前会以你的 OS 用户身份运行项目本地的 Wrangler dry-run 和 build 钩子,这些代码能读到磁盘上的 store(env scrub 只把 WDL 变量挡在 Wrangler 子进程的环境外,挡不住文件),所以只部署你信任的项目。`--no-token-store`(或 `WDL_TOKEN_STORE=off`)让 CLI 只从 flag / shell / `.env` 解析凭据、完全不读 store —— 这是给不太信任的项目或 CI 用的解析 opt-out,不是对文件本身的保护。

用 `wdl config explain` 查看最终 namespace、control URL、脱敏 token 以及每个值的来源。用 `wdl whoami` 调 control-plane `/whoami`,查看当前 authenticated principal、token id、platform version、最低支持 CLI version 和 URL hints。用 `wdl doctor` 做本地可用性检查,包括 Node.js、wdl-cli、Wrangler、配置文件是否存在、凭据是否能解析,以及 `/whoami` 是否可达;在 CI 里可加 `--strict`,命令仍会打印检查结果,但只要任一检查失败就以非零退出。当 control plane 暴露 `/whoami` 时,`doctor` 可以发现 token 是否有效、principal namespace、platform version 和 CLI compatibility;更细的 capability 检查仍需要额外的 control endpoint。
用 `wdl config explain` 查看最终 namespace、control URL、脱敏 token 以及每个值的来源。用 `wdl whoami` 调 control-plane `/whoami`,查看当前 authenticated principal、token id、platform version、最低支持 CLI version 和 URL hints。用 `wdl doctor` 做本地可用性检查,包括 Node.js、wdl-cli、Wrangler、配置文件是否存在、凭据是否能解析,以及 `/whoami` 是否可达;在 CI 里可加 `--strict`,命令仍会打印检查结果,但只要任一检查失败就以非零退出。当 control plane 暴露 `/whoami` 时,`doctor` 可以发现 token 是否有效、principal namespace、platform version 和 CLI compatibility;更细的 capability 检查仍需要额外的 control endpoint。运维方没有配置公开 platform domain 时,namespace URL 可能显示为 `(unavailable)`;认证和其它 `/whoami` 字段仍然有效。

## 脚手架新 Worker

Expand Down Expand Up @@ -146,7 +146,9 @@ APP_NAME = "hello"

新项目建议使用 `compatibility_date = "2026-06-17"`;除非需要的功能或管理方明确要求更新的目标日期。

你可以继续使用 `wrangler dev` 做本地开发;部署到本平台时改用 `wdl deploy`。平台部署命令会调用 `wrangler deploy --dry-run`(Wrangler v4)打包项目,解析顺序是 `WDL_WRANGLER_BIN`、Worker 项目本地 wrangler、CLI 包本地 wrangler、最后是 `PATH`。TypeScript、模块解析、esbuild 打包等流程仍走 wrangler 的标准路径。
Control 会拒绝早于 `2026-04-01` 的显式日期、无效或未来日期,以及超出 bundled workerd 支持范围的日期。上游 experimental enable flags、`legacy_error_serialization` 和 `allow_irrevocable_stub_storage` 不受支持。这些校验由 control canonical 持有,CLI 不复制 workerd flag table。

你可以继续使用 `wrangler dev` 做本地开发;部署到本平台时改用 `wdl deploy`。平台部署命令会调用 `wrangler deploy --dry-run`(Wrangler v4)打包项目,解析顺序是 `WDL_WRANGLER_BIN`、Worker 项目本地 wrangler、CLI 包本地 wrangler、最后是 `PATH`。TypeScript、模块解析、esbuild 打包等流程仍走 wrangler 的标准路径。WDL 会隐藏这个 dry-run 子进程的 Wrangler banner(因此跳过常规 banner 更新检查)并关闭匿名遥测。Wrangler 在报告未知配置字段时仍可能访问已配置的 npm registry;项目 build hook 仍保留正常的网络访问能力。

如果同时存在多个 Wrangler 配置文件,WDL 跟随 Wrangler 的优先级:`wrangler.json`,然后 `wrangler.jsonc`,最后 `wrangler.toml`。

Expand Down Expand Up @@ -220,6 +222,8 @@ cron / queue delivery 会在 `wdl tail` 里显示 start/finish 事件,包含 w

不要把用户访问 Worker 的流量打到 control URL。control URL 只用于部署和管理命令。

对于本地开发 control host,deploy 摘要会复用 `CONTROL_URL` 的 scheme 和对外端口生成 Worker URL。`CONTROL_CONNECT_HOST` 仍只覆盖 control socket 的连接目标,不会改变输出的 Worker origin。

自定义域名和 Wrangler `routes` 目前还不是 tenant self-service 的 GA 能力。除非管理方明确为你的 namespace 开通自定义 host,否则使用默认 Worker URL:

```text
Expand All @@ -230,7 +234,7 @@ https://<namespace>.<platform-domain>/<worker-name>/

## 支持的 wrangler 配置

Wrangler 能打包、但 WDL 不能运行的形状由 control plane 作为 canonical validator 拒绝,包括不支持的 workerd experimental compatibility flags 和 WDL 保留注入模块名。CLI 仍会对低成本的本地问题 fail-fast,例如 Python Workers modules,以及 `[vars]`、显式 bindings、隐式 `ASSETS` binding 之间的 runtime `env` 名称冲突。Deploy 和 secret mutation 还会校验留有 headroom 的 workerd 1 MiB `workerLoader` env budget;过大的 `[vars]`、secrets、binding metadata 或 retained versions 可能触发 `worker_env_too_large`。
Wrangler 能打包、但 WDL 不能运行的形状由 control plane 作为 canonical validator 拒绝,包括不支持的 workerd compatibility flags 和 WDL 保留注入模块名。CLI 仍会对低成本的本地问题 fail-fast,例如 Python Workers modules,以及 `[vars]`、显式 bindings、隐式 `ASSETS` binding 之间的 runtime `env` 名称冲突。Deploy 和 secret mutation 还会校验留有 headroom 的 workerd 1 MiB `workerLoader` env budget;过大的 `[vars]`、secrets、binding metadata 或 retained versions 可能触发 `worker_env_too_large`。

| 配置 | 支持情况 |
| --- | --- |
Expand Down Expand Up @@ -336,6 +340,8 @@ WDL 不会创建真实的 per-namespace S3 bucket。`bucket_name` 是部署时

当前支持 `head`、`get`、`put`、`delete`、`list` 等常用路径。需要时也可以使用条件读取、range GET 和 `list({ include })` metadata hydration;metadata hydration 会在并发上限内额外发起 HEAD。`put(stream, ...)` 目前会先 buffer,再做单次 S3 PUT,最大 25 MiB。multipart upload、SSE-C、checksum selection 暂不支持。

当 `httpMetadata` 使用 `Headers` object 传入时,`Expires` header 必须是 canonical IMF-fixdate,例如 `Wed, 21 Oct 2015 07:28:00 GMT`。

用 `wdl r2` 命令查看或显式删除 namespace 内的 R2 数据:

```bash
Expand Down Expand Up @@ -405,6 +411,8 @@ D1 运行时请求在执行前有边界:binary query body 最大 8 MiB;解

`wdl d1 migrations status/apply` 走 control-plane JSON request parser,所以请求体上限是 1 MiB。特别大的 migration 集合或 SQL 文件应拆成更小批次再 apply。

Control-plane D1 lifecycle API 会把 D1 runtime/backend 转发来的 5xx failure 收敛为 `Internal error`,只保留有界的 machine classifier:`upstreamCode`、`upstreamCategory`、`upstreamRetryable` 和 `upstreamStatus`。Control 自己生成的 contention / collision 503 response 仍保留可操作消息;对外 4xx SQL / migration failure 也可保留可操作诊断。

`examples/d1-demo` 提供了一个最小 visitor counter 示例,包含 D1 binding 和 forward-only migration。

### Durable Objects
Expand Down Expand Up @@ -447,6 +455,8 @@ export default {

当前支持 `stub.fetch()`、JSON-structured `stub.method(...args)` RPC、native `ctx.storage`、同步 `ctx.storage.sql`、alarm、普通 WebSocket upgrade 以及 native WebSocket hibernation API surface。跨 script binding、rename/delete migration、平台级 WebSocket session/cursor 恢复暂未实现。

DO fetch 请求体上限是 1 MiB。RPC method name 必须符合 JavaScript identifier grammar,且最多 256 ASCII bytes。RPC arguments 最多 1 MiB,只接受 structural JSON:finite value、dense array 和 plain object;序列化不会调用 `toJSON()`。Object name 和 id 必须是 well-formed Unicode;DO class name 使用 ASCII JavaScript class-name grammar,最多 468 bytes。

使用 `ctx.storage.sql` 时,不要使用以 `_cf_` 开头的应用表名;workerd 对这个前缀做大小写不敏感保留。`ctx.storage.deleteAll()` 也会保留平台自有的 `_cf_*` 表。

`examples/durable-objects-demo` 提供了最小的同 Worker Durable Object 计数器,使用 SQLite-backed storage 保存状态。
Expand Down Expand Up @@ -474,11 +484,15 @@ wdl workflows restart api orders order-123 --yes
wdl workflows terminate api orders order-123 --yes
```

`wdl workflows list` 会把 active Worker version 不再导出的定义标为 `retired=yes`。既有实例仍可查看和 terminate,但 restart 会返回 `workflow_not_exported`;需要先部署一个重新导出该 workflow name 的 active version。

这是 WDL Workflows 支持,不是完整 Cloudflare Workflows parity。 `script_name`、跨 worker workflow、跨 worker callback、service-binding callback 和 Cloudflare source-AST visualizer 不支持。same-worker DO progress callback 和 runtime-observed parallel/DAG `step.do` execution 可用。

重要运行限制和编程规则:

- `createBatch()` 每次最多接受 100 个 entry。单个 workflow result 上限是 1 MiB;一次 runtime 到 Workflows backend 的 JSON 请求上限是 2 MiB。
- 每个 instance 的聚合 payload 上限是 16 MiB。超过上限的 step/event 写入会让请求失败;runtime 写入过大的 terminal result 时,会在同一个事务里把 instance 转为 failed。
- 新创建的 completed、failed 和 terminated instance 默认保留 8 小时;需要时可通过 `create()` 的 `retention` option 覆盖 success/error retention。
- 一个 `step.do` 如果永久失败,本次 run 会进入 terminal failure,即使用户代码 catch 了这次抛错也一样。
- 单个 step 最多记录 1000 条 dependency edge。单次 dispatch turn 最多有 1000 个 in-flight workflow steps,并最多启动 1000 个 fresh backend steps。
- 用户代码必须 await 所有已启动的 `step.do`。run 在仍有 started step 未 settle 时返回会失败为 `workflow_invalid_step`。
Expand Down Expand Up @@ -514,7 +528,7 @@ printf '%s' "$DATABASE_URL" | wdl secret put --scope ns DATABASE_URL
- `secret_encryption_unconfigured`、`secret_decrypt_failed`、`invalid_envelope`、`unsupported_envelope`、`unknown_kid` 或 `secret_not_encrypted` 这类 secret-envelope 错误表示 mutation 没有写入;等运维侧修复 envelope 配置或已存储数据后再重试。
- worker-level secret 可以在第一次部署前设置;第一次部署会读取这些 secret。
- namespace-level secret 会共享给 namespace 下的所有 Worker,但不会批量 bump 所有 Worker。它会在下一次自然 cold-load 时生效,例如新部署、runtime recycle 或 isolate eviction。
- secret key 必须符合环境变量命名规则,例如 `STRIPE_KEY`;value 最大 64 KiB,并且和 `[vars]` 一样计入 workerLoader env budget。
- secret key 必须符合 `[A-Za-z_][A-Za-z0-9_]*`,最多 128 个字符;runtime-reserved name 和保留的 `Object.prototype` key 会被拒绝。Value 最大 64 KiB,并且和 `[vars]` 一样计入 workerLoader env budget。

### Queues

Expand Down Expand Up @@ -682,6 +696,8 @@ Service binding 在部署时解析并绑定到目标当时的线上版本。目

`export default function(request, env, ctx)` 会被当作 fetch handler 简写,并通过 `.fetch(...)` 暴露;它不是可直接调用的 default RPC method。RPC method 应放在命名 `WorkerEntrypoint` 上,或放在 default object / class 的方法上。

当前 tenant JSRPC 可以序列化 `Blob` value,并把 service 或 Durable Object class stub 作为 opaque capability argument 传递。接收方可以调用被委托的目标,但不能改写 stub 携带的 host-authored caller properties。Delegated stub 只应留在内存中;WDL 不支持长期 irrevocable stub storage。

### Platform bindings

如果平台提供了第一方共享能力,你只需要绑定平台给出的符号名:
Expand Down Expand Up @@ -798,7 +814,7 @@ wdl delete worker hello --dry-run
wdl delete worker hello
```

`wdl delete worker` 默认会要求确认。建议先用 `--dry-run` 预览受影响的线上版本、保留版本、路由、worker secrets、queue consumers 和资产清理。自动化脚本里只有在已有独立安全检查后,才建议传 `--yes`。
`wdl delete worker` 默认会要求确认。建议先用 `--dry-run` 预览受影响的线上版本、保留版本、路由、worker secrets、workflow definitions、queue consumers 和资产清理。即使没有 deployed version,`wdl workers` 也会用 `workflow-defs=yes` 显示仍有 workflow definitions 的 entry;旧 control 未上报该字段时,CLI 显示 `workflow-defs=unknown`,这不表示没有 workflow definitions。自动化脚本里只有在已有独立安全检查后,才建议传 `--yes`。

确认后删除 D1 数据库:

Expand Down
Loading