@claxedo/sandbox-manager 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -14
- package/dist/driver-catalog.d.ts +3 -53
- package/dist/driver-catalog.mjs +137 -128
- package/dist/drivers/box.mjs +143 -68
- package/dist/drivers/cloudflare.d.ts +4 -7
- package/dist/drivers/cloudflare.mjs +198 -108
- package/dist/drivers/daytona.d.ts +49 -13
- package/dist/drivers/daytona.mjs +225 -83
- package/dist/drivers/docker.mjs +118 -67
- package/dist/drivers/exe.mjs +74 -51
- package/dist/drivers/fetch-bridge.mjs +19 -4
- package/dist/drivers/modal.d.ts +2 -5
- package/dist/drivers/modal.mjs +130 -75
- package/dist/drivers/transient-error.d.ts +11 -0
- package/dist/drivers/vercel.d.ts +19 -22
- package/dist/drivers/vercel.mjs +178 -104
- package/dist/hosted-network-policy.d.ts +2 -2
- package/dist/hosted-network-policy.mjs +3 -3
- package/dist/image-name.mjs +34 -0
- package/dist/image.d.ts +2 -2
- package/dist/image.mjs +33 -11
- package/dist/index.d.ts +62 -17
- package/dist/index.mjs +68 -22
- package/dist/json.d.ts +13 -0
- package/dist/lease-policy.d.ts +6 -2
- package/dist/lease-policy.mjs +50 -40
- package/dist/lease-types.d.ts +11 -2
- package/dist/runtime-env.d.ts +12 -1
- package/dist/runtime-env.mjs +14 -0
- package/dist/service-url-exposure.d.ts +1 -2
- package/dist/service-url-exposure.mjs +1 -17
- package/dist/stores/memory.mjs +2 -2
- package/package.json +57 -55
- package/dist/drivers/cloudflare-egress.d.ts +0 -40
- package/dist/drivers/cloudflare-egress.mjs +0 -113
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ The package owns the generic pieces:
|
|
|
11
11
|
- `SandboxDriver`
|
|
12
12
|
- provider drivers for Cloudflare, Daytona, Docker, fetch bridge, Modal, and Vercel
|
|
13
13
|
|
|
14
|
-
It deliberately does not own Claxedo product auth, billing,
|
|
14
|
+
It deliberately does not own Claxedo product auth, billing, app storage schema, routes, or relay tokens. Applications provide those through adapters and call `createSandboxManager`.
|
|
15
15
|
|
|
16
16
|
## Install
|
|
17
17
|
|
|
@@ -59,8 +59,8 @@ Swap `createDockerSandboxDriver` for `createDaytonaSandboxDriver`,
|
|
|
59
59
|
`@claxedo/sandbox-manager/drivers/*`) to place on a hosted provider instead —
|
|
60
60
|
see [`docs/architecture.md`](docs/architecture.md) for the full driver
|
|
61
61
|
comparison and each provider's required options. Swap `createMemoryLeaseStore`
|
|
62
|
-
for a persisted `SandboxLeaseStore` implementation (e.g. backed by SQLite
|
|
63
|
-
|
|
62
|
+
for a persisted `SandboxLeaseStore` implementation (e.g. backed by SQLite) to
|
|
63
|
+
survive process restarts.
|
|
64
64
|
|
|
65
65
|
## Credentials & secrets
|
|
66
66
|
|
|
@@ -100,25 +100,21 @@ Per-provider mechanism (from each provider's official docs):
|
|
|
100
100
|
| --- | --- | --- |
|
|
101
101
|
| Daytona | `native` | `daytona.secret.create({name, value, hosts})`; the sandbox env holds an opaque `dtn_secret_…` placeholder and an egress proxy substitutes the real value only for allowlisted hosts ([docs](https://www.daytona.io/docs/en/secrets/)). |
|
|
102
102
|
| Vercel | `native` | Firewall header-transform (`updateNetworkPolicy`): the value is spliced onto egress to the allowlisted hosts as `header`, so the sandbox makes an unauthenticated request ([docs](https://vercel.com/docs/sandbox/concepts/firewall)). `updateNetworkPolicy` replaces the whole policy, so the driver sends the **union** of the create-time allow-list and the brokered hosts — attaching a credential must not revoke egress the caller was already granted (a mid-run `npm install` would start failing), nor widen it to a brokered host the create-time policy never approved. |
|
|
103
|
-
| Cloudflare | `
|
|
103
|
+
| Cloudflare | `native` | The driver sends named registrations to the API-token-gated Worker. KV holds the values outside the container; native HTTPS outbound handlers replace named placeholders in registered headers. Each request reads KV, so there is no expiring container JWT. KV propagation delay still applies to rotation and withdrawal. |
|
|
104
104
|
| Modal | `none` | Modal [Secrets](https://modal.com/docs/guide/secrets) are an encrypted by-reference store, but exposed as **readable env vars** inside the sandbox — they cannot satisfy the never-readable contract. |
|
|
105
105
|
| Docker, fetch | `none` | Plaintext env only. |
|
|
106
106
|
|
|
107
107
|
**Fail-closed contract.** A brokered secret is never silently downgraded to
|
|
108
|
-
readable env. `native`
|
|
109
|
-
|
|
110
|
-
only a `none` driver makes the manager refuse to provision (`status:
|
|
108
|
+
readable env. Only `native` keeps the value out of the sandbox and provisions
|
|
109
|
+
normally; a `none` driver makes the manager refuse to provision (`status:
|
|
111
110
|
"unavailable", error: "secret_brokering_unsupported"`) rather than expose or
|
|
112
111
|
drop the credential. Brokered secret values are also never written to labels,
|
|
113
112
|
never logged, and never captured in a driver snapshot.
|
|
114
113
|
|
|
115
|
-
>
|
|
116
|
-
>
|
|
117
|
-
>
|
|
118
|
-
>
|
|
119
|
-
> `x-claxedo-egress-target` header). Modal stays `none`; its secret store
|
|
120
|
-
> improves storage hygiene for *readable* credentials but does not hide them
|
|
121
|
-
> from the sandbox.
|
|
114
|
+
> Native brokering keeps the original upstream URL. Cloudflare accepts its
|
|
115
|
+
> named placeholder as the complete credential header, or with a Bearer prefix
|
|
116
|
+
> for Authorization API-key clients. Modal remains `none`: its encrypted store
|
|
117
|
+
> exposes credentials as readable environment variables inside the sandbox.
|
|
122
118
|
|
|
123
119
|
## Egress containment
|
|
124
120
|
|
package/dist/driver-catalog.d.ts
CHANGED
|
@@ -1,42 +1,11 @@
|
|
|
1
1
|
import { validateSandboxPersistenceCapabilities, type SandboxDriverMetadata } from "./index";
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
export type SandboxDriverAuth = {
|
|
5
|
-
exe?: {
|
|
6
|
-
api_token?: string;
|
|
7
|
-
};
|
|
8
|
-
daytona?: {
|
|
9
|
-
api_key?: string;
|
|
10
|
-
};
|
|
11
|
-
modal?: {
|
|
12
|
-
token_id?: string;
|
|
13
|
-
token_secret?: string;
|
|
14
|
-
};
|
|
15
|
-
vercel?: {
|
|
16
|
-
access_token?: string;
|
|
17
|
-
team_id?: string;
|
|
18
|
-
project_id?: string;
|
|
19
|
-
};
|
|
20
|
-
cloudflare?: {
|
|
21
|
-
api_token?: string;
|
|
22
|
-
worker_url?: string;
|
|
23
|
-
};
|
|
24
|
-
box?: {
|
|
25
|
-
api_key?: string;
|
|
26
|
-
};
|
|
27
|
-
docker?: {
|
|
28
|
-
image?: string;
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
export type SandboxDriverConfig = {
|
|
32
|
-
default_driver?: SandboxDriverID;
|
|
33
|
-
auth?: SandboxDriverAuth;
|
|
34
|
-
};
|
|
2
|
+
import { defaultSandboxDriverID, listSandboxDrivers, sandboxDriverId, type SandboxDriverAuth, type SandboxDriverConfig, type SandboxDriverEnv, type SandboxDriverID } from "@claxedo/sandbox-contract";
|
|
3
|
+
export { defaultSandboxDriverID, listSandboxDrivers, sandboxDriverId };
|
|
35
4
|
export type SandboxDriverCatalogEntry = {
|
|
36
5
|
id: SandboxDriverID;
|
|
37
6
|
label: string;
|
|
38
7
|
metadata: SandboxDriverMetadata;
|
|
39
|
-
credentialFields:
|
|
8
|
+
credentialFields: ReadonlyArray<{
|
|
40
9
|
key: string;
|
|
41
10
|
label: string;
|
|
42
11
|
secret?: boolean;
|
|
@@ -44,25 +13,6 @@ export type SandboxDriverCatalogEntry = {
|
|
|
44
13
|
};
|
|
45
14
|
export { validateSandboxPersistenceCapabilities };
|
|
46
15
|
export declare const sandboxDriverCatalog: Record<SandboxDriverID, SandboxDriverCatalogEntry>;
|
|
47
|
-
export declare function isSandboxDriverID(input: string | undefined): input is SandboxDriverID;
|
|
48
|
-
export declare function sandboxDriverId(input: string | undefined, cfg?: SandboxDriverConfig, env?: SandboxDriverEnv): "box" | "cloudflare" | "daytona" | "docker" | "exe" | "modal" | "vercel" | undefined;
|
|
49
|
-
export declare function defaultSandboxDriverID(cfg?: SandboxDriverConfig, env?: SandboxDriverEnv): SandboxDriverID;
|
|
50
16
|
export declare function sandboxDriverAuth<T extends SandboxDriverID>(cfg: SandboxDriverConfig | undefined, id: T, env?: SandboxDriverEnv): SandboxDriverAuth[T] | undefined;
|
|
51
17
|
export declare function hasSandboxDriverAuth(cfg: SandboxDriverConfig | undefined, id: SandboxDriverID, env?: SandboxDriverEnv): boolean;
|
|
52
18
|
export declare function dockerSandboxDriverEnabled(env?: SandboxDriverEnv): boolean;
|
|
53
|
-
export declare function listSandboxDrivers(cfg?: SandboxDriverConfig, env?: SandboxDriverEnv, managedDriverIds?: ReadonlySet<string>): {
|
|
54
|
-
default_driver: "box" | "cloudflare" | "daytona" | "docker" | "exe" | "modal" | "vercel";
|
|
55
|
-
drivers: {
|
|
56
|
-
id: "box" | "cloudflare" | "daytona" | "docker" | "exe" | "modal" | "vercel";
|
|
57
|
-
label: string;
|
|
58
|
-
fields: {
|
|
59
|
-
key: string;
|
|
60
|
-
label: string;
|
|
61
|
-
secret?: boolean;
|
|
62
|
-
}[];
|
|
63
|
-
configured: boolean;
|
|
64
|
-
source: "config" | "managed" | "none";
|
|
65
|
-
default: boolean;
|
|
66
|
-
}[];
|
|
67
|
-
};
|
|
68
|
-
type SandboxDriverEnv = Record<string, string | undefined>;
|
package/dist/driver-catalog.mjs
CHANGED
|
@@ -68,13 +68,120 @@ function defaultSandboxImage(version = workspaceRuntimeVersion(), buildId, env =
|
|
|
68
68
|
return `${sandboxImageRepository(env)}:workspace-runtime-${snapshotVersion(version)}${buildIdSuffix(buildId, env)}-v${SNAPSHOT_SCHEMA_VERSION}`;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
//
|
|
71
|
+
// ../sandbox-contract/dist/index.mjs
|
|
72
|
+
function isString(value) {
|
|
73
|
+
return typeof value === "string";
|
|
74
|
+
}
|
|
75
|
+
function trimToUndefined(value) {
|
|
76
|
+
if (!isString(value))
|
|
77
|
+
return;
|
|
78
|
+
const trimmed = value.trim();
|
|
79
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
80
|
+
}
|
|
72
81
|
var sandboxDriverIds = ["exe", "daytona", "modal", "vercel", "cloudflare", "box", "docker"];
|
|
82
|
+
var sandboxDriverCredentialFields = {
|
|
83
|
+
exe: [{ key: "api_token", label: "API Token", secret: true }],
|
|
84
|
+
daytona: [{ key: "api_key", label: "API Key", secret: true }],
|
|
85
|
+
modal: [
|
|
86
|
+
{ key: "token_id", label: "Token ID", secret: true },
|
|
87
|
+
{ key: "token_secret", label: "Token Secret", secret: true }
|
|
88
|
+
],
|
|
89
|
+
vercel: [
|
|
90
|
+
{ key: "access_token", label: "Access Token", secret: true },
|
|
91
|
+
{ key: "team_id", label: "Team ID" },
|
|
92
|
+
{ key: "project_id", label: "Project ID" }
|
|
93
|
+
],
|
|
94
|
+
cloudflare: [
|
|
95
|
+
{ key: "api_token", label: "API Token", secret: true },
|
|
96
|
+
{ key: "worker_url", label: "Worker URL" }
|
|
97
|
+
],
|
|
98
|
+
box: [{ key: "api_key", label: "API Key", secret: true }],
|
|
99
|
+
docker: [{ key: "image", label: "Image" }]
|
|
100
|
+
};
|
|
101
|
+
var sandboxDriverLabels = {
|
|
102
|
+
exe: "exe.dev",
|
|
103
|
+
daytona: "Daytona",
|
|
104
|
+
modal: "Modal",
|
|
105
|
+
vercel: "Vercel",
|
|
106
|
+
cloudflare: "Cloudflare",
|
|
107
|
+
box: "Box",
|
|
108
|
+
docker: "Docker"
|
|
109
|
+
};
|
|
110
|
+
function isSandboxDriverID(input) {
|
|
111
|
+
return !!input && sandboxDriverIds.includes(input);
|
|
112
|
+
}
|
|
113
|
+
function enabled(input) {
|
|
114
|
+
return ["1", "true", "yes", "on"].includes(input?.trim().toLowerCase() ?? "");
|
|
115
|
+
}
|
|
116
|
+
function dockerSandboxDriverEnabled(env = process.env) {
|
|
117
|
+
return enabled(env.CLAXEDO_ENABLE_DOCKER_SANDBOX) || enabled(env.CLAXEDO_DEV_DOCKER_SANDBOX);
|
|
118
|
+
}
|
|
119
|
+
function sandboxDriverAuthValues(cfg, id, env = process.env) {
|
|
120
|
+
if (id === "daytona") {
|
|
121
|
+
const api_key = trimToUndefined(cfg?.auth?.daytona?.api_key);
|
|
122
|
+
return api_key ? { api_key } : void 0;
|
|
123
|
+
}
|
|
124
|
+
if (id === "exe") {
|
|
125
|
+
const api_token = trimToUndefined(cfg?.auth?.exe?.api_token) ?? trimToUndefined(env.EXE_DEV_API_TOKEN);
|
|
126
|
+
return api_token ? { api_token } : void 0;
|
|
127
|
+
}
|
|
128
|
+
if (id === "modal") {
|
|
129
|
+
const token_id = trimToUndefined(cfg?.auth?.modal?.token_id) ?? trimToUndefined(env.MODAL_TOKEN_ID);
|
|
130
|
+
const token_secret = trimToUndefined(cfg?.auth?.modal?.token_secret) ?? trimToUndefined(env.MODAL_TOKEN_SECRET);
|
|
131
|
+
return token_id && token_secret ? { token_id, token_secret } : void 0;
|
|
132
|
+
}
|
|
133
|
+
if (id === "vercel") {
|
|
134
|
+
const access_token = trimToUndefined(cfg?.auth?.vercel?.access_token) ?? trimToUndefined(env.VERCEL_TOKEN);
|
|
135
|
+
const team_id = trimToUndefined(cfg?.auth?.vercel?.team_id) ?? trimToUndefined(env.VERCEL_TEAM_ID);
|
|
136
|
+
const project_id = trimToUndefined(cfg?.auth?.vercel?.project_id) ?? trimToUndefined(env.VERCEL_PROJECT_ID);
|
|
137
|
+
return access_token && team_id && project_id ? { access_token, team_id, project_id } : void 0;
|
|
138
|
+
}
|
|
139
|
+
if (id === "cloudflare") {
|
|
140
|
+
const api_token = trimToUndefined(cfg?.auth?.cloudflare?.api_token) ?? trimToUndefined(env.CLOUDFLARE_API_TOKEN);
|
|
141
|
+
const worker_url = trimToUndefined(cfg?.auth?.cloudflare?.worker_url) ?? trimToUndefined(env.CLOUDFLARE_SANDBOX_WORKER_URL);
|
|
142
|
+
return api_token && worker_url ? { api_token, worker_url } : void 0;
|
|
143
|
+
}
|
|
144
|
+
if (id === "box") {
|
|
145
|
+
const api_key = trimToUndefined(cfg?.auth?.box?.api_key) ?? trimToUndefined(env.BOX_API_KEY);
|
|
146
|
+
return api_key ? { api_key } : void 0;
|
|
147
|
+
}
|
|
148
|
+
if (!dockerSandboxDriverEnabled(env)) return void 0;
|
|
149
|
+
const image = trimToUndefined(cfg?.auth?.docker?.image) ?? trimToUndefined(env.CLAXEDO_DOCKER_SANDBOX_IMAGE) ?? trimToUndefined(env.CLAXEDO_SANDBOX_IMAGE);
|
|
150
|
+
return image ? { image } : {};
|
|
151
|
+
}
|
|
152
|
+
function sandboxDriverId(input, cfg, env = process.env) {
|
|
153
|
+
if (!isSandboxDriverID(input)) return void 0;
|
|
154
|
+
if (input === "docker" && !sandboxDriverAuthValues(cfg, input, env)) return void 0;
|
|
155
|
+
return input;
|
|
156
|
+
}
|
|
157
|
+
function defaultSandboxDriverID(cfg, env = process.env) {
|
|
158
|
+
return sandboxDriverId(cfg?.default_driver, cfg, env) ?? (enabled(env.CLAXEDO_DOCKER_SANDBOX_DEFAULT) && sandboxDriverAuthValues(cfg, "docker", env) ? "docker" : "daytona");
|
|
159
|
+
}
|
|
160
|
+
function listSandboxDrivers(cfg, env = process.env, managedDriverIds = /* @__PURE__ */ new Set()) {
|
|
161
|
+
const defaultDriver = defaultSandboxDriverID(cfg, env);
|
|
162
|
+
return {
|
|
163
|
+
default_driver: defaultDriver,
|
|
164
|
+
drivers: sandboxDriverIds.filter((id) => id !== "docker" || !!sandboxDriverAuthValues(cfg, "docker", env)).map((id) => {
|
|
165
|
+
const configuredFromConfigOrEnv = !!sandboxDriverAuthValues(cfg, id, env);
|
|
166
|
+
const configured = id === "docker" ? configuredFromConfigOrEnv : configuredFromConfigOrEnv || managedDriverIds.has(id);
|
|
167
|
+
return {
|
|
168
|
+
id,
|
|
169
|
+
label: sandboxDriverLabels[id],
|
|
170
|
+
fields: sandboxDriverCredentialFields[id],
|
|
171
|
+
configured,
|
|
172
|
+
source: configuredFromConfigOrEnv ? "config" : configured ? "managed" : "none",
|
|
173
|
+
default: id === defaultDriver
|
|
174
|
+
};
|
|
175
|
+
})
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// src/driver-catalog.ts
|
|
73
180
|
var sandboxDriverCatalog = {
|
|
74
181
|
exe: {
|
|
75
182
|
id: "exe",
|
|
76
|
-
label:
|
|
77
|
-
credentialFields:
|
|
183
|
+
label: sandboxDriverLabels.exe,
|
|
184
|
+
credentialFields: sandboxDriverCredentialFields.exe,
|
|
78
185
|
metadata: {
|
|
79
186
|
driverRunsIn: ["worker", "node"],
|
|
80
187
|
hostStopBehavior: "not-supported",
|
|
@@ -94,17 +201,15 @@ var sandboxDriverCatalog = {
|
|
|
94
201
|
},
|
|
95
202
|
daytona: {
|
|
96
203
|
id: "daytona",
|
|
97
|
-
label:
|
|
98
|
-
credentialFields:
|
|
204
|
+
label: sandboxDriverLabels.daytona,
|
|
205
|
+
credentialFields: sandboxDriverCredentialFields.daytona,
|
|
99
206
|
metadata: {
|
|
100
207
|
driverRunsIn: ["worker", "node"],
|
|
101
208
|
hostStopBehavior: "suspends-host",
|
|
102
209
|
hostResumeBehavior: "same-host",
|
|
103
210
|
targetAccess: "relay",
|
|
104
211
|
secretBrokering: "native",
|
|
105
|
-
//
|
|
106
|
-
// by address: `domainAllowList` (names) alongside `networkAllowList`
|
|
107
|
-
// (CIDRs), with `networkBlockAll` as the deny-all floor.
|
|
212
|
+
// The driver translates names to domainAllowList, or addresses to networkAllowList.
|
|
108
213
|
egressControl: "hosts-and-cidrs",
|
|
109
214
|
persistence: {
|
|
110
215
|
resume: "same-sandbox",
|
|
@@ -118,20 +223,15 @@ var sandboxDriverCatalog = {
|
|
|
118
223
|
},
|
|
119
224
|
modal: {
|
|
120
225
|
id: "modal",
|
|
121
|
-
label:
|
|
122
|
-
credentialFields:
|
|
123
|
-
{ key: "token_id", label: "Token ID", secret: true },
|
|
124
|
-
{ key: "token_secret", label: "Token Secret", secret: true }
|
|
125
|
-
],
|
|
226
|
+
label: sandboxDriverLabels.modal,
|
|
227
|
+
credentialFields: sandboxDriverCredentialFields.modal,
|
|
126
228
|
metadata: {
|
|
127
229
|
driverRunsIn: ["node"],
|
|
128
230
|
hostStopBehavior: "terminates-host",
|
|
129
231
|
hostResumeBehavior: "replacement-host",
|
|
130
232
|
targetAccess: "relay",
|
|
131
233
|
secretBrokering: "none",
|
|
132
|
-
//
|
|
133
|
-
// an allowlist, and its driver throws on a host policy. A blackout is
|
|
134
|
-
// not containment for a workspace that has to clone and reach a model.
|
|
234
|
+
// The driver does not install Modal's domain allowlist or alpha sidecar.
|
|
135
235
|
egressControl: "none",
|
|
136
236
|
persistence: {
|
|
137
237
|
resume: "replacement-restore",
|
|
@@ -145,20 +245,15 @@ var sandboxDriverCatalog = {
|
|
|
145
245
|
},
|
|
146
246
|
vercel: {
|
|
147
247
|
id: "vercel",
|
|
148
|
-
label:
|
|
149
|
-
credentialFields:
|
|
150
|
-
{ key: "access_token", label: "Access Token", secret: true },
|
|
151
|
-
{ key: "team_id", label: "Team ID" },
|
|
152
|
-
{ key: "project_id", label: "Project ID" }
|
|
153
|
-
],
|
|
248
|
+
label: sandboxDriverLabels.vercel,
|
|
249
|
+
credentialFields: sandboxDriverCredentialFields.vercel,
|
|
154
250
|
metadata: {
|
|
155
251
|
driverRunsIn: ["node"],
|
|
156
252
|
hostStopBehavior: "terminates-host",
|
|
157
253
|
hostResumeBehavior: "replacement-host",
|
|
158
254
|
targetAccess: "relay",
|
|
159
255
|
secretBrokering: "native",
|
|
160
|
-
//
|
|
161
|
-
// never CIDRs.
|
|
256
|
+
// The driver translates hosts only; the SDK's subnet rules are not wired to net.cidrs.
|
|
162
257
|
egressControl: "hosts",
|
|
163
258
|
persistence: {
|
|
164
259
|
resume: "replacement-restore",
|
|
@@ -172,23 +267,15 @@ var sandboxDriverCatalog = {
|
|
|
172
267
|
},
|
|
173
268
|
cloudflare: {
|
|
174
269
|
id: "cloudflare",
|
|
175
|
-
label:
|
|
176
|
-
credentialFields:
|
|
177
|
-
{ key: "api_token", label: "API Token", secret: true },
|
|
178
|
-
{ key: "worker_url", label: "Worker URL" }
|
|
179
|
-
],
|
|
270
|
+
label: sandboxDriverLabels.cloudflare,
|
|
271
|
+
credentialFields: sandboxDriverCredentialFields.cloudflare,
|
|
180
272
|
metadata: {
|
|
181
273
|
driverRunsIn: ["worker"],
|
|
182
274
|
hostStopBehavior: "not-supported",
|
|
183
275
|
hostResumeBehavior: "same-host",
|
|
184
276
|
targetAccess: "relay",
|
|
185
|
-
secretBrokering: "
|
|
186
|
-
//
|
|
187
|
-
// (drivers/cloudflare-egress.ts) is an OPT-IN proxy the sandbox chooses
|
|
188
|
-
// to route brokered-credential requests through, not a boundary. The
|
|
189
|
-
// driver therefore drops `net` entirely — which is exactly why this
|
|
190
|
-
// must be declared, so the manager refuses instead of provisioning a
|
|
191
|
-
// sandbox the caller believes is contained.
|
|
277
|
+
secretBrokering: "native",
|
|
278
|
+
// Credential handlers do not restrict unrelated destinations.
|
|
192
279
|
egressControl: "none",
|
|
193
280
|
persistence: {
|
|
194
281
|
resume: "replacement-restore",
|
|
@@ -202,8 +289,8 @@ var sandboxDriverCatalog = {
|
|
|
202
289
|
},
|
|
203
290
|
box: {
|
|
204
291
|
id: "box",
|
|
205
|
-
label:
|
|
206
|
-
credentialFields:
|
|
292
|
+
label: sandboxDriverLabels.box,
|
|
293
|
+
credentialFields: sandboxDriverCredentialFields.box,
|
|
207
294
|
metadata: {
|
|
208
295
|
driverRunsIn: ["node"],
|
|
209
296
|
hostStopBehavior: "suspends-host",
|
|
@@ -223,8 +310,8 @@ var sandboxDriverCatalog = {
|
|
|
223
310
|
},
|
|
224
311
|
docker: {
|
|
225
312
|
id: "docker",
|
|
226
|
-
label:
|
|
227
|
-
credentialFields:
|
|
313
|
+
label: sandboxDriverLabels.docker,
|
|
314
|
+
credentialFields: sandboxDriverCredentialFields.docker,
|
|
228
315
|
metadata: {
|
|
229
316
|
driverRunsIn: ["local"],
|
|
230
317
|
hostStopBehavior: "terminates-host",
|
|
@@ -243,106 +330,28 @@ var sandboxDriverCatalog = {
|
|
|
243
330
|
}
|
|
244
331
|
}
|
|
245
332
|
};
|
|
246
|
-
function isSandboxDriverID(input) {
|
|
247
|
-
return !!input && sandboxDriverIds.includes(input);
|
|
248
|
-
}
|
|
249
|
-
function sandboxDriverId(input, cfg, env = process.env) {
|
|
250
|
-
if (!isSandboxDriverID(input)) return;
|
|
251
|
-
if (input === "docker" && !sandboxDriverAuth(cfg, input, env)) return;
|
|
252
|
-
return input;
|
|
253
|
-
}
|
|
254
|
-
function defaultSandboxDriverID(cfg, env = process.env) {
|
|
255
|
-
return sandboxDriverId(cfg?.default_driver, cfg, env) ?? (dockerSandboxDefault(env) && sandboxDriverAuth(cfg, "docker", env) ? "docker" : "daytona");
|
|
256
|
-
}
|
|
257
333
|
function sandboxDriverAuth(cfg, id, env = process.env) {
|
|
258
|
-
if (id === "
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return
|
|
334
|
+
if (id === "docker") {
|
|
335
|
+
const configured = sandboxDriverAuthValues(cfg, "docker", env);
|
|
336
|
+
if (!configured) return void 0;
|
|
337
|
+
const image = configured.image ?? defaultSandboxImage(workspaceRuntimeVersion(), void 0, env);
|
|
338
|
+
return { image };
|
|
339
|
+
}
|
|
340
|
+
return sandboxDriverAuthValues(cfg, id, env);
|
|
265
341
|
}
|
|
266
342
|
function hasSandboxDriverAuth(cfg, id, env = process.env) {
|
|
267
343
|
return !!sandboxDriverAuth(cfg, id, env);
|
|
268
344
|
}
|
|
269
|
-
function
|
|
270
|
-
return
|
|
271
|
-
}
|
|
272
|
-
function listSandboxDrivers(cfg, env = process.env, managedDriverIds = /* @__PURE__ */ new Set()) {
|
|
273
|
-
const def = defaultSandboxDriverID(cfg, env);
|
|
274
|
-
return {
|
|
275
|
-
default_driver: def,
|
|
276
|
-
drivers: sandboxDriverIds.filter((id) => id !== "docker" || !!sandboxDriverAuth(cfg, "docker", env)).map((id) => {
|
|
277
|
-
const configuredFromConfigOrEnv = !!sandboxDriverAuth(cfg, id, env);
|
|
278
|
-
const configured = id === "docker" ? configuredFromConfigOrEnv : configuredFromConfigOrEnv || managedDriverIds.has(id);
|
|
279
|
-
return {
|
|
280
|
-
id,
|
|
281
|
-
label: sandboxDriverCatalog[id].label,
|
|
282
|
-
fields: sandboxDriverCatalog[id].credentialFields,
|
|
283
|
-
configured,
|
|
284
|
-
source: configuredFromConfigOrEnv ? "config" : configured ? "managed" : "none",
|
|
285
|
-
default: id === def
|
|
286
|
-
};
|
|
287
|
-
})
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
function clean(input) {
|
|
291
|
-
const txt = input?.trim();
|
|
292
|
-
return txt ? txt : void 0;
|
|
293
|
-
}
|
|
294
|
-
function enabled(input) {
|
|
295
|
-
return ["1", "true", "yes", "on"].includes(input?.trim().toLowerCase() ?? "");
|
|
296
|
-
}
|
|
297
|
-
function dockerSandboxEnabled(env) {
|
|
298
|
-
return enabled(env.CLAXEDO_ENABLE_DOCKER_SANDBOX) || enabled(env.CLAXEDO_DEV_DOCKER_SANDBOX);
|
|
299
|
-
}
|
|
300
|
-
function dockerSandboxDefault(env) {
|
|
301
|
-
return enabled(env.CLAXEDO_DOCKER_SANDBOX_DEFAULT);
|
|
302
|
-
}
|
|
303
|
-
function authDaytona(cfg) {
|
|
304
|
-
const api_key = clean(cfg?.auth?.daytona?.api_key);
|
|
305
|
-
return api_key ? { api_key } : void 0;
|
|
306
|
-
}
|
|
307
|
-
function authExe(cfg, env) {
|
|
308
|
-
const api_token = clean(cfg?.auth?.exe?.api_token) ?? clean(env.EXE_DEV_API_TOKEN);
|
|
309
|
-
return api_token ? { api_token } : void 0;
|
|
310
|
-
}
|
|
311
|
-
function authModal(cfg, env) {
|
|
312
|
-
const token_id = clean(cfg?.auth?.modal?.token_id) ?? clean(env.MODAL_TOKEN_ID);
|
|
313
|
-
const token_secret = clean(cfg?.auth?.modal?.token_secret) ?? clean(env.MODAL_TOKEN_SECRET);
|
|
314
|
-
return token_id && token_secret ? { token_id, token_secret } : void 0;
|
|
315
|
-
}
|
|
316
|
-
function authVercel(cfg, env) {
|
|
317
|
-
const access_token = clean(cfg?.auth?.vercel?.access_token) ?? clean(env.VERCEL_TOKEN);
|
|
318
|
-
const team_id = clean(cfg?.auth?.vercel?.team_id) ?? clean(env.VERCEL_TEAM_ID);
|
|
319
|
-
const project_id = clean(cfg?.auth?.vercel?.project_id) ?? clean(env.VERCEL_PROJECT_ID);
|
|
320
|
-
return access_token && team_id && project_id ? { access_token, team_id, project_id } : void 0;
|
|
321
|
-
}
|
|
322
|
-
function authCloudflare(cfg, env) {
|
|
323
|
-
const api_token = clean(cfg?.auth?.cloudflare?.api_token) ?? clean(env.CLOUDFLARE_API_TOKEN);
|
|
324
|
-
const worker_url = clean(cfg?.auth?.cloudflare?.worker_url) ?? clean(env.CLOUDFLARE_SANDBOX_WORKER_URL);
|
|
325
|
-
return api_token && worker_url ? { api_token, worker_url } : void 0;
|
|
326
|
-
}
|
|
327
|
-
function authBox(cfg, env) {
|
|
328
|
-
const api_key = clean(cfg?.auth?.box?.api_key) ?? clean(env.BOX_API_KEY);
|
|
329
|
-
return api_key ? { api_key } : void 0;
|
|
330
|
-
}
|
|
331
|
-
function authDocker(cfg, env) {
|
|
332
|
-
if (!dockerSandboxEnabled(env)) return;
|
|
333
|
-
return {
|
|
334
|
-
image: clean(cfg?.auth?.docker?.image) ?? clean(env.CLAXEDO_DOCKER_SANDBOX_IMAGE) ?? clean(env.CLAXEDO_SANDBOX_IMAGE) ?? defaultSandboxImage(workspaceRuntimeVersion(), void 0, env)
|
|
335
|
-
};
|
|
345
|
+
function dockerSandboxDriverEnabled2(env = process.env) {
|
|
346
|
+
return dockerSandboxDriverEnabled(env);
|
|
336
347
|
}
|
|
337
348
|
export {
|
|
338
349
|
defaultSandboxDriverID,
|
|
339
|
-
dockerSandboxDriverEnabled,
|
|
350
|
+
dockerSandboxDriverEnabled2 as dockerSandboxDriverEnabled,
|
|
340
351
|
hasSandboxDriverAuth,
|
|
341
|
-
isSandboxDriverID,
|
|
342
352
|
listSandboxDrivers,
|
|
343
353
|
sandboxDriverAuth,
|
|
344
354
|
sandboxDriverCatalog,
|
|
345
355
|
sandboxDriverId,
|
|
346
|
-
sandboxDriverIds,
|
|
347
356
|
validateSandboxPersistenceCapabilities
|
|
348
357
|
};
|