@moinulmoin/eden 0.8.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 CHANGED
@@ -12,15 +12,15 @@ If you already have an Eve project, start with `eden deploy`.
12
12
  Use any one of these package managers:
13
13
 
14
14
  ```sh
15
- npm install --global @moinulmoin/eden@0.8.0
15
+ npm install --global @moinulmoin/eden@0.9.0
16
16
  ```
17
17
 
18
18
  ```sh
19
- pnpm add --global @moinulmoin/eden@0.8.0
19
+ pnpm add --global @moinulmoin/eden@0.9.0
20
20
  ```
21
21
 
22
22
  ```sh
23
- bun add --global @moinulmoin/eden@0.8.0
23
+ bun add --global @moinulmoin/eden@0.9.0
24
24
  ```
25
25
 
26
26
  Then confirm the CLI is available:
@@ -8,7 +8,7 @@ import { execFile, spawn, } from "node:child_process";
8
8
  import { fileURLToPath, } from "node:url";
9
9
  import { promisify, } from "node:util";
10
10
  import { EveCliError, EVE_NAME_PATTERN, } from "./eve.js";
11
- import { buildEveProjectSnapshot, createDockerEveProjectBuilder, revalidateEveProjectCandidateInputs, EvePackagingError, IMAGE_ID_PATTERN, } from "./eve-packaging.js";
11
+ import { buildEveProjectSnapshot, checkEveSandboxProvider, createDockerEveProjectBuilder, revalidateEveProjectCandidateInputs, EvePackagingError, IMAGE_ID_PATTERN, } from "./eve-packaging.js";
12
12
  import { buildEveRuntimeImage, discardEveRuntimeImage, revalidateEveRuntimeCandidate, validateEveHostRequirements, } from "./eve-runtime-image.js";
13
13
  import { EveRuntimeConfigError, prepareEveRuntimeInjection, redactEveRuntimeOutput, } from "./eve-runtime-config.js";
14
14
  import { createEveHostConfig, generateEveHostWorkerSource, parseEveScheduleCron, resolveStableWorkersDevOrigin, } from "@moinulmoin/eden-runtime-cloudflare";
@@ -65,6 +65,7 @@ function mapPackagingCheck(value) {
65
65
  case "DOCKER_PLATFORM_BLOCKED":
66
66
  return "VAL-BUILD-005";
67
67
  case "EVE_SANDBOX_RESUME_PATCH":
68
+ case "EVE_SANDBOX_PROVIDER":
68
69
  return value.id;
69
70
  default:
70
71
  return `EVE-${value.id}`;
@@ -2053,6 +2054,22 @@ async function collectEvePreflight(request, options) {
2053
2054
  runtimeConfig,
2054
2055
  };
2055
2056
  }
2057
+ const sandboxProvider = await checkEveSandboxProvider(request.projectRoot);
2058
+ if (sandboxProvider !== undefined) {
2059
+ checks.push(check(sandboxProvider.code, "failed", sandboxProvider.message, sandboxProvider.remediation));
2060
+ return {
2061
+ result: {
2062
+ command: request.command === "deploy" ? "eve deploy" : "eve preflight",
2063
+ ok: false,
2064
+ environment: request.environment,
2065
+ name: request.name,
2066
+ checks,
2067
+ warnings,
2068
+ candidate: null,
2069
+ },
2070
+ runtimeConfig,
2071
+ };
2072
+ }
2056
2073
  warnings.push(...await collectEveSetupWarnings(request.projectRoot));
2057
2074
  eveProgress(options, "packaging project — snapshot, frozen install, eve build");
2058
2075
  const nodeImage = options.nodeImage ?? DEFAULT_EVE_NODE_IMAGE;
@@ -1,5 +1,5 @@
1
1
  import { type EveRuntimeInputIdentity } from "./eve-runtime-config.js";
2
- export type EvePackagingCode = "ROOT_INVALID" | "UNSUPPORTED_TOOLCHAIN" | "DEPENDENCY_AMBIGUITY" | "SOURCE_RACE" | "EVE_BUILD_FAILED" | "UNSUPPORTED_EVE_OUTPUT" | "RUNTIME_CLOSURE_INCOMPLETE" | "SECRET_EXCLUSION_FAILED" | "DOCKER_PLATFORM_BLOCKED" | "UNSUPPORTED_HOST_REQUIREMENT" | "EVE_HEALTH_FAILED" | "WORLD_MIGRATION_FAILED" | "CLEANUP_UNVERIFIED";
2
+ export type EvePackagingCode = "ROOT_INVALID" | "UNSUPPORTED_TOOLCHAIN" | "DEPENDENCY_AMBIGUITY" | "SOURCE_RACE" | "EVE_BUILD_FAILED" | "EVE_SANDBOX_PROVIDER" | "UNSUPPORTED_EVE_OUTPUT" | "RUNTIME_CLOSURE_INCOMPLETE" | "SECRET_EXCLUSION_FAILED" | "DOCKER_PLATFORM_BLOCKED" | "UNSUPPORTED_HOST_REQUIREMENT" | "EVE_HEALTH_FAILED" | "WORLD_MIGRATION_FAILED" | "CLEANUP_UNVERIFIED";
3
3
  export interface EveRuntimeConfigExclusion {
4
4
  /**
5
5
  * This path is opaque. The packaging worker only uses its lexical identity
@@ -228,9 +228,10 @@ export interface EveProjectPackagingResult {
228
228
  readonly checks: readonly EvePackagingCheck[];
229
229
  /**
230
230
  * Outcome of the builder's temporary eve#4440 sandbox-resume patch:
231
- * `applied` when the shipped just-bash binding carries it, `skipped` when
232
- * the binding is a version Eden does not know, `absent` when this Eve
233
- * build has no just-bash binding or packaging never reached the image.
231
+ * `applied` when the shipped just-bash binding carries it, `fixed` when the
232
+ * installed Eve already includes the upstream fix, `skipped` when the
233
+ * binding is a version Eden does not know, `absent` when this Eve build has
234
+ * no just-bash binding or packaging never reached the image.
234
235
  */
235
236
  readonly sandboxResumePatch: EveSandboxResumePatchStatus;
236
237
  readonly candidateImageId: string | null;
@@ -272,6 +273,25 @@ export declare const EVE_SANDBOX_RESUME_PATCH_KNOWN_SHA256 = "0ba0ac3a237c99af2f
272
273
  export declare const EVE_SANDBOX_RESUME_PATCH_LATEST_SHA256 = "ab8b1ad7398af8f6fd2a1e91eb0d1ff8d2b9b9afe1836234f36ce0e896791c45";
273
274
  /** Marker the patched binding always contains; proves the patch shipped. */
274
275
  export declare const EVE_SANDBOX_RESUME_PATCH_SIGNATURE = "edenRefreshJustBashSessionSkills";
276
+ /**
277
+ * First Eve release whose just-bash provider keeps a session's files across
278
+ * template changes (vercel/eve#5132), so the patch is not needed from here on.
279
+ */
280
+ export declare const EVE_SANDBOX_RESUME_FIXED_VERSION = "0.83.0";
281
+ /**
282
+ * True when an installed Eve version already ships the eve#4440 fix. A
283
+ * prerelease of the fixed version sorts before it (semver), so it may predate
284
+ * the fix and keeps the patch.
285
+ */
286
+ export declare function eveIncludesSandboxResumeFix(version: unknown): boolean;
287
+ /**
288
+ * Early, source-level rejection of sandbox setups that cannot work in Eden's
289
+ * isolated builder: a native provider named in the sandbox module, or, on Eve
290
+ * 0.83.0 and later, DefaultSandbox (no module, or one that names it without
291
+ * JustBash). Anything it cannot recognize is left to
292
+ * checkPreparedJustBashTemplate, which inspects what `eve build` produced.
293
+ */
294
+ export declare function checkEveSandboxProvider(projectRoot: string, resolvedVersion?: string): Promise<EvePackagingError | undefined>;
275
295
  /** The exact `resume()` implementation in Eve 0.68.0, 0.71.2, 0.72.1, and 0.79.1. */
276
296
  export declare const EVE_JUST_BASH_RESUME_ORIGINAL = "async resume(e,n,r){let i=requirePreparedJustBashArtifact(n),a=requireJustBashSessionState(r),o=createSandboxProviderIdentity({artifact:i,version:1}),s=sessionRootPath(e,i);if(a.generation!==o||a.rootPath!==s)throw Error(`just-bash session state is incompatible with this environment.`);if(!await pathExists(a.rootPath))throw Error(`just-bash session root \"${a.rootPath}\" no longer exists.`);return await openHandle(e,a.rootPath,t)}";
277
297
  /**
@@ -305,7 +325,7 @@ export declare const EVE_SANDBOX_RESUME_PATCH_HELPERS = "async function edenRefr
305
325
  */
306
326
  export declare const EVE_SANDBOX_RESUME_PATCH_SCRIPT: string;
307
327
  /** Outcome of the builder's sandbox-resume patch for the packaged image. */
308
- export type EveSandboxResumePatchStatus = "applied" | "skipped" | "absent";
328
+ export type EveSandboxResumePatchStatus = "applied" | "fixed" | "skipped" | "absent";
309
329
  export declare function sha256(value: string | Buffer): string;
310
330
  export declare function jsonBytes(value: unknown): Buffer;
311
331
  export declare function isWithin(root: string, candidate: string): boolean;
@@ -48,6 +48,150 @@ export const EVE_SANDBOX_RESUME_PATCH_KNOWN_SHA256 = "0ba0ac3a237c99af2f67a6028f
48
48
  export const EVE_SANDBOX_RESUME_PATCH_LATEST_SHA256 = "ab8b1ad7398af8f6fd2a1e91eb0d1ff8d2b9b9afe1836234f36ce0e896791c45";
49
49
  /** Marker the patched binding always contains; proves the patch shipped. */
50
50
  export const EVE_SANDBOX_RESUME_PATCH_SIGNATURE = "edenRefreshJustBashSessionSkills";
51
+ /**
52
+ * First Eve release whose just-bash provider keeps a session's files across
53
+ * template changes (vercel/eve#5132), so the patch is not needed from here on.
54
+ */
55
+ export const EVE_SANDBOX_RESUME_FIXED_VERSION = "0.83.0";
56
+ /** `major.minor.patch` of a version string; prerelease and build suffixes are dropped. */
57
+ function parseEveRelease(version) {
58
+ const match = typeof version === "string"
59
+ ? /^(\d+)\.(\d+)\.(\d+)/u.exec(version)
60
+ : null;
61
+ return match === null
62
+ ? null
63
+ : [Number(match[1]), Number(match[2]), Number(match[3])];
64
+ }
65
+ /**
66
+ * True when an installed Eve version already ships the eve#4440 fix. A
67
+ * prerelease of the fixed version sorts before it (semver), so it may predate
68
+ * the fix and keeps the patch.
69
+ */
70
+ export function eveIncludesSandboxResumeFix(version) {
71
+ const installed = parseEveRelease(version);
72
+ const fixed = parseEveRelease(EVE_SANDBOX_RESUME_FIXED_VERSION);
73
+ if (installed === null || fixed === null)
74
+ return false;
75
+ for (let index = 0; index < 3; index += 1) {
76
+ if (installed[index] !== fixed[index]) {
77
+ return (installed[index] ?? 0) > (fixed[index] ?? 0);
78
+ }
79
+ }
80
+ return typeof version === "string" && !/^\d+\.\d+\.\d+-/u.test(version);
81
+ }
82
+ /** Eve 0.83.0 and later no longer fall back to just-bash in production builds. */
83
+ function eveRequiresExplicitJustBash(version) {
84
+ const release = parseEveRelease(version);
85
+ return release !== null && (release[0] > 0 || release[1] >= 83);
86
+ }
87
+ /**
88
+ * Eve reads its sandbox module from either path, with any source extension.
89
+ * When `agent/sandbox/` exists only the nested module counts: Eve 0.83–0.86
90
+ * silently ignores `agent/sandbox.ts` and 0.87+ fails the build.
91
+ */
92
+ const EVE_SANDBOX_MODULE_PATHS = ["agent/sandbox", "agent/sandbox/sandbox"].flatMap((base) => ["ts", "mts", "cts", "tsx", "js", "mjs", "cjs", "jsx"].map((extension) => `${base}.${extension}`));
93
+ function justBashRemediation(command, path) {
94
+ return `Run ${command} (production dependency), then create or replace ${path} with:\nimport { defineSandbox } from 'eve/sandbox';\nimport { JustBashSandbox } from 'eve/sandbox/just-bash';\nexport const environment = JustBashSandbox.environment();\nexport default defineSandbox(() => environment.open());\nCommit the module, package.json, and updated lockfile, then retry eden preflight. See docs/deploy.md. Do not set EVE_DEV.`;
95
+ }
96
+ /**
97
+ * Early, source-level rejection of sandbox setups that cannot work in Eden's
98
+ * isolated builder: a native provider named in the sandbox module, or, on Eve
99
+ * 0.83.0 and later, DefaultSandbox (no module, or one that names it without
100
+ * JustBash). Anything it cannot recognize is left to
101
+ * checkPreparedJustBashTemplate, which inspects what `eve build` produced.
102
+ */
103
+ export async function checkEveSandboxProvider(projectRoot, resolvedVersion) {
104
+ const source = async (path) => readFile(join(projectRoot, path), "utf8").catch(() => "");
105
+ const json = async (path) => {
106
+ try {
107
+ const value = JSON.parse(await source(path));
108
+ return value !== null && typeof value === "object" && !Array.isArray(value)
109
+ ? value
110
+ : {};
111
+ }
112
+ catch {
113
+ return {};
114
+ }
115
+ };
116
+ const manifest = await json("package.json");
117
+ const dependencies = manifest.dependencies;
118
+ const lock = await json("package-lock.json");
119
+ const packages = lock.packages;
120
+ const pnpmLock = await source("pnpm-lock.yaml");
121
+ const pnpmVersion = /^\s{6}eve:\s*\r?\n\s{8}specifier:[^\n]*\r?\n\s{8}version:\s*['"]?(\d+\.\d+\.\d+(?:-[^('"\s]+)?)/mu
122
+ .exec(pnpmLock)?.[1];
123
+ const installed = await json("node_modules/eve/package.json");
124
+ const declared = typeof dependencies?.eve === "string"
125
+ ? /^[~^]?(\d+\.\d+\.\d+)/u.exec(dependencies.eve)?.[1]
126
+ : undefined;
127
+ const version = resolvedVersion ?? packages?.["node_modules/eve"]?.version ??
128
+ pnpmVersion ?? installed.version ?? declared;
129
+ const requiresExplicit = eveRequiresExplicitJustBash(version);
130
+ const sandboxDirectory = (await lstat(join(projectRoot, "agent/sandbox")).catch(() => undefined))
131
+ ?.isDirectory() === true;
132
+ let path;
133
+ for (const candidate of EVE_SANDBOX_MODULE_PATHS) {
134
+ if ((await lstat(join(projectRoot, candidate)).catch(() => undefined))?.isFile() === true) {
135
+ path = candidate;
136
+ break;
137
+ }
138
+ }
139
+ const module = path === undefined
140
+ ? ""
141
+ : (await source(path)).replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*/gu, "");
142
+ const otherProvider = /\b(DefaultSandbox|DockerSandbox|VercelSandbox|VmSandbox|VMSandbox)\b/u
143
+ .exec(module)?.[1];
144
+ const justBash = /import\s*\{[^}]*?\bJustBashSandbox(?:\s+as\s+(\w+))?\s*(?:,|\})[^;]*?from\s*["']eve\/sandbox\/just-bash["']/u
145
+ .exec(module);
146
+ const binding = justBash?.[1] ?? "JustBashSandbox";
147
+ const explicit = justBash !== null &&
148
+ new RegExp(`\\b${binding}\\s*\\.\\s*environment\\s*\\(`, "u").test(module);
149
+ const native = otherProvider !== undefined && otherProvider !== "DefaultSandbox";
150
+ const usesDefault = path === undefined || (otherProvider === "DefaultSandbox" && !explicit);
151
+ const shadowed = requiresExplicit && sandboxDirectory && path?.startsWith("agent/sandbox.") === true;
152
+ if (!native && !shadowed && !(requiresExplicit && usesDefault))
153
+ return undefined;
154
+ const target = shadowed || (path === undefined && sandboxDirectory)
155
+ ? "agent/sandbox/sandbox.ts"
156
+ : path ?? "agent/sandbox.ts";
157
+ const command = typeof manifest.packageManager === "string" &&
158
+ manifest.packageManager.startsWith("pnpm@")
159
+ ? "pnpm add just-bash"
160
+ : "npm install just-bash";
161
+ return new EvePackagingError({
162
+ code: "EVE_SANDBOX_PROVIDER",
163
+ subject: target,
164
+ reason: shadowed
165
+ ? `${String(path)} sits beside the agent/sandbox/ directory, where Eve ${String(version)} reads only agent/sandbox/sandbox.ts: Eve 0.83–0.86 ignores ${String(path)} and falls back to DefaultSandbox, and 0.87 and later fail the build.`
166
+ : native
167
+ ? `${target} selects ${otherProvider}, which Eden does not support; use explicit JustBash instead.`
168
+ : path === undefined
169
+ ? `Eve ${String(version)} has no sandbox module, so it uses DefaultSandbox, which has no provider in Eden's isolated builder: production builds no longer fall back to just-bash.`
170
+ : `${target} selects DefaultSandbox, which has no provider in Eden's isolated builder on Eve ${String(version)}: production builds no longer fall back to just-bash.`,
171
+ remediation: shadowed
172
+ ? `Move ${String(path)} to agent/sandbox/sandbox.ts (delete it instead if agent/sandbox/sandbox.ts already exists), then retry eden preflight.`
173
+ : justBashRemediation(command, target),
174
+ });
175
+ }
176
+ /**
177
+ * Ground truth after `eve build`: on Eve 0.83.0 and later an agent whose
178
+ * sandbox resolved to no provider prepares no template and would fail to open
179
+ * its sandbox on Cloudflare, however its sandbox module is written.
180
+ */
181
+ async function checkPreparedJustBashTemplate(snapshotRoot, version) {
182
+ if (!eveRequiresExplicitJustBash(version))
183
+ return undefined;
184
+ const templatesPath = `${EVE_SANDBOX_CACHE_ROOT}/just-bash/templates`;
185
+ const templates = await readdir(join(snapshotRoot, templatesPath)).catch(() => []);
186
+ if (templates.length > 0)
187
+ return undefined;
188
+ return new EvePackagingError({
189
+ code: "EVE_SANDBOX_PROVIDER",
190
+ subject: templatesPath,
191
+ reason: `Eve ${version} built no just-bash sandbox template, so the agent's sandbox would fail to open on Cloudflare; its sandbox module does not resolve to JustBash.`,
192
+ remediation: justBashRemediation("npm install just-bash (or pnpm add just-bash)", "agent/sandbox.ts (agent/sandbox/sandbox.ts when agent/sandbox/ exists)"),
193
+ });
194
+ }
51
195
  /** Path of the just-bash binding inside the resolved Eve package root. */
52
196
  const EVE_JUST_BASH_BINDING_PATH = "dist/src/execution/sandbox/bindings/just-bash.js";
53
197
  /** The exact `resume()` implementation in Eve 0.68.0, 0.71.2, 0.72.1, and 0.79.1. */
@@ -107,9 +251,23 @@ const KNOWN_PATCHES = ${JSON.stringify({
107
251
  const SIGNATURE = ${JSON.stringify(EVE_SANDBOX_RESUME_PATCH_SIGNATURE)};
108
252
  const BINDING_PATH = ${JSON.stringify(EVE_JUST_BASH_BINDING_PATH)};
109
253
  const HELPERS = ${JSON.stringify(EVE_SANDBOX_RESUME_PATCH_HELPERS)};
254
+ const FIXED_VERSION = ${JSON.stringify(EVE_SANDBOX_RESUME_FIXED_VERSION)};
110
255
  function finish(outcome, detail) {
111
256
  console.log("eden-eve-sandbox-resume-patch: " + outcome + " (" + detail + ")");
112
257
  }
258
+ function parseRelease(version) {
259
+ const match = typeof version === "string" ? /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(version) : null;
260
+ return match === null ? null : [Number(match[1]), Number(match[2]), Number(match[3])];
261
+ }
262
+ function includesFix(version) {
263
+ const installed = parseRelease(version);
264
+ const fixed = parseRelease(FIXED_VERSION);
265
+ if (installed === null || fixed === null) return false;
266
+ for (let index = 0; index < 3; index += 1) {
267
+ if (installed[index] !== fixed[index]) return installed[index] > fixed[index];
268
+ }
269
+ return !/^\\d+\\.\\d+\\.\\d+-/.test(version);
270
+ }
113
271
  let packageJsonPath;
114
272
  try {
115
273
  packageJsonPath = fs.realpathSync("node_modules/eve/package.json");
@@ -125,6 +283,16 @@ try {
125
283
  finish("absent", "this eve build has no just-bash binding");
126
284
  process.exit(0);
127
285
  }
286
+ let eveVersion;
287
+ try {
288
+ eveVersion = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).version;
289
+ } catch {
290
+ eveVersion = undefined;
291
+ }
292
+ if (!source.includes(SIGNATURE) && includesFix(eveVersion)) {
293
+ finish("fixed", "eve " + eveVersion + " includes the upstream fix for eve#4440");
294
+ process.exit(0);
295
+ }
128
296
  if (source.includes(SIGNATURE)) {
129
297
  finish("applied", "already patched");
130
298
  process.exit(0);
@@ -1475,6 +1643,14 @@ async function scanGeneratedSandboxCache(snapshotRoot) {
1475
1643
  const relativePath = relativeDirectory.length === 0
1476
1644
  ? entry.name
1477
1645
  : `${relativeDirectory}/${entry.name}`;
1646
+ if (relativeDirectory === "" && entry.name !== "just-bash") {
1647
+ throw new EvePackagingError({
1648
+ code: "EVE_SANDBOX_PROVIDER",
1649
+ subject: `${EVE_SANDBOX_CACHE_ROOT}/${entry.name}`,
1650
+ reason: `The Eve build prepared a ${entry.name} sandbox template; Eden supports only just-bash templates.`,
1651
+ remediation: "Replace the sandbox module with the explicit JustBash environment in docs/deploy.md, run npm install just-bash (or pnpm add just-bash), commit the module and lockfile, then retry eden preflight without EVE_DEV.",
1652
+ });
1653
+ }
1478
1654
  const candidate = join(directory, entry.name);
1479
1655
  if (entry.isSymbolicLink()) {
1480
1656
  throw new EvePackagingError({
@@ -1691,20 +1867,39 @@ function classifyNpmInstallFailure(stderr) {
1691
1867
  remediation: "Fix the reported npm failure; regenerate package-lock.json with the selected exact npm version if it is out of sync. Use public registry dependencies without .npmrc credentials or dependency build scripts.",
1692
1868
  });
1693
1869
  }
1870
+ /**
1871
+ * The failing BuildKit step's own output (`#<step> <seconds> <line>`), last 20
1872
+ * lines, so Eve's error reaches the user instead of a generic build failure.
1873
+ */
1874
+ function failingDockerStepOutput(stderr) {
1875
+ const step = [...stderr.matchAll(/^#(\d+) ERROR:/gmu)].at(-1)?.[1];
1876
+ if (step === undefined)
1877
+ return undefined;
1878
+ const lines = [...stderr.matchAll(new RegExp(`^#${step} \\d+\\.\\d+ (.*)$`, "gmu"))]
1879
+ .map((match) => (match[1] ?? "").trimEnd())
1880
+ .filter((line) => line.length > 0)
1881
+ .slice(-20);
1882
+ if (lines.length === 0)
1883
+ return undefined;
1884
+ const output = lines.join("\n");
1885
+ return output.length > 2000 ? `…${output.slice(-2000)}` : output;
1886
+ }
1694
1887
  function classifyEveBuildFailure(stderr) {
1888
+ const output = failingDockerStepOutput(stderr);
1889
+ const reported = output === undefined ? "" : `\nEve reported:\n${output}`;
1695
1890
  if (/\bjust-bash\b/u.test(stderr)) {
1696
1891
  return new EvePackagingError({
1697
1892
  code: "EVE_BUILD_FAILED",
1698
1893
  subject: "eve build",
1699
- reason: "The project-local Eve build failed inside the isolated Linux/amd64 builder because Eve's default sandbox needs just-bash where no Docker daemon or /dev/kvm exists.",
1894
+ reason: `The project-local Eve build failed inside the isolated Linux/amd64 builder because Eve's default sandbox needs just-bash where no Docker daemon or /dev/kvm exists.${reported}`,
1700
1895
  remediation: "Declare just-bash as a production dependency of the Eve project, regenerate its package-manager lockfile, and retry.",
1701
1896
  });
1702
1897
  }
1703
1898
  return new EvePackagingError({
1704
1899
  code: "EVE_BUILD_FAILED",
1705
1900
  subject: "eve build",
1706
- reason: "The project-local Eve build failed inside the isolated Linux/amd64 builder.",
1707
- remediation: "Fix the project-local Eve build and retry without changing the authored project during packaging.",
1901
+ reason: `The project-local Eve build failed inside the isolated Linux/amd64 builder.${reported}`,
1902
+ remediation: "Fix the error Eve reported (run eve build locally to reproduce it) and retry.",
1708
1903
  });
1709
1904
  }
1710
1905
  function classifyDockerBuildFailure(error) {
@@ -1818,9 +2013,18 @@ async function detectEveSandboxResumePatch(snapshotRoot) {
1818
2013
  try {
1819
2014
  const packageJsonPath = await realpath(join(snapshotRoot, "node_modules/eve/package.json"));
1820
2015
  const binding = await readFile(join(dirname(packageJsonPath), EVE_JUST_BASH_BINDING_PATH), "utf8");
1821
- return binding.includes(EVE_SANDBOX_RESUME_PATCH_SIGNATURE)
1822
- ? "applied"
1823
- : "skipped";
2016
+ if (binding.includes(EVE_SANDBOX_RESUME_PATCH_SIGNATURE))
2017
+ return "applied";
2018
+ const version = await readFile(packageJsonPath, "utf8")
2019
+ .then((text) => {
2020
+ const manifest = JSON.parse(text);
2021
+ return typeof manifest === "object" && manifest !== null &&
2022
+ "version" in manifest
2023
+ ? manifest.version
2024
+ : undefined;
2025
+ })
2026
+ .catch(() => undefined);
2027
+ return eveIncludesSandboxResumeFix(version) ? "fixed" : "skipped";
1824
2028
  }
1825
2029
  catch {
1826
2030
  return "absent";
@@ -2028,6 +2232,9 @@ export async function buildEveProjectSnapshot(options) {
2028
2232
  const afterCopyRace = await sourceRaceErrorIfChanged(roots.canonicalRoot, initialInputs, initialRuntimeInputIdentity, options.runtimeConfig, resolve(options.artifactRoot), roots.requestedRoot);
2029
2233
  if (afterCopyRace !== undefined)
2030
2234
  return blockedResult(afterCopyRace, { writtenPaths });
2235
+ const sandboxProvider = await checkEveSandboxProvider(snapshotRoot);
2236
+ if (sandboxProvider !== undefined)
2237
+ throw sandboxProvider;
2031
2238
  const nodeImage = options.nodeImage ?? options.builder.nodeImage;
2032
2239
  let actualDockerfilePath;
2033
2240
  if (nodeImage !== undefined) {
@@ -2094,9 +2301,15 @@ export async function buildEveProjectSnapshot(options) {
2094
2301
  return blockedResult(cleanupError ?? dependencyError, { writtenPaths });
2095
2302
  }
2096
2303
  const eve = await resolveProjectLocalEve(snapshotRoot);
2304
+ const sandboxProviderAfterBuild = await checkEveSandboxProvider(snapshotRoot, eve.version);
2305
+ if (sandboxProviderAfterBuild !== undefined)
2306
+ throw sandboxProviderAfterBuild;
2097
2307
  const sandboxResumePatch = await detectEveSandboxResumePatch(snapshotRoot);
2098
2308
  const output = await scanGeneratedOutput(snapshotRoot);
2099
2309
  const sandboxCache = await scanGeneratedSandboxCache(snapshotRoot);
2310
+ const preparedTemplate = await checkPreparedJustBashTemplate(snapshotRoot, eve.version);
2311
+ if (preparedTemplate !== undefined)
2312
+ throw preparedTemplate;
2100
2313
  await assertGeneratedTreesExcludeSecrets(snapshotRoot);
2101
2314
  const snapshotSourceDigest = await snapshotDigest(snapshotRoot);
2102
2315
  const runtimeManifestPath = join(generationRoot, "runtime-manifest.json");
@@ -2277,6 +2490,15 @@ export async function buildEveProjectSnapshot(options) {
2277
2490
  remediation: null,
2278
2491
  }]
2279
2492
  : []),
2493
+ ...(sandboxResumePatch === "fixed"
2494
+ ? [{
2495
+ id: "EVE_SANDBOX_RESUME_PATCH",
2496
+ status: "pass",
2497
+ subject: "eve-sandbox-resume",
2498
+ reason: `not needed: Eve ${EVE_SANDBOX_RESUME_FIXED_VERSION} and later include the fix for eve#4440`,
2499
+ remediation: null,
2500
+ }]
2501
+ : []),
2280
2502
  ],
2281
2503
  sandboxResumePatch,
2282
2504
  candidateImageId: buildResult.imageId ?? null,
@@ -196,11 +196,18 @@ function parseEnvironmentText(text) {
196
196
  }
197
197
  return Object.freeze(values);
198
198
  }
199
+ /**
200
+ * Values shorter than this are not masked: substring masking of `1`, `8`, or
201
+ * `eve` garbled every message and matched Eden's own random revision IDs,
202
+ * failing deploys. Credentials are longer; short values are still delivered
203
+ * only through the protected channels, just not masked if a tool echoes them.
204
+ */
205
+ const MIN_REDACTED_RUNTIME_VALUE_LENGTH = 8;
199
206
  class EveRuntimeRedactionRegistry {
200
207
  handle = `eve-runtime-redaction-${randomUUID()}`;
201
208
  values = new Set();
202
209
  register(value) {
203
- if (value.length > 0)
210
+ if (value.length >= MIN_REDACTED_RUNTIME_VALUE_LENGTH)
204
211
  this.values.add(value);
205
212
  }
206
213
  redact(value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moinulmoin/eden",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Deploy existing Eve projects to your own Cloudflare account.",
5
5
  "keywords": [
6
6
  "ai",
@@ -31,7 +31,7 @@
31
31
  "NOTICE"
32
32
  ],
33
33
  "dependencies": {
34
- "@moinulmoin/eden-runtime-cloudflare": "0.8.0",
34
+ "@moinulmoin/eden-runtime-cloudflare": "0.9.0",
35
35
  "wrangler": "4.147.0"
36
36
  },
37
37
  "devDependencies": {