1---
2title: 2.0.0-beta.56 - 200+ Cloudflare Resources
3date: 2026-06-17T20:00:00Z
4category: release
5excerpt: v2.0.0-beta.56 grows the Cloudflare provider from 22 resources to 230, each implemented and live-tested against the real Cloudflare API — plus `alchemy unsafe nuke`, GitHub webhook event sources, and an S3-backed state store.
6---
7
8The Cloudflare provider grows from **22 resources to 230** in this
9release. A single PR ([#601](https://github.com/alchemy-run/alchemy/pull/601))
10lands +101k lines across 542 files — 189 new live-test suites, every
11one run against a real Cloudflare account — bringing coverage to over
12a hundred Cloudflare services: Zero Trust (Access, Tunnels, Devices,
13Gateway, DLP), Magic Transit and Magic Network Monitoring, Load
14Balancing, DNS and DNS Firewall, SSL/TLS and certificates, Waiting
15Rooms, Logpush, Spectrum, Turnstile, API Shield, Bot Management, Page
16Shield, Workers for Platforms, Snippets, Zaraz, Registrar, Addressing,
17Alerting, and the rest of the long tail.
18
19That means an entire Zero Trust deployment — tunnel, private network
20route, identity-gated application, WARP device profile — is now a
21single Effect (Zero Trust resources contributed by
22**[Andy Jefferson](https://github.com/microagi-andy)** in
23[#570](https://github.com/alchemy-run/alchemy/pull/570)):
24
25```typescript
26// a private network reachable only through WARP + Access
27const tunnel = yield* Cloudflare.Tunnel("Corp", {
28 ingress: [
29 { hostname: "dashboard.example.com", service: "http://localhost:3000" },
30 { service: "http_status:404" },
31 ],
32});
33
34yield* Cloudflare.TunnelRoute("PrivateNet", {
35 tunnelId: tunnel.tunnelId,
36 network: "10.4.0.0/16",
37});
38
39const allowCorp = yield* Cloudflare.AccessPolicy("AllowCorp", {
40 name: "Allow corp users",
41 decision: "allow",
42 include: [{ emailDomain: { domain: "example.com" } }],
43});
44
45yield* Cloudflare.AccessApplication("Dashboard", {
46 type: "self_hosted",
47 domain: "dashboard.example.com",
48 sessionDuration: "24h",
49 policies: [allowCorp.policyId],
50});
51
52yield* Cloudflare.DeviceDefaultProfile("Default", {
53 mode: "exclude",
54 splitTunnelExclude: [{ address: "10.0.0.0/8", description: "RFC1918" }],
55 excludeOfficeIps: true,
56});
57```
58
59## How: a test-driven SDK flywheel
60
61The resources were implemented by fleets of AI agents working
62service by service against
63[distilled](https://github.com/alchemy-run/distilled), our generated
64Cloudflare SDK. Each agent implements a service's resources, then
65live-tests them against the real API — and when a test hits an API
66behavior the types don't capture, the fix goes into the SDK as a
67typed-error patch, not a catch-block in the consumer:
68
69```json
70// submodules/distilled/packages/cloudflare/patches/turnstile/getWidget.json
71{
72 "errors": {
73 "WidgetNotFound": [{ "code": 10404 }, { "code": 10407 }],
74 "Forbidden": [{ "status": 403 }]
75 }
76}
77```
78
79Run that loop across 288 live-test suites and the SDK's patch set
80grows from 369 to **1,087 operations spanning 94 of 114 Cloudflare
81services** — in one release cycle. Each patch records how the API
82actually behaves, as a type, for every future consumer of the SDK.
83
84The full story — the loop, the patches, and the factory that ran
85them — is in
86[Looping the Generation of IaC and SDKs](/blog/2026-07-02-cloudflare-resource-factory).
87
88## Feature flags: `Cloudflare.FlagshipApp`
89
90Cloudflare's Flagship feature flags land as full resources with an
91Effect-native Worker binding
92([#602](https://github.com/alchemy-run/alchemy/pull/602)).
93Declare the app and its flags:
94
95```typescript
96const app = yield* Cloudflare.FlagshipApp("Flags", {});
97
98yield* Cloudflare.FlagshipFlag("NewCheckout", {
99 appId: app.appId,
100 key: "new-checkout",
101 defaultVariation: "off",
102 variations: { off: false, on: true },
103});
104```
105
106`FlagshipApp.bind(app)` attaches the binding to the surrounding Worker
107and returns a runtime client for evaluating flags:
108
109```typescript
110export const App = Cloudflare.FlagshipApp("Flags", {});
111
112export default Cloudflare.Worker(
113 "FlagsWorker",
114 { main: import.meta.filename },
115 Effect.gen(function* () {
116 const flags = yield* Cloudflare.FlagshipApp.bind(App);
117 return {
118 fetch: Effect.gen(function* () {
119 const enabled = yield* flags.getBooleanValue("new-checkout", false, {
120 userId: "user-42",
121 });
122 return HttpServerResponse.text(enabled ? "on" : "off");
123 }),
124 };
125 }).pipe(Effect.provide(Cloudflare.FlagshipBindingLive)),
126);
127```
128
129Every method of the runtime `Flagship` binding is mirrored as an
130Effect. Async Workers can bind the app on `env` instead and use the
131raw binding.
132
133## `Provider.list` and `alchemy unsafe nuke`
134
135Providers can now implement a `list()` lifecycle operation that
136enumerates every live resource of their type in the ambient
137account/zone
138([#620](https://github.com/alchemy-run/alchemy/pull/620)) —
139each item returned in the same `Attributes` shape `read` produces, so
140it's directly deletable.
141
142Built on top of it: `alchemy unsafe nuke`
143([#624](https://github.com/alchemy-run/alchemy/pull/624))
144enumerates everything a profile's providers can see and deletes it
145all. With 230 resource types now enumerable, a burned test account is
146a one-liner to clean:
147
148```sh
149alchemy unsafe nuke \
150 --include "Cloudflare.*" \
151 --filter 'resource.workerName === "alchemy-state-store"' \
152 --dry-run
153```
154
155`--include` / `--exclude` take provider-ID globs; `--filter` takes
156JavaScript expressions evaluated with `resource` in scope — any
157resource for which an expression is truthy is **spared**. `--dry-run`
158previews, `--yes` skips the confirmation. The command is deliberately
159hidden from `--help`; it deletes real infrastructure.
160
161## GitHub repositories and webhook events
162
163**[Justin Bennett](https://github.com/just-be-dev)** contributed
164`GitHub.Repository`
165([#607](https://github.com/alchemy-run/alchemy/pull/607)) —
166full repository lifecycle with a converging reconciler that reads by
167stable numeric id, so renaming a repo out from under the stack doesn't
168corrupt state:
169
170```typescript
171const repo = yield* GitHub.Repository("internal-tools", {
172 owner: "my-org",
173 name: "internal-tools",
174 visibility: "private",
175 deleteBranchOnMerge: true,
176});
177```
178
179On top of it, `GitHub.events` turns a repository into an **event
180source** for Cloudflare Workers
181([#619](https://github.com/alchemy-run/alchemy/pull/619)).
182Subscribing in a Worker's init provisions a `GitHub.Webhook` pointed
183at the Worker's URL; at runtime, deliveries are verified with a
184constant-time HMAC-SHA256 signature check and handed to your handler
185as fully-typed payloads:
186
187```typescript
188const secret = yield* Config.redacted("GITHUB_WEBHOOK_SECRET");
189
190// `event.name` is narrowed to "push" | "pull_request"
191yield* GitHub.events({
192 owner: "my-org",
193 repository: "my-repo",
194 events: ["push", "pull_request"],
195 secret,
196}).subscribe((event) =>
197 Effect.log(`received ${event.name} (${event.id})`),
198);
199```
200
201## S3-backed state store: `AWS.state()`
202
203AWS stacks get a first-class remote state backend, mirroring
204`Cloudflare.state()`
205([#585](https://github.com/alchemy-run/alchemy/pull/585)):
206
207```typescript
208const Stack = Alchemy.Stack(
209 "my-stack",
210 { providers: AWS.providers(), state: AWS.state() },
211 Effect.gen(function* () {
212 // ...
213 }),
214);
215```
216
217State lives at `s3://{bucket}/{prefix}{stack}/{stage}/{fqn}.json`. By
218default the bucket is an auto-created account-regional bucket
219(`alchemy-state-{accountId}-{region}-an`); pass `bucketName` /
220`prefix` to use your own. Credential resolution and bucket creation
221are deferred to the first state operation, so nothing touches AWS at
222layer construction.
223
224## Also in this release
225
226- **`bundle: false` on `Cloudflare.Worker`** uploads a prebuilt `main`
227 byte-for-byte — no rolldown, no minification — with glob-based
228 `rules` selecting additional modules. The working path for OpenNext
229 and other externally-bundled outputs. Thanks
230 **[Alex](https://github.com/agcty)**
231 ([#592](https://github.com/alchemy-run/alchemy/pull/592)).
232- **`alchemy plan` starts near-instant** — 8.2s → 1.8s warm, via
233 lazy-loading the TUI and vite plugin and deferring distilled schema
234 construction
235 ([#618](https://github.com/alchemy-run/alchemy/pull/618)).
236- **`worker.url` is stable across deploys** when the first domain is
237 unchanged, so downstream resources referencing it (e.g. webhook
238 delivery URLs) stop phantom-updating
239 ([#616](https://github.com/alchemy-run/alchemy/pull/616));
240 same for `worker.durableObjectNamespaces` when the DO class set is
241 unchanged
242 ([#617](https://github.com/alchemy-run/alchemy/pull/617)).
243- **Lambda function URLs accept full config** —
244 `url: { authType: "AWS_IAM", cors, invokeMode: "RESPONSE_STREAM" }`;
245 IAM-auth URLs drop the public permission statement. Thanks
246 **[José Netto](https://github.com/mineiro)**
247 ([#614](https://github.com/alchemy-run/alchemy/pull/614)).
248- **`alchemy dev` stays alive when an apply fails**, logging the full
249 cause instead of silently exiting. Thanks
250 **[Matthew Aylward](https://github.com/Butch78)**
251 ([#582](https://github.com/alchemy-run/alchemy/pull/582)).
252- **StaticSite forwards `dev.env`** (including Redacted secrets) to
253 the external dev-server command. Thanks
254 **[Alex](https://github.com/agcty)**
255 ([#587](https://github.com/alchemy-run/alchemy/pull/587)).
256- **Local assets binding no longer 500s** in `alchemy dev`
257 ([#613](https://github.com/alchemy-run/alchemy/pull/613)).
258- **Drizzle drift detection is cached** per plan/apply cycle, so
259 drizzle-kit's interactive rename prompt appears once instead of
260 hanging `alchemy dev`
261 ([#597](https://github.com/alchemy-run/alchemy/pull/597)).
262
263## Where to go next
264
265- [Looping the Generation of IaC and SDKs](/blog/2026-07-02-cloudflare-resource-factory)
266- [Concepts › Providers](/infrastructure-as-code/provider)
267- [Concepts › State Store](/state-store)
268- [CLI guide](/cli)
269- [Deploy a Lambda Function](/aws/compute/lambda)
270- [CHANGELOG](https://github.com/alchemy-run/alchemy/blob/main/CHANGELOG.md#v200-beta56)
271- [Compare v2.0.0-beta.55 → v2.0.0-beta.56](https://github.com/alchemy-run/alchemy/compare/v2.0.0-beta.55...v2.0.0-beta.56)