{ "$schema": "node_modules/wrangler/config-schema.json", "name": "executor-cloud", "compatibility_date": "2025-04-01", "compatibility_flags": ["nodejs_compat"], "main": "src/server.ts", // The vite plugin fills in assets.directory (dist/client); the binding must // be declared here or env.ASSETS does not exist at runtime. "assets": { "binding": "ASSETS", }, "routes": [ { "pattern": "executor.sh", "custom_domain": true, }, ], "limits": { "cpu_ms": 30000, }, "observability": { "enabled": true, }, "durable_objects": { "bindings": [ { "name": "MCP_SESSION", "class_name": "McpSessionDOSqlite", }, { "name": "MCP_EXECUTION_OWNER", "class_name": "McpExecutionOwnerDirectoryDO", }, // Per-org execution rate-limit counter (abuse backstop). One instance // per organization via idFromName(orgId); a single { windowId, count } // record per instance, purged by alarm after inactivity. { "name": "EXECUTION_RATE_LIMITER", "class_name": "ExecutionRateLimiterDO", }, ], }, // The MCP session DO previously moved to a SQLite-backed class. The original // `McpSessionDO` was created on the // key-value backend (`new_classes`) and cannot be converted in place. Cloudflare // also refuses to delete a class in the same deploy that moves its binding (it // validates the delete against the live binding), so v2 only CREATES the new // SQLite class `McpSessionDOSqlite` and the `MCP_SESSION` binding moved to it. // The old KV `McpSessionDO` is left orphaned (unbound, kept as a stub export in // server.ts so the migration stays valid); it can be deleted in a later deploy // now that nothing binds it. Session state is ephemeral, so nothing is lost. "migrations": [ { "tag": "v1", "new_classes": ["McpSessionDO"], }, { "tag": "v2", "new_sqlite_classes": ["McpSessionDOSqlite"], }, { "tag": "v3", "new_sqlite_classes": ["ExecutionRateLimiterDO"], }, { "tag": "v4", "new_sqlite_classes": ["McpExecutionOwnerDirectoryDO"], }, ], "services": [ { "binding": "MARKETING", "service": "executor-marketing", }, ], "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "ca5f68119e4e4277b2ad6298a9048875", "localConnectionString": "postgresql://postgres:postgres@127.0.0.1:5433/postgres", }, ], // Plugin blob seam backend (multi-MB resolved specs). Bucket must exist // before deploy: `wrangler r2 bucket create executor-cloud-blobs`. "r2_buckets": [ { "binding": "BLOBS", "bucket_name": "executor-cloud-blobs", }, ], "placement": { "region": "aws:us-east-1", }, "worker_loaders": [ { "binding": "LOADER", }, ], // DEPLOYMENT PREREQUISITE: MCP 2026-07-28 requestState is shared between // stateless Worker isolates and session DOs. Configure the same 32+ byte // secret for both with `wrangler secret put MCP_REQUEST_STATE_KEY`. // It must never be placed in `vars` or generated independently per isolate. "vars": { // MCP_2026_07_28_ENABLED is intentionally absent: unset enables modern // inbound serving. Set the Worker var to "false" for emergency rollback; // legacy serving remains available. "VITE_PUBLIC_SITE_URL": "https://executor.sh", "VITE_PUBLIC_POSTHOG_KEY": "phc_nNLrNMALpRsfrEkZovUkfMxYbcJvHnsJHeoSPavprgLL", // Browser OTLP spans → same-origin, forwarded to Axiom by the worker // (src/observability/browser-traces.ts). Relative on purpose: the // client resolves it against the page origin, so previews work too. "VITE_PUBLIC_OTLP_TRACES_URL": "/v1/traces", // Per-session sampling: 1 = every signed-in session exports. Dial down // (e.g. "0.1") if Axiom volume becomes a cost concern. "VITE_PUBLIC_OTLP_SAMPLE_RATIO": "1", },}
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "executor-cloud",
"compatibility_date": "2025-04-01",
"compatibility_flags": ["nodejs_compat"],
"main": "src/server.ts",
// The vite plugin fills in assets.directory (dist/client); the binding must
// be declared here or env.ASSETS does not exist at runtime.
"assets": {
"binding": "ASSETS",
},
"routes": [
{
"pattern": "executor.sh",
"custom_domain": true,
},
],
"limits": {
"cpu_ms": 30000,
},
"observability": {
"enabled": true,
},
"durable_objects": {
"bindings": [
{
"name": "MCP_SESSION",
"class_name": "McpSessionDOSqlite",
},
{
"name": "MCP_EXECUTION_OWNER",
"class_name": "McpExecutionOwnerDirectoryDO",
},
// Per-org execution rate-limit counter (abuse backstop). One instance
// per organization via idFromName(orgId); a single { windowId, count }
// record per instance, purged by alarm after inactivity.
{
"name": "EXECUTION_RATE_LIMITER",
"class_name": "ExecutionRateLimiterDO",
},
],
},
// The MCP session DO previously moved to a SQLite-backed class. The original
// `McpSessionDO` was created on the
// key-value backend (`new_classes`) and cannot be converted in place. Cloudflare
// also refuses to delete a class in the same deploy that moves its binding (it
// validates the delete against the live binding), so v2 only CREATES the new
// SQLite class `McpSessionDOSqlite` and the `MCP_SESSION` binding moved to it.
// The old KV `McpSessionDO` is left orphaned (unbound, kept as a stub export in
// server.ts so the migration stays valid); it can be deleted in a later deploy
// now that nothing binds it. Session state is ephemeral, so nothing is lost.
"migrations": [
{
"tag": "v1",
"new_classes": ["McpSessionDO"],
},
{
"tag": "v2",
"new_sqlite_classes": ["McpSessionDOSqlite"],
},
{
"tag": "v3",
"new_sqlite_classes": ["ExecutionRateLimiterDO"],
},
{
"tag": "v4",
"new_sqlite_classes": ["McpExecutionOwnerDirectoryDO"],
},
],
"services": [
{
"binding": "MARKETING",
"service": "executor-marketing",
},
],
"hyperdrive": [
{
"binding": "HYPERDRIVE",
"id": "ca5f68119e4e4277b2ad6298a9048875",
"localConnectionString": "postgresql://postgres:postgres@127.0.0.1:5433/postgres",
},
],
// Plugin blob seam backend (multi-MB resolved specs). Bucket must exist
// before deploy: `wrangler r2 bucket create executor-cloud-blobs`.
"r2_buckets": [
{
"binding": "BLOBS",
"bucket_name": "executor-cloud-blobs",
},
],
"placement": {
"region": "aws:us-east-1",
},
"worker_loaders": [
{
"binding": "LOADER",
},
],
// DEPLOYMENT PREREQUISITE: MCP 2026-07-28 requestState is shared between
// stateless Worker isolates and session DOs. Configure the same 32+ byte
// secret for both with `wrangler secret put MCP_REQUEST_STATE_KEY`.
// It must never be placed in `vars` or generated independently per isolate.
"vars": {
// MCP_2026_07_28_ENABLED is intentionally absent: unset enables modern
// inbound serving. Set the Worker var to "false" for emergency rollback;
// legacy serving remains available.
"VITE_PUBLIC_SITE_URL": "https://executor.sh",
"VITE_PUBLIC_POSTHOG_KEY": "phc_nNLrNMALpRsfrEkZovUkfMxYbcJvHnsJHeoSPavprgLL",
// Browser OTLP spans → same-origin, forwarded to Axiom by the worker
// (src/observability/browser-traces.ts). Relative on purpose: the
// client resolves it against the page origin, so previews work too.
"VITE_PUBLIC_OTLP_TRACES_URL": "/v1/traces",
// Per-session sampling: 1 = every signed-in session exports. Dial down
// (e.g. "0.1") if Axiom volume becomes a cost concern.
"VITE_PUBLIC_OTLP_SAMPLE_RATIO": "1",
},
}