feat: alchemy deployment — the cloudflare-os package with the OperatingSystem resource - #24
feat: alchemy deployment — the cloudflare-os package with the OperatingSystem resource#24sam-goodwin wants to merge 1 commit into
Conversation
…ngSystem resource Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
| @@ -0,0 +1,69 @@ | |||
| { | |||
| "name": "cloudflare-os", | |||
There was a problem hiding this comment.
This name might be wrong. Should itbe @gadgets/alchemy or something else? Up to you guys how you want to distribute
There was a problem hiding this comment.
Probably @cloudflare/cloudflare-os-alchemy or the like (I know its a mouthful)
|
This term Please provide feedback on the desired DX |
|
would love this as well |
There was a problem hiding this comment.
I would love if CI could produce and publish whatever we call the npm package containing:
- Prebuilt Worker module bundles.
- Prebuilt frontend variants for password/OAuth and Access.
- Static asset manifests and blobs.
- The complete deployment manifest.
- Full DO migration/lifecycle declarations.
- Checksums and source commit metadata.
- Supported configuration schema.
It seems like composable primitives would work well with a convenience facade, i.e.
const data = yield* OperatingSystemData("Data", {
protect: true,
});
const github = yield* BuiltinGatekeeper("GitHub", {
release: CloudflareOs.release.gatekeepers.github,
credentials: { clientId, clientSecret },
});
const os = yield* OperatingSystem("OS", {
release: CloudflareOs.release,
data,
auth: OAuthAuth({ providers: [github.auth] }),
admins: ["admin"],
gatekeepers: [
github,
BuiltinGatekeeper.Context(),
BuiltinGatekeeper.Scheduler(),
],
});| | undefined; | ||
| } | ||
|
|
||
| interface RawWranglerConfig { |
There was a problem hiding this comment.
This looks like a second, incomplete deployment-config parser. It silently ignores several things the existing release manifest handles or explicitly rejects, so the two deployment paths can drift without anyone noticing.
Could this consume the existing release manifest instead? Otherwise, I think it needs to share the same strict parser and fail on anything it doesn’t understand.
| main: NodePath.join(dir, raw.main), | ||
| compatibilityDate: raw.compatibility_date, | ||
| compatibilityFlags: raw.compatibility_flags ?? [], | ||
| durableObjects: (raw.migrations ?? []).flatMap( |
There was a problem hiding this comment.
Possible 🐛
Flattening the migration history down to class names loses tags, ordering, renames, deletes, and transfers. That’s probably enough for a fresh deployment today, but not for upgrades or adoption.
I think we need to preserve the full DO lifecycle and test deploy → write data → upgrade.
| ); | ||
| } | ||
| // Durable Object classes are reached via `ctx.exports` | ||
| // (`enable_ctx_exports`); the bindings exist to declare the classes and |
There was a problem hiding this comment.
I don't think any services actually use this compat flag so this may require updates to all the gatekeepers
| Effect.gen(function* () { | ||
| const gatekeeperSet = resolveGatekeepers(props.gatekeepers); | ||
|
|
||
| // ── Storage ──────────────────────────────────────────────────────── |
There was a problem hiding this comment.
Does this mean that they’re owned internally by the convenience component?
I’d rather have a separate protected OperatingSystemData resource, with support for caller-owned existing storage and explicit destructive deletion.
This would own:
- Blueprint KV
- Avatar KV
- Blueprint R2
- Any long-lived shared storage
| @@ -0,0 +1,69 @@ | |||
| { | |||
| "name": "cloudflare-os", | |||
There was a problem hiding this comment.
Probably @cloudflare/cloudflare-os-alchemy or the like (I know its a mouthful)
| "alchemy": ">=2.0.0-beta.67", | ||
| "effect": ">=4.0.0-beta.100 || >=4.0.0" | ||
| }, | ||
| "dependencies": { |
There was a problem hiding this comment.
This package depends on unpublished workspace packages and then runs their builds in the consumer’s environment. Those builds rely on dev dependencies and monorepo-root scripts that won’t be present after a normal npm install.
What are your thoughts on the npm package carrying prebuilt, checksummed Worker and frontend artifacts instead of rebuilding the monorepo in customer projects?
| if (props.admins !== undefined) backendEnv.ADMINS = props.admins; | ||
| const auth = props.auth; | ||
| if (auth?.gatekeepers?.length) { | ||
| backendEnv.AUTH_GATEKEEPERS = auth.gatekeepers.join(","); |
There was a problem hiding this comment.
Can we make this typed against the current gatekeeper list? Or at least validated?
I'm worried Aatypo here can leave the whole installation without a login method: the list is non-empty, password auth gets disabled, but no usable auth gatekeeper appears
Make alchemy the recommended way to deploy Cloudflare OS: a new public package,
cloudflare-os(packages/alchemy), whoseOperatingSystemresource provisions the whole system.Every prop is optional —
OperatingSystem("OS")alone deploys a working OS at the router's workers.dev URL. Gatekeepers are configured with plugin functions;context,scheduler, andmcpdeploy by default:A custom gatekeeper is any Worker (or any package following the standard capnweb layout):
The
aiprop provisions the AI Gateway, its access token, and Secrets-Store-backed provider keys — nothing to create in the dashboard:Live e2e coverage deploys a full OS, verifies it over HTTP, and destroys it:
🤖 Generated with Claude Code