feat(sandbox-cloudflare): Cloudflare Sandbox provider worker (iii worker + CF Worker bridge)#97
feat(sandbox-cloudflare): Cloudflare Sandbox provider worker (iii worker + CF Worker bridge)#97rohitg00 wants to merge 5 commits into
Conversation
…rker + CF Worker bridge)
CF Sandbox lives inside a Durable Object on the Workers V8 runtime, so
the iii engine cannot host it directly. This crate ships two artifacts:
1. sandbox-cf/ iii worker (Node, runs on iii engine host).
Registers sandbox::cf::* functions (create, exec,
stop, list, expose_port, fs::read, fs::write).
Talks HTTPS to the bridge.
2. sandbox-cf/bridge/ Thin CF Worker deployed via wrangler. Hosts the
Sandbox Durable Object class re-exported from
@cloudflare/sandbox. Exposes HTTPS routes
matching the iii worker's function set. Auth
via shared bearer token (CF_BRIDGE_TOKEN).
Capabilities advertised: ["expose_port", "fs"]. CF Sandbox does not
ship snapshot or branch — callers that need those should pick a
different provider.
The iii worker side ships full smoke tests (5/5) against a stubbed
bridge client; the bridge ships the auth check + route shell. Both
halves' upstream calls are stubbed pending verified deploy of
@cloudflare/sandbox's getSandbox() against a real CF account.
Wire protocol between worker and bridge is stable. Lint clean (biome
+ tsc on both halves). Part of the sandbox-as-worker family.
Replaces 501 stubs with real getSandbox().* calls verified via context7
against /cloudflare/sandbox-sdk:
- POST /create → getSandbox(env.Sandbox, id, {sleepAfter}); exec('true')
to force container provisioning; returns {sandbox_id,
image, started_at}
- POST /exec → sandbox.exec(buildExecCommand(cmd, args), {timeout,
cwd, env}) → maps {stdout, stderr, exitCode, success}
to the iii ABI
- POST /stop → sandbox.destroy()
- GET /list → 501 'sdk has no list primitive' — the iii worker side
already falls back to local in_flight accounting when
the bridge can't answer (matches the resilience the
reconciliation pattern guarantees for every provider)
- POST /expose-port → sandbox.exposePort(port, {hostname, name}) using a
PREVIEW_HOSTNAME var; surfaces a clear 500 if the
operator forgot to set it (custom domain required
per the SDK contract — workers.dev won't work)
- POST /fs/read → sandbox.readFile(path); base64-encoded for the wire
- POST /fs/write → sandbox.writeFile(path, content)
proxyToSandbox runs at the top of fetch() so preview-port URLs get
routed before the bearer auth check (preview URLs carry their own
token).
Existing 5 wiremock tests on the iii worker side keep passing; bridge
typecheck clean. Live verification deferred until someone deploys the
bridge with wrangler.
iii worker side only — bridge runs CF Worker runtime and pulls @cloudflare/sandbox separately. Existing tests + typecheck still green.
Spell out the provider name everywhere — folder, branch, function ids (`sandbox::cloudflare::*`), package names (`sandbox-cloudflare`, `sandbox-cloudflare-bridge`), and env vars (`CLOUDFLARE_BRIDGE_URL`, `CLOUDFLARE_BRIDGE_TOKEN`, `SANDBOX_CLOUDFLARE_CONFIG`). `cf` was an internal shorthand that read like a half-baked acronym to anyone who hadn't been in the conversation. Matches the explicit naming the rest of the family uses (sandbox-e2b, sandbox-daytona, sandbox-morph, sandbox-vercel, sandbox-modal). Tests: 5/5 vitest, biome check + ci clean, top-level tsc clean, bridge tsc clean.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (17)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…lare::* Stops shadowing the bare sandbox::* namespace. Routes through the sandbox router worker (provider="cloudflare"); direct invocation stays supported and stable. CF Worker bridge unchanged. Handler logic, tests, S-code mapping unchanged.
|
Refactored to register only Validation: |
Member of the sandbox worker family. Read `sandbox-CONTEXT.md` (lands via #92) for family terminology and ABI contract.
What ships — two artifacts
CF Sandbox lives inside a Durable Object on the Cloudflare Workers V8 runtime, so the iii engine cannot host it directly. This crate ships two artifacts:
The bridge is implementation detail of the iii worker per the CONTEXT.md "iii primitives" decision (Q3): trigger ABI is the contract, transport is free. Caller never invokes the bridge directly.
Functions (iii worker side)
SDK shapes verified via context7 against `/cloudflare/sandbox-sdk`:
Capabilities advertised: `["expose_port","fs"]`. No `snapshot`, no `branch`.
Setup (two steps)
```bash
cd bridge && npm install
wrangler secret put CLOUDFLARE_BRIDGE_TOKEN
wrangler deploy
```
```bash
export CLOUDFLARE_BRIDGE_URL=https://...workers.dev
export CLOUDFLARE_BRIDGE_TOKEN=
iii worker add sandbox-cloudflare
```
`PREVIEW_HOSTNAME` is required on the bridge if callers will use `expose_port` (CF Sandbox's preview URLs need a custom domain — `workers.dev` won't work).
Tests
5 vitest cases on the iii worker side (allowlist, in_flight rollback, exec validation, stop error mapping, list envelope) plus `bridge/` typecheck. Bridge runtime tests (miniflare-based) deferred to a follow-up; the iii worker side has full smoke against a mocked bridge response.
Live test status
Bridge wired against documented SDK; not yet deployed end-to-end.
Pin
`iii-sdk: 0.11.6` (iii worker side only — bridge pulls `@cloudflare/sandbox` separately).