@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/dist/drivers/modal.mjs
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
// src/drivers/modal.ts
|
|
2
|
-
import { ModalClient, Probe } from "modal";
|
|
3
|
-
|
|
4
1
|
// src/runtime-env.ts
|
|
2
|
+
function workspaceRuntimeBootEnv(input) {
|
|
3
|
+
const env = {
|
|
4
|
+
...workspaceRuntimeTargetEnv(input),
|
|
5
|
+
...workspaceRuntimeSourceEnv(input),
|
|
6
|
+
...input.env
|
|
7
|
+
};
|
|
8
|
+
if (input.runner) env.WORKSPACE_RUNTIME_RUNNER = input.runner;
|
|
9
|
+
if (input.controlEnv?.relayJwksUrl) env.WORKSPACE_RUNTIME_RELAY_JWKS_URL = input.controlEnv.relayJwksUrl;
|
|
10
|
+
if (input.controlEnv?.relayVerifyPem) env.WORKSPACE_RUNTIME_RELAY_HOST_VERIFY_PEM = input.controlEnv.relayVerifyPem;
|
|
11
|
+
if (input.controlEnv?.managementJwksUrl) env.WORKSPACE_RUNTIME_MANAGEMENT_JWKS_URL = input.controlEnv.managementJwksUrl;
|
|
12
|
+
if (input.controlEnv?.sessionAuthorityUrl) env.WORKSPACE_RUNTIME_SESSION_AUTHORITY_URL = input.controlEnv.sessionAuthorityUrl;
|
|
13
|
+
return env;
|
|
14
|
+
}
|
|
5
15
|
function workspaceRuntimeTargetEnv(input) {
|
|
6
16
|
return {
|
|
7
17
|
WORKSPACE_RUNTIME_WORKSPACE_ID: input.workspaceId,
|
|
@@ -28,9 +38,6 @@ function shell(input) {
|
|
|
28
38
|
// src/constants.ts
|
|
29
39
|
var DEFAULT_WORKSPACE_RUNTIME_PORT = 2593;
|
|
30
40
|
|
|
31
|
-
// src/image.ts
|
|
32
|
-
import { Image, DaytonaNotFoundError } from "@daytona/sdk";
|
|
33
|
-
|
|
34
41
|
// src/runtime-version.ts
|
|
35
42
|
var DEFAULT_WORKSPACE_RUNTIME_VERSION = "0.5.2";
|
|
36
43
|
function workspaceRuntimeVersion() {
|
|
@@ -58,6 +65,19 @@ function defaultSnapshotName(version = workspaceRuntimeVersion(), buildId, env =
|
|
|
58
65
|
return `claxedo-workspace-runtime-${snapshotVersion(version)}${buildIdSuffix(buildId, env)}-v${SNAPSHOT_SCHEMA_VERSION}`;
|
|
59
66
|
}
|
|
60
67
|
|
|
68
|
+
// ../claxedo-helpers/dist/guards.mjs
|
|
69
|
+
function isRecord(value) {
|
|
70
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
71
|
+
}
|
|
72
|
+
function asRecord(value) {
|
|
73
|
+
return isRecord(value) ? value : void 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/json.ts
|
|
77
|
+
function num(input) {
|
|
78
|
+
return typeof input === "number" ? input : void 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
61
81
|
// src/image.ts
|
|
62
82
|
var SANDBOX_IMAGE_REPOSITORY = sandboxImageRepository();
|
|
63
83
|
var SANDBOX_IMAGE = process.env.CLAXEDO_SANDBOX_IMAGE || defaultSandboxImage();
|
|
@@ -89,12 +109,42 @@ var SANDBOX_BASELINE_EGRESS_HOSTS = [
|
|
|
89
109
|
...SANDBOX_PACKAGE_REGISTRY_HOSTS
|
|
90
110
|
];
|
|
91
111
|
|
|
112
|
+
// ../sandbox-contract/dist/index.mjs
|
|
113
|
+
var sandboxDriverCredentialFields = {
|
|
114
|
+
exe: [{ key: "api_token", label: "API Token", secret: true }],
|
|
115
|
+
daytona: [{ key: "api_key", label: "API Key", secret: true }],
|
|
116
|
+
modal: [
|
|
117
|
+
{ key: "token_id", label: "Token ID", secret: true },
|
|
118
|
+
{ key: "token_secret", label: "Token Secret", secret: true }
|
|
119
|
+
],
|
|
120
|
+
vercel: [
|
|
121
|
+
{ key: "access_token", label: "Access Token", secret: true },
|
|
122
|
+
{ key: "team_id", label: "Team ID" },
|
|
123
|
+
{ key: "project_id", label: "Project ID" }
|
|
124
|
+
],
|
|
125
|
+
cloudflare: [
|
|
126
|
+
{ key: "api_token", label: "API Token", secret: true },
|
|
127
|
+
{ key: "worker_url", label: "Worker URL" }
|
|
128
|
+
],
|
|
129
|
+
box: [{ key: "api_key", label: "API Key", secret: true }],
|
|
130
|
+
docker: [{ key: "image", label: "Image" }]
|
|
131
|
+
};
|
|
132
|
+
var sandboxDriverLabels = {
|
|
133
|
+
exe: "exe.dev",
|
|
134
|
+
daytona: "Daytona",
|
|
135
|
+
modal: "Modal",
|
|
136
|
+
vercel: "Vercel",
|
|
137
|
+
cloudflare: "Cloudflare",
|
|
138
|
+
box: "Box",
|
|
139
|
+
docker: "Docker"
|
|
140
|
+
};
|
|
141
|
+
|
|
92
142
|
// src/driver-catalog.ts
|
|
93
143
|
var sandboxDriverCatalog = {
|
|
94
144
|
exe: {
|
|
95
145
|
id: "exe",
|
|
96
|
-
label:
|
|
97
|
-
credentialFields:
|
|
146
|
+
label: sandboxDriverLabels.exe,
|
|
147
|
+
credentialFields: sandboxDriverCredentialFields.exe,
|
|
98
148
|
metadata: {
|
|
99
149
|
driverRunsIn: ["worker", "node"],
|
|
100
150
|
hostStopBehavior: "not-supported",
|
|
@@ -114,17 +164,15 @@ var sandboxDriverCatalog = {
|
|
|
114
164
|
},
|
|
115
165
|
daytona: {
|
|
116
166
|
id: "daytona",
|
|
117
|
-
label:
|
|
118
|
-
credentialFields:
|
|
167
|
+
label: sandboxDriverLabels.daytona,
|
|
168
|
+
credentialFields: sandboxDriverCredentialFields.daytona,
|
|
119
169
|
metadata: {
|
|
120
170
|
driverRunsIn: ["worker", "node"],
|
|
121
171
|
hostStopBehavior: "suspends-host",
|
|
122
172
|
hostResumeBehavior: "same-host",
|
|
123
173
|
targetAccess: "relay",
|
|
124
174
|
secretBrokering: "native",
|
|
125
|
-
//
|
|
126
|
-
// by address: `domainAllowList` (names) alongside `networkAllowList`
|
|
127
|
-
// (CIDRs), with `networkBlockAll` as the deny-all floor.
|
|
175
|
+
// The driver translates names to domainAllowList, or addresses to networkAllowList.
|
|
128
176
|
egressControl: "hosts-and-cidrs",
|
|
129
177
|
persistence: {
|
|
130
178
|
resume: "same-sandbox",
|
|
@@ -138,20 +186,15 @@ var sandboxDriverCatalog = {
|
|
|
138
186
|
},
|
|
139
187
|
modal: {
|
|
140
188
|
id: "modal",
|
|
141
|
-
label:
|
|
142
|
-
credentialFields:
|
|
143
|
-
{ key: "token_id", label: "Token ID", secret: true },
|
|
144
|
-
{ key: "token_secret", label: "Token Secret", secret: true }
|
|
145
|
-
],
|
|
189
|
+
label: sandboxDriverLabels.modal,
|
|
190
|
+
credentialFields: sandboxDriverCredentialFields.modal,
|
|
146
191
|
metadata: {
|
|
147
192
|
driverRunsIn: ["node"],
|
|
148
193
|
hostStopBehavior: "terminates-host",
|
|
149
194
|
hostResumeBehavior: "replacement-host",
|
|
150
195
|
targetAccess: "relay",
|
|
151
196
|
secretBrokering: "none",
|
|
152
|
-
//
|
|
153
|
-
// an allowlist, and its driver throws on a host policy. A blackout is
|
|
154
|
-
// not containment for a workspace that has to clone and reach a model.
|
|
197
|
+
// The driver does not install Modal's domain allowlist or alpha sidecar.
|
|
155
198
|
egressControl: "none",
|
|
156
199
|
persistence: {
|
|
157
200
|
resume: "replacement-restore",
|
|
@@ -165,20 +208,15 @@ var sandboxDriverCatalog = {
|
|
|
165
208
|
},
|
|
166
209
|
vercel: {
|
|
167
210
|
id: "vercel",
|
|
168
|
-
label:
|
|
169
|
-
credentialFields:
|
|
170
|
-
{ key: "access_token", label: "Access Token", secret: true },
|
|
171
|
-
{ key: "team_id", label: "Team ID" },
|
|
172
|
-
{ key: "project_id", label: "Project ID" }
|
|
173
|
-
],
|
|
211
|
+
label: sandboxDriverLabels.vercel,
|
|
212
|
+
credentialFields: sandboxDriverCredentialFields.vercel,
|
|
174
213
|
metadata: {
|
|
175
214
|
driverRunsIn: ["node"],
|
|
176
215
|
hostStopBehavior: "terminates-host",
|
|
177
216
|
hostResumeBehavior: "replacement-host",
|
|
178
217
|
targetAccess: "relay",
|
|
179
218
|
secretBrokering: "native",
|
|
180
|
-
//
|
|
181
|
-
// never CIDRs.
|
|
219
|
+
// The driver translates hosts only; the SDK's subnet rules are not wired to net.cidrs.
|
|
182
220
|
egressControl: "hosts",
|
|
183
221
|
persistence: {
|
|
184
222
|
resume: "replacement-restore",
|
|
@@ -192,23 +230,15 @@ var sandboxDriverCatalog = {
|
|
|
192
230
|
},
|
|
193
231
|
cloudflare: {
|
|
194
232
|
id: "cloudflare",
|
|
195
|
-
label:
|
|
196
|
-
credentialFields:
|
|
197
|
-
{ key: "api_token", label: "API Token", secret: true },
|
|
198
|
-
{ key: "worker_url", label: "Worker URL" }
|
|
199
|
-
],
|
|
233
|
+
label: sandboxDriverLabels.cloudflare,
|
|
234
|
+
credentialFields: sandboxDriverCredentialFields.cloudflare,
|
|
200
235
|
metadata: {
|
|
201
236
|
driverRunsIn: ["worker"],
|
|
202
237
|
hostStopBehavior: "not-supported",
|
|
203
238
|
hostResumeBehavior: "same-host",
|
|
204
239
|
targetAccess: "relay",
|
|
205
|
-
secretBrokering: "
|
|
206
|
-
//
|
|
207
|
-
// (drivers/cloudflare-egress.ts) is an OPT-IN proxy the sandbox chooses
|
|
208
|
-
// to route brokered-credential requests through, not a boundary. The
|
|
209
|
-
// driver therefore drops `net` entirely — which is exactly why this
|
|
210
|
-
// must be declared, so the manager refuses instead of provisioning a
|
|
211
|
-
// sandbox the caller believes is contained.
|
|
240
|
+
secretBrokering: "native",
|
|
241
|
+
// Credential handlers do not restrict unrelated destinations.
|
|
212
242
|
egressControl: "none",
|
|
213
243
|
persistence: {
|
|
214
244
|
resume: "replacement-restore",
|
|
@@ -222,8 +252,8 @@ var sandboxDriverCatalog = {
|
|
|
222
252
|
},
|
|
223
253
|
box: {
|
|
224
254
|
id: "box",
|
|
225
|
-
label:
|
|
226
|
-
credentialFields:
|
|
255
|
+
label: sandboxDriverLabels.box,
|
|
256
|
+
credentialFields: sandboxDriverCredentialFields.box,
|
|
227
257
|
metadata: {
|
|
228
258
|
driverRunsIn: ["node"],
|
|
229
259
|
hostStopBehavior: "suspends-host",
|
|
@@ -243,8 +273,8 @@ var sandboxDriverCatalog = {
|
|
|
243
273
|
},
|
|
244
274
|
docker: {
|
|
245
275
|
id: "docker",
|
|
246
|
-
label:
|
|
247
|
-
credentialFields:
|
|
276
|
+
label: sandboxDriverLabels.docker,
|
|
277
|
+
credentialFields: sandboxDriverCredentialFields.docker,
|
|
248
278
|
metadata: {
|
|
249
279
|
driverRunsIn: ["local"],
|
|
250
280
|
hostStopBehavior: "terminates-host",
|
|
@@ -264,6 +294,24 @@ var sandboxDriverCatalog = {
|
|
|
264
294
|
}
|
|
265
295
|
};
|
|
266
296
|
|
|
297
|
+
// src/drivers/transient-error.ts
|
|
298
|
+
function textOf(input) {
|
|
299
|
+
return typeof input === "string" ? input : "";
|
|
300
|
+
}
|
|
301
|
+
function driverErrorSignals(err) {
|
|
302
|
+
const shaped = isRecord(err) ? err : {};
|
|
303
|
+
const nested = isRecord(shaped.response) ? shaped.response : {};
|
|
304
|
+
return {
|
|
305
|
+
status: num(nested.status) ?? num(shaped.status),
|
|
306
|
+
text: `${textOf(shaped.code)} ${textOf(shaped.name)} ${textOf(shaped.message)}`.toLowerCase()
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function isTransientDriverError(err, markers) {
|
|
310
|
+
const { status, text: text2 } = driverErrorSignals(err);
|
|
311
|
+
if (status !== void 0 && status >= 500) return true;
|
|
312
|
+
return markers.some((marker) => text2.includes(marker));
|
|
313
|
+
}
|
|
314
|
+
|
|
267
315
|
// src/drivers/modal.ts
|
|
268
316
|
var DEFAULT_APP_NAME = "claxedo";
|
|
269
317
|
var DEFAULT_RUNTIME_COMMAND = "/usr/local/bin/workspace-runtime";
|
|
@@ -271,21 +319,28 @@ var DEFAULT_WORKSPACE_DIR = "/workspace";
|
|
|
271
319
|
var DEFAULT_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
272
320
|
var DEFAULT_TUNNEL_TIMEOUT_MS = 3e4;
|
|
273
321
|
var DEFAULT_OPERATION_TIMEOUT_MS = 6e4;
|
|
322
|
+
function isModalClient(value) {
|
|
323
|
+
const row = asRecord(value);
|
|
324
|
+
return typeof asRecord(row?.apps)?.fromName === "function" && typeof asRecord(row?.images)?.fromRegistry === "function" && typeof asRecord(row?.sandboxes)?.create === "function";
|
|
325
|
+
}
|
|
274
326
|
function nameFor(workspaceId) {
|
|
275
327
|
return `claxedo-${workspaceId}`;
|
|
276
328
|
}
|
|
329
|
+
var TRANSIENT_MARKERS = ["timeout", "unavailable", "deadline"];
|
|
277
330
|
function transientDriverError(err) {
|
|
278
|
-
|
|
279
|
-
const status = shaped.response?.status ?? shaped.status;
|
|
280
|
-
if (typeof status === "number" && status >= 500) return true;
|
|
281
|
-
const text = `${shaped.code ?? ""} ${shaped.name ?? ""} ${shaped.message ?? ""}`.toLowerCase();
|
|
282
|
-
return text.includes("timeout") || text.includes("unavailable") || text.includes("deadline");
|
|
331
|
+
return isTransientDriverError(err, TRANSIENT_MARKERS);
|
|
283
332
|
}
|
|
284
333
|
function createModalSandboxDriver(options) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
334
|
+
let defaultClient;
|
|
335
|
+
function resolveClient() {
|
|
336
|
+
if (options.client) return options.client;
|
|
337
|
+
defaultClient ??= import("modal").then((sdk) => {
|
|
338
|
+
const client = new sdk.ModalClient({ tokenId: options.tokenId, tokenSecret: options.tokenSecret });
|
|
339
|
+
if (!isModalClient(client)) throw new Error("modal SDK does not expose the client surface this driver uses");
|
|
340
|
+
return client;
|
|
341
|
+
});
|
|
342
|
+
return defaultClient;
|
|
343
|
+
}
|
|
289
344
|
const appName = options.appName ?? DEFAULT_APP_NAME;
|
|
290
345
|
const runtimePort = options.runtimePort ?? DEFAULT_WORKSPACE_RUNTIME_PORT;
|
|
291
346
|
const runtimeCommand = options.runtimeCommand ?? DEFAULT_RUNTIME_COMMAND;
|
|
@@ -293,29 +348,28 @@ function createModalSandboxDriver(options) {
|
|
|
293
348
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
294
349
|
const tunnelTimeoutMs = options.tunnelTimeoutMs ?? DEFAULT_TUNNEL_TIMEOUT_MS;
|
|
295
350
|
const operationTimeoutMs = options.operationTimeoutMs ?? DEFAULT_OPERATION_TIMEOUT_MS;
|
|
296
|
-
|
|
351
|
+
async function readinessProbeFor(port) {
|
|
352
|
+
if (options.readinessProbe) return options.readinessProbe(port);
|
|
353
|
+
const { Probe } = await import("modal");
|
|
354
|
+
return Probe.withTcp(port, { intervalMs: 1e3 });
|
|
355
|
+
}
|
|
297
356
|
function workspaceDirectory(input) {
|
|
298
357
|
return input.workspaceRoot ?? workspaceDir;
|
|
299
358
|
}
|
|
300
359
|
function bootEnv(input, hostId) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
};
|
|
312
|
-
if (options.runner) env.WORKSPACE_RUNTIME_RUNNER = options.runner;
|
|
313
|
-
if (options.controlEnv?.relayJwksUrl) env.WORKSPACE_RUNTIME_RELAY_JWKS_URL = options.controlEnv.relayJwksUrl;
|
|
314
|
-
if (options.controlEnv?.relayVerifyPem) env.WORKSPACE_RUNTIME_RELAY_HOST_VERIFY_PEM = options.controlEnv.relayVerifyPem;
|
|
315
|
-
if (options.controlEnv?.managementJwksUrl) env.WORKSPACE_RUNTIME_MANAGEMENT_JWKS_URL = options.controlEnv.managementJwksUrl;
|
|
316
|
-
return env;
|
|
360
|
+
return workspaceRuntimeBootEnv({
|
|
361
|
+
workspaceId: input.workspaceId,
|
|
362
|
+
hostId,
|
|
363
|
+
directory: workspaceDirectory(input),
|
|
364
|
+
port: runtimePort,
|
|
365
|
+
host: "0.0.0.0",
|
|
366
|
+
source: input.source,
|
|
367
|
+
env: input.env,
|
|
368
|
+
runner: options.runner,
|
|
369
|
+
controlEnv: options.controlEnv
|
|
370
|
+
});
|
|
317
371
|
}
|
|
318
|
-
async function image(input) {
|
|
372
|
+
async function image(client, input) {
|
|
319
373
|
if (input.bootSource?.kind === "driver-snapshot") return client.images.fromId(input.bootSource.snapshotId);
|
|
320
374
|
if (input.bootSource?.kind === "image") return client.images.fromId(input.bootSource.image);
|
|
321
375
|
if (input.snapshot) return client.images.fromId(input.snapshot);
|
|
@@ -353,9 +407,10 @@ function createModalSandboxDriver(options) {
|
|
|
353
407
|
...bootEnv(input, hostId),
|
|
354
408
|
...await options.env?.(input, { id: hostId })
|
|
355
409
|
};
|
|
410
|
+
const client = await resolveClient();
|
|
356
411
|
const sandbox = await client.sandboxes.create(
|
|
357
412
|
await client.apps.fromName(appName, { createIfMissing: true }),
|
|
358
|
-
await image(input),
|
|
413
|
+
await image(client, input),
|
|
359
414
|
{
|
|
360
415
|
name: nameFor(input.workspaceId),
|
|
361
416
|
command: ["bash", "-lc", `mkdir -p ${shell(directory)}; cd ${shell(directory)}; exec ${runtimeCommand}`],
|
|
@@ -365,7 +420,7 @@ function createModalSandboxDriver(options) {
|
|
|
365
420
|
timeoutMs,
|
|
366
421
|
...options.idleTimeoutMs !== void 0 ? { idleTimeoutMs: options.idleTimeoutMs } : {},
|
|
367
422
|
tags: { ...input.labels, "claxedo.workspaceId": input.workspaceId },
|
|
368
|
-
readinessProbe:
|
|
423
|
+
readinessProbe: await readinessProbeFor(runtimePort),
|
|
369
424
|
...network(input)
|
|
370
425
|
}
|
|
371
426
|
).catch((err) => {
|
|
@@ -376,7 +431,7 @@ function createModalSandboxDriver(options) {
|
|
|
376
431
|
return readyTarget(input, sandbox, hostId);
|
|
377
432
|
}
|
|
378
433
|
async function sandboxById(target) {
|
|
379
|
-
return
|
|
434
|
+
return (await resolveClient()).sandboxes.fromId(target.sandboxId);
|
|
380
435
|
}
|
|
381
436
|
return {
|
|
382
437
|
id: "modal",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The status and lower-cased text a driver error carries, if it carries any. */
|
|
2
|
+
export declare function driverErrorSignals(err: unknown): {
|
|
3
|
+
status: number | undefined;
|
|
4
|
+
text: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* A 5xx is transient for every driver; anything else is a per-driver judgment
|
|
8
|
+
* made from the error text, so each driver passes the markers it has actually
|
|
9
|
+
* seen its own SDK produce.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isTransientDriverError(err: unknown, markers: readonly string[]): boolean;
|
package/dist/drivers/vercel.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
1
|
+
import type { NetworkPolicy } from "@vercel/sandbox";
|
|
2
|
+
import { type SandboxBrokeredSecret, type SandboxDriver, type SandboxDriverEnsureInput } from "..";
|
|
3
|
+
import { type WorkspaceRuntimeControlEnv } from "../runtime-env";
|
|
3
4
|
type VercelSnapshotLike = {
|
|
4
5
|
snapshotId: string;
|
|
5
6
|
};
|
|
@@ -80,11 +81,7 @@ export type VercelSandboxDriverOptions = {
|
|
|
80
81
|
runtimeCommand?: string;
|
|
81
82
|
workspaceDir?: string;
|
|
82
83
|
runner?: string;
|
|
83
|
-
controlEnv?:
|
|
84
|
-
relayJwksUrl?: string;
|
|
85
|
-
relayVerifyPem?: string;
|
|
86
|
-
managementJwksUrl?: string;
|
|
87
|
-
};
|
|
84
|
+
controlEnv?: WorkspaceRuntimeControlEnv;
|
|
88
85
|
env?: (input: SandboxDriverEnsureInput, host: {
|
|
89
86
|
id: string;
|
|
90
87
|
}) => Record<string, string> | Promise<Record<string, string>>;
|
|
@@ -103,26 +100,26 @@ export type VercelSandboxDriverOptions = {
|
|
|
103
100
|
* and https://vercel.com/docs/sandbox/concepts/firewall — credentials
|
|
104
101
|
* brokering).
|
|
105
102
|
*
|
|
106
|
-
* The result is the
|
|
103
|
+
* The result is the union of `base` — the create-time allow-list — and the
|
|
107
104
|
* brokered hosts, never a replacement. Replacing it is wrong in both
|
|
108
|
-
* directions
|
|
109
|
-
* overwrites the whole policy, so a sandbox created with
|
|
110
|
-
* registry allowed loses both the instant a brokered secret is
|
|
111
|
-
* the agent's next `npm install` fails mid-run.
|
|
112
|
-
* egress
|
|
113
|
-
* reachable,
|
|
114
|
-
* attaching a credential. A union changes exactly one thing — it adds the
|
|
115
|
-
* brokered hosts,
|
|
105
|
+
* directions: it breaks egress the caller was granted, since
|
|
106
|
+
* `updateNetworkPolicy` overwrites the whole policy, so a sandbox created with
|
|
107
|
+
* git and the npm registry allowed loses both the instant a brokered secret is
|
|
108
|
+
* attached, and the agent's next `npm install` fails mid-run. It can also
|
|
109
|
+
* silently widen egress, since a brokered host that was not in the create-time
|
|
110
|
+
* list becomes reachable, installing a policy nobody approved as a side effect
|
|
111
|
+
* of attaching a credential. A union changes exactly one thing — it adds the
|
|
112
|
+
* brokered hosts, the smallest edit that makes the credential usable.
|
|
116
113
|
*
|
|
117
114
|
* `base` is the create-time `NetworkPolicy` exactly as passed to `create`, and
|
|
118
|
-
* it is
|
|
115
|
+
* it is required even though `undefined` is a legal value: `undefined` means
|
|
119
116
|
* "no policy was requested", so the merge keeps egress unrestricted, expressed
|
|
120
117
|
* as the `"*"` wildcard the record form needs for the header transforms to ride
|
|
121
|
-
* alongside it.
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
118
|
+
* alongside it. An optional parameter defaulting to
|
|
119
|
+
* deny-all-except-brokered-hosts would let an existing caller keep compiling
|
|
120
|
+
* while its egress silently widens. Spelling the base out forces that decision
|
|
121
|
+
* to be made once, visibly. A `"deny-all"` base contributes nothing, leaving
|
|
122
|
+
* deny-all-except-brokered-hosts.
|
|
126
123
|
*/
|
|
127
124
|
export declare function vercelBrokeredNetworkPolicy(secrets: SandboxBrokeredSecret[], base: NetworkPolicy | undefined): NetworkPolicy;
|
|
128
125
|
export declare function createVercelSandboxDriver(options: VercelSandboxDriverOptions): SandboxDriver;
|