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
12 changes: 11 additions & 1 deletion .claude/skills/wdl-deploy/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: wdl-deploy
description: Deploy and manage Cloudflare Workers-style projects on the WDL platform via the `wdl` CLI (init, deploy, config explain, whoami, doctor, tail, secret, workers, delete, d1, r2, ai, workflows). Trigger when the user asks to scaffold or deploy a Worker, inspect resolved CLI configuration, identify the active control token/principal, run diagnostics, tail live logs, configure KV / Queues / Durable Objects / Workflows / AI bindings, manage D1 / R2 / AI providers / secrets through `wdl`, or troubleshoot wdl CLI output. Works with `wrangler.json` / `wrangler.jsonc` / `wrangler.toml` projects pinned to wrangler@^4.
description: Deploy and manage Cloudflare Workers-style projects on the WDL platform via the `wdl` CLI (init, deploy, config explain, whoami, doctor, tail, secret, token, workers, delete, d1, r2, ai, workflows). Trigger when the user asks to scaffold or deploy a Worker, inspect resolved CLI configuration, identify the active control token/principal, manage the local WDL token store, run diagnostics, tail live logs, configure KV / Queues / Durable Objects / Workflows / AI bindings, manage D1 / R2 / AI providers / secrets through `wdl`, or troubleshoot wdl CLI output. Works with `wrangler.json` / `wrangler.jsonc` / `wrangler.toml` projects pinned to wrangler@^4.
---

# WDL CLI deploy skill
Expand Down Expand Up @@ -93,6 +93,12 @@ 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.

`CONTROL_URL` may include a path prefix, but embedded usernames/passwords, query
strings, and fragments are rejected. A bare `.local` host defaults to HTTPS
because mDNS is not loopback, except that the existing bare `:8080` rule still
selects HTTP on any host. Every HTTP `.local` target emits the plaintext-token
warning.

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
Expand Down Expand Up @@ -138,6 +144,10 @@ to confirm the resolved namespace, inspect the target with
`wdl ai providers get <provider> --ns <namespace>`, and use the same explicit
`--ns` for deletion. Never add `--yes` without user confirmation.

`wdl delete version` also requires confirmation and has no dry-run endpoint.
Inspect the retained version first; never add `--yes` without a separate safety
check and user confirmation.

`templates/AGENTS.md` is the generic agent entrypoint that `wdl init` copies
into every new project. It points at the same `docs/` through
`node_modules/@wdl-dev/cli/docs/<name>.md` paths.
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ jobs:
group: ci-node-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: ${{ github.event_name == 'pull_request' || github.event_name == 'push' }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: actions/setup-node@v6
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "22"
cache: npm
Expand All @@ -43,7 +43,7 @@ jobs:
group: ci-hygiene-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: ${{ github.event_name == 'pull_request' || github.event_name == 'push' }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: raven-actions/actionlint@205b530c5d9fa8f44ae9ed59f341a0db994aa6f8 # v2

Expand All @@ -65,9 +65,9 @@ jobs:
exit 1
fi

- uses: actions/checkout@v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: actions/setup-node@v6
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "22"
cache: npm
Expand Down
40 changes: 24 additions & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ jobs:
outputs:
dist-tag: ${{ steps.version.outputs.dist-tag }}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: actions/setup-node@v6
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "22"
cache: npm
Expand All @@ -32,7 +32,7 @@ jobs:

# Pre-release versions (1.2.3-rc.1) publish under the `next` dist-tag
# so `npm i -g @wdl-dev/cli` keeps resolving to the last stable release.
- name: Tag must match package.json version
- name: Tag and stable changelog must match package.json version
id: version
run: |
version="$(node -p 'require("./package.json").version')"
Expand All @@ -42,7 +42,10 @@ jobs:
fi
case "$version" in
*-*) echo "dist-tag=next" >> "$GITHUB_OUTPUT" ;;
*) echo "dist-tag=latest" >> "$GITHUB_OUTPUT" ;;
*)
echo "dist-tag=latest" >> "$GITHUB_OUTPUT"
node scripts/changelog-section.js "$version" > /dev/null
;;
esac

- run: npm pack --dry-run
Expand All @@ -55,9 +58,9 @@ jobs:
contents: read
id-token: write # OIDC: trusted-publishing auth + provenance attestation
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: actions/setup-node@v6
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "22"
registry-url: https://registry.npmjs.org
Expand All @@ -83,9 +86,9 @@ jobs:
contents: read
packages: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: actions/setup-node@v6
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "22"
registry-url: https://npm.pkg.github.com
Expand All @@ -103,7 +106,11 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6

- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: "22"

# Final releases take their notes from the matching CHANGELOG.md
# section; pre-releases (x.y.z-rc.N) have no section and fall back to
Expand All @@ -113,16 +120,17 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
version="${GITHUB_REF_NAME#v}"
awk -v ver="$version" '
$0 == "## " ver { found=1; next }
/^## / && found { exit }
found { print }
' CHANGELOG.md > /tmp/notes.md
args=(--verify-tag)
if [ -s /tmp/notes.md ]; then
if node scripts/changelog-section.js "$version" > /tmp/notes.md 2>/tmp/changelog-error; then
args+=(--notes-file /tmp/notes.md)
else
args+=(--generate-notes)
status=$?
if [[ "$version" == *-* && "$status" -eq 3 ]]; then
args+=(--generate-notes)
else
cat /tmp/changelog-error >&2
exit "$status"
fi
fi
case "$version" in
*-*) args+=(--prerelease) ;;
Expand Down
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,10 @@ Credential resolution layers, highest precedence first: CLI flags, shell/CI env,
the project `./.env` (sectioned by namespace, with a cross-origin guard that
drops a `.env`-supplied endpoint when the effective token is not from the same
`.env`), then the global token store (`~/.config/wdl/credentials`, managed by
`wdl token`). The store is trusted (home directory, same-source token +
endpoint) and not subject to the guard; a project `.env` is not. The namespace
itself follows the same shape —
`wdl token`). A store that passes the directory/file type checks and POSIX
permission checks is trusted (protected per-user config location, same-source
token + endpoint) and not subject to the guard; a project `.env` is not. The
namespace itself follows the same shape —
`--ns > shell WDL_NS > project .env WDL_NS > store default (base WDL_NS)` — so
the store's default namespace is the lowest selector, materialized into
`env.WDL_NS` before the per-key gap-fill. Keep that ordering and the guard
Expand Down
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,44 @@

## Unreleased

### Changed

- Accept only Wrangler v4.
- Validate Workflow page limits as integers in `1..1000` before contacting
Control.
- List `wdl token` in deploy-skill discovery so agent token-store tasks load the
repository guidance.
- Document that R2 `--out` accepts arbitrary filesystem destinations and uses
normal overwrite and symlink-following semantics.

### Fixed

- Reject Control base URLs containing embedded credentials, query strings, or
fragments instead of risking credential disclosure or appending command paths
into the wrong URL component.
- Keep `wdl config explain` usable when credential resolution needs the token
store but finds it malformed, unreadable, or unsafe by reporting
`tokenStore.error` alongside the remaining provenance; fully covered
higher-precedence values continue to leave the store unread.
- Make the opt-in `WDL_ALLOW_NPX_WRANGLER=1` fallback runnable on Windows by
using `npx.exe` or npm's `npx-cli.js` instead of the blocked `npx.cmd` shim.
- Make stable release tags fail before publishing when their changelog section
is missing.

### Security

- Require confirmation for `wdl delete version` and reject its unsupported
`--dry-run` flag instead of silently performing the deletion.
- Reject non-file or symlink credential paths on read, and fail closed when
POSIX token-store file ownership or directory/file permissions are unsafe.
- Tighten local HTTP classification: recognize case-insensitive `localhost` and
`.test` hosts plus the full `127.0.0.0/8` range as local targets, but treat
`.local` as a network/mDNS host. Bare `.local` hosts default to HTTPS except
for the existing `:8080` rule, and every HTTP `.local` target warns before
sending the token.
- Fail `wdl tail` when cumulative SSE event data exceeds 4 MiB.
- Pin official GitHub Actions to fixed commit SHAs in CI and release jobs.

## 1.8.0

### Added
Expand Down
5 changes: 4 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ parameters and returns (no implicit `any`).
| `bin/wdl.js` | Dispatcher. A `REGISTRY` of command modules derives both routing and the `wdl help` table from each command's `meta`; pre-scans argv so the `.env` namespace overlay sees the same `--ns` the command will. |
| `commands/*.js` | One file per command: an option schema plus a `run` body. |
| `lib/command.js` | The `defineCommand` framework: flag presets, `--help` short-circuit, dependency injection, and a `context` with `resolveControl` / `nsUrl` / `fetchJson` / `fetchStream`. |
| `lib/common.js` | Control-URL/namespace/token resolution, sectioned `.env` loading with the endpoint trust guard, `CliError`, help formatting, terminal-escape choke point. |
| `lib/common.js` | `CliError`, help formatting, shared CLI options, and compact HTTP/JSON error handling. |
| `lib/credentials.js`, `lib/dotenv.js` | Control URL / namespace / token resolution, sectioned `.env` loading, and the endpoint trust guard. |
| `lib/token-store.js` | The per-user credential store, its read/write trust checks, and serialized mutations. |
| `lib/control-fetch.js` | HTTP client for the control plane: timeouts, body caps, streaming, Host/IPv6 handling. |
| `lib/output.js` | Human and JSON output primitives, diagnostic formatting, token masking, and terminal escaping. |
| `lib/wrangler-pack.js`, `lib/wrangler/` | Wrangler config parsing (TOML/JSONC), deploy manifest assembly, asset collection with `.assetsignore`, local bundling via `wrangler deploy --dry-run`. |
| `lib/*-format.js` | Per-command output formatters. |

Expand Down
Loading