@moinulmoin/eden 0.6.0 → 0.7.1
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 +13 -9
- package/dist/eve-control-plane.js +39 -57
- package/dist/eve-packaging.d.ts +86 -12
- package/dist/eve-packaging.js +358 -60
- package/dist/eve-runtime-config.d.ts +7 -2
- package/dist/eve-runtime-config.js +7 -2
- package/dist/eve-runtime-image.d.ts +12 -9
- package/dist/eve-runtime-image.js +140 -62
- package/dist/eve.d.ts +1 -2
- package/dist/eve.js +1 -18
- package/dist/index.d.ts +4 -7
- package/dist/index.js +2 -10
- package/package.json +2 -2
package/dist/eve-packaging.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { createHash, } from "node:crypto";
|
|
2
2
|
import { execFile, } from "node:child_process";
|
|
3
|
-
import { chmod, lstat, mkdir, readFile, readlink, readdir, realpath, writeFile, } from "node:fs/promises";
|
|
3
|
+
import { chmod, lstat, mkdir, readFile, readlink, readdir, realpath, rm, writeFile, } from "node:fs/promises";
|
|
4
4
|
import { promisify, } from "node:util";
|
|
5
|
+
import { EVE_HOST_ENVIRONMENT as HOST_ENVIRONMENT, EVE_START_COMMAND as START_COMMAND, } from "./eve-runtime-config.js";
|
|
5
6
|
import { basename, dirname, isAbsolute, join, relative, resolve, } from "node:path";
|
|
6
7
|
const execFileAsync = promisify(execFile);
|
|
8
|
+
/** Snapshot-relative root of Eve's prepared sandbox templates. */
|
|
9
|
+
export const EVE_SANDBOX_CACHE_ROOT = ".eve/sandbox-cache";
|
|
7
10
|
export class EvePackagingError extends Error {
|
|
8
11
|
code;
|
|
9
12
|
subject;
|
|
@@ -27,6 +30,137 @@ export class EvePackagingError extends Error {
|
|
|
27
30
|
// exempt from the ldd check, and the runtime stage sets
|
|
28
31
|
// CBOR_NATIVE_ACCELERATION_DISABLED.
|
|
29
32
|
const IGNORED_BUILDS_GUARD = `node -e 'const m=JSON.parse(require("fs").readFileSync("node_modules/.modules.yaml","utf8"));const b=(m.ignoredBuilds||[]).filter((p)=>!p.startsWith("cbor-extract@"));if(b.length){console.error("ERR_PNPM_IGNORED_BUILDS Ignored build scripts: "+b.join(", "));process.exit(1)}'`;
|
|
33
|
+
/**
|
|
34
|
+
* Eden's temporary fix for upstream https://github.com/vercel/eve/issues/4440
|
|
35
|
+
* (repro: https://github.com/moinulmoin/eve-justbash-resume-repro).
|
|
36
|
+
* Eve's just-bash provider permanently refuses to resume a conversation once
|
|
37
|
+
* the sandbox template changes (skills, `agent/sandbox/workspace/`, or the
|
|
38
|
+
* sandbox definition) and never falls back, so one `eden deploy` update would
|
|
39
|
+
* break every existing conversation's sandbox forever. The isolated builder
|
|
40
|
+
* rewrites one file in the installed Eve copy so an existing session reopens
|
|
41
|
+
* against the current template instead of throwing; user files under
|
|
42
|
+
* `/workspace` always win over the template. The patch applies only when the
|
|
43
|
+
* target file's sha256 matches a known binding and selects that binding's
|
|
44
|
+
* replacement; it is removed entirely once upstream ships the fix.
|
|
45
|
+
*/
|
|
46
|
+
export const EVE_SANDBOX_RESUME_PATCH_KNOWN_SHA256 = "0ba0ac3a237c99af2f67a6028f1675bf7c04b22454b4ebfb4cd9d19e5bf5aaf8";
|
|
47
|
+
/** Eve 0.79.1 stores a template key instead of an absolute template path. */
|
|
48
|
+
export const EVE_SANDBOX_RESUME_PATCH_LATEST_SHA256 = "ab8b1ad7398af8f6fd2a1e91eb0d1ff8d2b9b9afe1836234f36ce0e896791c45";
|
|
49
|
+
/** Marker the patched binding always contains; proves the patch shipped. */
|
|
50
|
+
export const EVE_SANDBOX_RESUME_PATCH_SIGNATURE = "edenRefreshJustBashSessionSkills";
|
|
51
|
+
/** Path of the just-bash binding inside the resolved Eve package root. */
|
|
52
|
+
const EVE_JUST_BASH_BINDING_PATH = "dist/src/execution/sandbox/bindings/just-bash.js";
|
|
53
|
+
/** The exact `resume()` implementation in Eve 0.68.0, 0.71.2, 0.72.1, and 0.79.1. */
|
|
54
|
+
export 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)}`;
|
|
55
|
+
/**
|
|
56
|
+
* The replacement `resume()`: a session whose template generation moved is
|
|
57
|
+
* contained to the same sessions directory and reopened with its authored
|
|
58
|
+
* skills refreshed from the current template. A session folder that is gone
|
|
59
|
+
* (for example a deploy that could not carry it) is recreated from the
|
|
60
|
+
* current template instead of failing every later sandbox call.
|
|
61
|
+
*/
|
|
62
|
+
export const EVE_SANDBOX_RESUME_PATCHED = `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)&&dirname(a.rootPath)!==dirname(s))throw Error(\`just-bash session state is incompatible with this environment.\`);await ensureSessionRoot(i,a.rootPath);if(a.generation!==o)await edenRefreshJustBashSessionSkills(i.templateRootPath,a.rootPath);return await openHandle(e,a.rootPath,t)}`;
|
|
63
|
+
/**
|
|
64
|
+
* Eve 0.79.1 resolves the current template key under the runtime cache.
|
|
65
|
+
* Its ensureSessionRoot accepts that path, not the prepared artifact.
|
|
66
|
+
*/
|
|
67
|
+
export const EVE_SANDBOX_RESUME_PATCHED_LATEST = `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)&&dirname(a.rootPath)!==dirname(s))throw Error(\`just-bash session state is incompatible with this environment.\`);let c=resolveTemplateRootPath(e.storagePath,i.templateKey);await ensureSessionRoot(c,a.rootPath);if(a.generation!==o)await edenRefreshJustBashSessionSkills(c,a.rootPath);return await openHandle(e,a.rootPath,t)}`;
|
|
68
|
+
/**
|
|
69
|
+
* Helpers appended to the patched binding. They use only identifiers the
|
|
70
|
+
* module already imports (`readdir`, `rm`, `join`, `pathExists`,
|
|
71
|
+
* `copyDirectoryAtomically`). Skills live at `$HOME/.agents/skills` inside a
|
|
72
|
+
* just-bash root, so the session keeps the same path relative to its `fs`
|
|
73
|
+
* directory as the template; the template's `fs` is scanned because `$HOME`
|
|
74
|
+
* is only known inside the sandbox.
|
|
75
|
+
*/
|
|
76
|
+
export const EVE_SANDBOX_RESUME_PATCH_HELPERS = `async function edenRefreshJustBashSessionSkills(e,t){let n=await edenFindTemplateSkillsRelativePath(join(e,"fs"));if(n===void 0)return;let r=join(t,"fs",n);await rm(r,{force:!0,recursive:!0}),await copyDirectoryAtomically(join(e,"fs",n),r)}
|
|
77
|
+
async function edenFindTemplateSkillsRelativePath(e){let t=[["",0]];for(;t.length>0;){let n=t.shift(),r=n[0],i=n[1];if(i>3)continue;let a=[];try{a=await readdir(join(e,r),{withFileTypes:!0})}catch{a=[]}for(let o of a){if(!o.isDirectory())continue;let s=r===""?o.name:r+"/"+o.name;if(o.name===".agents")return await pathExists(join(e,s,"skills"))?s+"/skills":void 0;t.push([s,i+1])}}return void 0}
|
|
78
|
+
`;
|
|
79
|
+
/**
|
|
80
|
+
* The CommonJS patcher the isolated builder runs between the frozen install
|
|
81
|
+
* and `eve build` (and again for the production reinstall). It never touches
|
|
82
|
+
* project files, applies only against known sha256 hashes, verifies the
|
|
83
|
+
* replacement matched exactly once, validates the result with `node --check`,
|
|
84
|
+
* and breaks hardlinks by writing a temp file and renaming it into place.
|
|
85
|
+
*/
|
|
86
|
+
export const EVE_SANDBOX_RESUME_PATCH_SCRIPT = `// Eden temporary fix for https://github.com/vercel/eve/issues/4440: Eve's
|
|
87
|
+
// just-bash provider permanently refuses to resume a conversation after the
|
|
88
|
+
// sandbox template changes (skills, agent/sandbox/workspace/, sandbox
|
|
89
|
+
// definition) and never falls back. This rewrites one file in the installed
|
|
90
|
+
// Eve copy so an existing session reopens against the current template. It
|
|
91
|
+
// runs only against sha256 hashes Eden knows, with a replacement specific to
|
|
92
|
+
// each binding, and is removed once upstream ships the fix.
|
|
93
|
+
const fs = require("node:fs");
|
|
94
|
+
const path = require("node:path");
|
|
95
|
+
const crypto = require("node:crypto");
|
|
96
|
+
const { spawnSync } = require("node:child_process");
|
|
97
|
+
const KNOWN_PATCHES = ${JSON.stringify({
|
|
98
|
+
[EVE_SANDBOX_RESUME_PATCH_KNOWN_SHA256]: {
|
|
99
|
+
original: EVE_JUST_BASH_RESUME_ORIGINAL,
|
|
100
|
+
replacement: EVE_SANDBOX_RESUME_PATCHED,
|
|
101
|
+
},
|
|
102
|
+
[EVE_SANDBOX_RESUME_PATCH_LATEST_SHA256]: {
|
|
103
|
+
original: EVE_JUST_BASH_RESUME_ORIGINAL,
|
|
104
|
+
replacement: EVE_SANDBOX_RESUME_PATCHED_LATEST,
|
|
105
|
+
},
|
|
106
|
+
})};
|
|
107
|
+
const SIGNATURE = ${JSON.stringify(EVE_SANDBOX_RESUME_PATCH_SIGNATURE)};
|
|
108
|
+
const BINDING_PATH = ${JSON.stringify(EVE_JUST_BASH_BINDING_PATH)};
|
|
109
|
+
const HELPERS = ${JSON.stringify(EVE_SANDBOX_RESUME_PATCH_HELPERS)};
|
|
110
|
+
function finish(outcome, detail) {
|
|
111
|
+
console.log("eden-eve-sandbox-resume-patch: " + outcome + " (" + detail + ")");
|
|
112
|
+
}
|
|
113
|
+
let packageJsonPath;
|
|
114
|
+
try {
|
|
115
|
+
packageJsonPath = fs.realpathSync("node_modules/eve/package.json");
|
|
116
|
+
} catch {
|
|
117
|
+
finish("absent", "no project-local eve package to patch");
|
|
118
|
+
process.exit(0);
|
|
119
|
+
}
|
|
120
|
+
const binding = path.join(path.dirname(packageJsonPath), BINDING_PATH);
|
|
121
|
+
let source;
|
|
122
|
+
try {
|
|
123
|
+
source = fs.readFileSync(binding, "utf8");
|
|
124
|
+
} catch {
|
|
125
|
+
finish("absent", "this eve build has no just-bash binding");
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
if (source.includes(SIGNATURE)) {
|
|
129
|
+
finish("applied", "already patched");
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
const digest = crypto.createHash("sha256").update(source).digest("hex");
|
|
133
|
+
const patch = KNOWN_PATCHES[digest];
|
|
134
|
+
if (patch === undefined) {
|
|
135
|
+
finish("skipped", "sha256 " + digest + " is not a version Eden knows (eve#4440)");
|
|
136
|
+
process.exit(0);
|
|
137
|
+
}
|
|
138
|
+
const { original: ORIGINAL, replacement: PATCHED_RESUME } = patch;
|
|
139
|
+
const first = source.indexOf(ORIGINAL);
|
|
140
|
+
if (first === -1 || source.indexOf(ORIGINAL, first + 1) !== -1) {
|
|
141
|
+
console.error("eden-eve-sandbox-resume-patch: the known resume implementation did not match exactly once; refusing to patch");
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
const patched = source.slice(0, first) + PATCHED_RESUME +
|
|
145
|
+
source.slice(first + ORIGINAL.length) + "\\n" + HELPERS + "\\n";
|
|
146
|
+
const temporary = binding + ".tmp.js";
|
|
147
|
+
fs.rmSync(temporary, { force: true });
|
|
148
|
+
fs.writeFileSync(temporary, patched);
|
|
149
|
+
const parsed = spawnSync(process.execPath, ["--check", temporary], { encoding: "utf8" });
|
|
150
|
+
if (parsed.status !== 0) {
|
|
151
|
+
fs.rmSync(temporary, { force: true });
|
|
152
|
+
console.error("eden-eve-sandbox-resume-patch: the patched file failed node --check; refusing to install it" + (typeof parsed.stderr === "string" ? "\\n" + parsed.stderr : ""));
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
// Rename (not write) so any hardlink to the original inode is broken.
|
|
156
|
+
fs.renameSync(temporary, binding);
|
|
157
|
+
finish("applied", "temporary eve#4440 fix written into the isolated builder image");
|
|
158
|
+
`;
|
|
159
|
+
/** The heredoc COPY + RUN inserted after each frozen install in the builder. */
|
|
160
|
+
const EVE_SANDBOX_RESUME_PATCH_DOCKERFILE_STEP = `COPY <<'EDEN_EVE_PATCH_EOF' /tmp/eden-eve-sandbox-resume-patch.cjs
|
|
161
|
+
${EVE_SANDBOX_RESUME_PATCH_SCRIPT}EDEN_EVE_PATCH_EOF
|
|
162
|
+
RUN node /tmp/eden-eve-sandbox-resume-patch.cjs
|
|
163
|
+
`;
|
|
30
164
|
const INSTALL_COMMAND = [
|
|
31
165
|
"corepack",
|
|
32
166
|
"pnpm",
|
|
@@ -34,14 +168,6 @@ const INSTALL_COMMAND = [
|
|
|
34
168
|
"--frozen-lockfile",
|
|
35
169
|
];
|
|
36
170
|
const BUILD_COMMAND = ["./node_modules/.bin/eve", "build"];
|
|
37
|
-
const START_COMMAND = [
|
|
38
|
-
"./node_modules/.bin/eve",
|
|
39
|
-
"start",
|
|
40
|
-
"--host",
|
|
41
|
-
"0.0.0.0",
|
|
42
|
-
"--port",
|
|
43
|
-
"8080",
|
|
44
|
-
];
|
|
45
171
|
const EVE_ENTRYPOINT = ".output/server/index.mjs";
|
|
46
172
|
const EVE_EXCLUDED_DIRECTORY_NAMES = new Set([
|
|
47
173
|
".eden",
|
|
@@ -78,27 +204,45 @@ const EVE_COMPETING_LOCKFILES = new Set([
|
|
|
78
204
|
"package-lock.json",
|
|
79
205
|
"yarn.lock",
|
|
80
206
|
]);
|
|
81
|
-
|
|
82
|
-
HOST: "0.0.0.0",
|
|
83
|
-
NITRO_HOST: "0.0.0.0",
|
|
84
|
-
PORT: "8080",
|
|
85
|
-
NITRO_PORT: "8080",
|
|
86
|
-
NODE_ENV: "production",
|
|
87
|
-
};
|
|
88
|
-
function sha256(value) {
|
|
207
|
+
export function sha256(value) {
|
|
89
208
|
return createHash("sha256").update(value).digest("hex");
|
|
90
209
|
}
|
|
91
|
-
function jsonBytes(value) {
|
|
210
|
+
export function jsonBytes(value) {
|
|
92
211
|
return Buffer.from(`${JSON.stringify(value)}\n`, "utf8");
|
|
93
212
|
}
|
|
94
|
-
function isWithin(root, candidate) {
|
|
213
|
+
export function isWithin(root, candidate) {
|
|
95
214
|
const normalizedRoot = root.endsWith("/") ? root.slice(0, -1) : root;
|
|
96
215
|
return candidate === normalizedRoot ||
|
|
97
216
|
candidate.startsWith(`${normalizedRoot}/`);
|
|
98
217
|
}
|
|
99
|
-
function safeRelativePath(root, candidate) {
|
|
218
|
+
export function safeRelativePath(root, candidate) {
|
|
100
219
|
return relative(root, candidate).split("\\").join("/");
|
|
101
220
|
}
|
|
221
|
+
export const IMAGE_ID_PATTERN = /^sha256:[0-9a-f]{64}$/u;
|
|
222
|
+
const NODE_IMAGE_PATTERN = /^node:24\.17\.0(?:-[a-z0-9][a-z0-9._-]*)?$/u;
|
|
223
|
+
export function imageReference(nodeImage, reason, remediation) {
|
|
224
|
+
if (!NODE_IMAGE_PATTERN.test(nodeImage.reference) ||
|
|
225
|
+
!IMAGE_ID_PATTERN.test(nodeImage.digest)) {
|
|
226
|
+
throw new EvePackagingError({
|
|
227
|
+
code: "DOCKER_PLATFORM_BLOCKED",
|
|
228
|
+
subject: "node-24-image",
|
|
229
|
+
reason,
|
|
230
|
+
remediation,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
return `${nodeImage.reference}@${nodeImage.digest}`;
|
|
234
|
+
}
|
|
235
|
+
function safeDockerEnvironment() {
|
|
236
|
+
return {
|
|
237
|
+
PATH: process.env.PATH,
|
|
238
|
+
HOME: process.env.HOME,
|
|
239
|
+
TMPDIR: process.env.TMPDIR,
|
|
240
|
+
LANG: process.env.LANG,
|
|
241
|
+
LC_ALL: process.env.LC_ALL,
|
|
242
|
+
DOCKER_HOST: process.env.DOCKER_HOST,
|
|
243
|
+
DOCKER_CONTEXT: process.env.DOCKER_CONTEXT,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
102
246
|
function isAllowedSystemAlias(path) {
|
|
103
247
|
const normalized = resolve(path);
|
|
104
248
|
return normalized === "/var" || normalized === "/tmp";
|
|
@@ -770,6 +914,10 @@ async function verifySnapshotInputs(snapshotRoot, inputs) {
|
|
|
770
914
|
if (firstSegment !== undefined && generatedRoots.has(firstSegment)) {
|
|
771
915
|
continue;
|
|
772
916
|
}
|
|
917
|
+
if (relativePath === EVE_SANDBOX_CACHE_ROOT ||
|
|
918
|
+
relativePath.startsWith(`${EVE_SANDBOX_CACHE_ROOT}/`)) {
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
773
921
|
const candidate = join(directory, entry.name);
|
|
774
922
|
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
775
923
|
if (!entry.isFile() || entry.isSymbolicLink()) {
|
|
@@ -928,16 +1076,7 @@ export async function eveSnapshotSourceEntries(snapshotRoot) {
|
|
|
928
1076
|
return names;
|
|
929
1077
|
}
|
|
930
1078
|
async function writeDockerBuildFiles(options) {
|
|
931
|
-
|
|
932
|
-
!/^node:24\.17\.0(?:-[a-z0-9][a-z0-9._-]*)?$/u.test(options.nodeImage.reference)) {
|
|
933
|
-
throw new EvePackagingError({
|
|
934
|
-
code: "DOCKER_PLATFORM_BLOCKED",
|
|
935
|
-
subject: "node-24-image",
|
|
936
|
-
reason: "The Linux/amd64 builder requires an immutable Node 24 image digest.",
|
|
937
|
-
remediation: "Supply a verified Node 24 image reference and sha256 digest.",
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
const image = `${options.nodeImage.reference}@${options.nodeImage.digest}`;
|
|
1079
|
+
const image = imageReference(options.nodeImage, "The Linux/amd64 builder requires an immutable Node 24 image digest.", "Supply a verified Node 24 image reference and sha256 digest.");
|
|
941
1080
|
const installSources = ["package.json", "pnpm-lock.yaml"];
|
|
942
1081
|
if ((await lstat(join(options.snapshotRoot, "pnpm-workspace.yaml"))
|
|
943
1082
|
.catch(() => undefined))?.isFile() === true) {
|
|
@@ -956,16 +1095,18 @@ RUN corepack enable \\
|
|
|
956
1095
|
&& test "$(sha256sum pnpm-lock.yaml | cut -d ' ' -f1)" = "${options.lockfileSha256}" \\
|
|
957
1096
|
&& corepack pnpm install --frozen-lockfile --config.node-linker=hoisted --config.strict-dep-builds=false \\
|
|
958
1097
|
&& ${IGNORED_BUILDS_GUARD}
|
|
959
|
-
RUN test "$(sha256sum pnpm-lock.yaml | cut -d ' ' -f1)" = "${options.lockfileSha256}"
|
|
1098
|
+
${EVE_SANDBOX_RESUME_PATCH_DOCKERFILE_STEP}RUN test "$(sha256sum pnpm-lock.yaml | cut -d ' ' -f1)" = "${options.lockfileSha256}"
|
|
960
1099
|
COPY . ./
|
|
961
1100
|
RUN test -x ./node_modules/.bin/eve \\
|
|
962
|
-
&& ./node_modules/.bin/eve build
|
|
1101
|
+
&& ./node_modules/.bin/eve build \\
|
|
1102
|
+
&& mkdir -p .eve/sandbox-cache
|
|
963
1103
|
|
|
964
1104
|
FROM builder AS runtime-deps
|
|
965
1105
|
RUN rm -rf node_modules \\
|
|
966
1106
|
&& corepack pnpm install --frozen-lockfile --prod --config.node-linker=hoisted --config.strict-dep-builds=false \\
|
|
967
1107
|
&& ${IGNORED_BUILDS_GUARD} \\
|
|
968
1108
|
&& for l in node_modules/.bin/*; do t=$(readlink "$l") || continue; case "$t" in /*) ln -sfn "$(realpath --relative-to=node_modules/.bin "$t")" "$l" ;; esac; done
|
|
1109
|
+
${EVE_SANDBOX_RESUME_PATCH_DOCKERFILE_STEP}
|
|
969
1110
|
|
|
970
1111
|
FROM --platform=linux/amd64 ${image} AS runtime
|
|
971
1112
|
WORKDIR /app
|
|
@@ -975,6 +1116,12 @@ ENV HOST=0.0.0.0 \\
|
|
|
975
1116
|
NITRO_PORT=8080 \\
|
|
976
1117
|
NODE_ENV=production
|
|
977
1118
|
COPY --from=builder /workspace/.output /app/.output
|
|
1119
|
+
# Eve's prepared just-bash sandbox template: the builder stage's eve build
|
|
1120
|
+
# prewarm wrote it under /workspace/.eve/sandbox-cache, and the runtime sandbox
|
|
1121
|
+
# resolves it at /app/.eve/sandbox-cache (bash/read_file/write_file fail
|
|
1122
|
+
# without it). The mkdir in the build step guarantees the source exists even
|
|
1123
|
+
# when this Eve build prepared no template.
|
|
1124
|
+
COPY --from=builder /workspace/.eve/sandbox-cache /app/.eve/sandbox-cache
|
|
978
1125
|
${runtimeSourceCopies}
|
|
979
1126
|
COPY --from=runtime-deps /workspace/node_modules /app/node_modules
|
|
980
1127
|
EXPOSE 8080
|
|
@@ -1221,10 +1368,123 @@ async function scanGeneratedOutput(snapshotRoot) {
|
|
|
1221
1368
|
fileCount: files.length,
|
|
1222
1369
|
};
|
|
1223
1370
|
}
|
|
1371
|
+
/**
|
|
1372
|
+
* A generous sanity bound for the prepared sandbox-template tree (templates
|
|
1373
|
+
* carry the sandbox filesystem seeds and authored skills; the minimal Eve
|
|
1374
|
+
* fixture produces ~1 KiB). Anything larger means the builder extracted more
|
|
1375
|
+
* than Eve's build-time prewarm could have written.
|
|
1376
|
+
*/
|
|
1377
|
+
const EVE_SANDBOX_CACHE_MAX_BYTES = 64 * 1024 * 1024;
|
|
1378
|
+
/**
|
|
1379
|
+
* Validates the prepared sandbox-template tree the builder extracted into
|
|
1380
|
+
* `<snapshot>/.eve/sandbox-cache` with the same rigor as `.output`: regular
|
|
1381
|
+
* files and directories only, no symbolic links, no special files, stable
|
|
1382
|
+
* reads inside the immutable snapshot, and a total-size sanity bound.
|
|
1383
|
+
* Returns `null` when this Eve build prepared no sandbox template.
|
|
1384
|
+
*/
|
|
1385
|
+
async function scanGeneratedSandboxCache(snapshotRoot) {
|
|
1386
|
+
const cacheRoot = join(snapshotRoot, EVE_SANDBOX_CACHE_ROOT);
|
|
1387
|
+
const rootDetails = await lstat(cacheRoot).catch(() => undefined);
|
|
1388
|
+
if (rootDetails === undefined)
|
|
1389
|
+
return null;
|
|
1390
|
+
const rootCanonical = await realpath(cacheRoot).catch(() => undefined);
|
|
1391
|
+
if (!rootDetails.isDirectory() ||
|
|
1392
|
+
rootDetails.isSymbolicLink() ||
|
|
1393
|
+
rootCanonical === undefined ||
|
|
1394
|
+
!isWithin(snapshotRoot, resolve(rootCanonical))) {
|
|
1395
|
+
throw new EvePackagingError({
|
|
1396
|
+
code: "UNSUPPORTED_EVE_OUTPUT",
|
|
1397
|
+
subject: EVE_SANDBOX_CACHE_ROOT,
|
|
1398
|
+
reason: "The prepared sandbox template root is missing, a symbolic link, or escapes the immutable snapshot.",
|
|
1399
|
+
remediation: "Rebuild the candidate so the isolated builder extracts a regular .eve/sandbox-cache directory.",
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
const files = [];
|
|
1403
|
+
let totalBytes = 0;
|
|
1404
|
+
const visit = async (directory, relativeDirectory) => {
|
|
1405
|
+
const directoryDetails = await lstat(directory).catch(() => undefined);
|
|
1406
|
+
const directoryCanonical = await realpath(directory).catch(() => undefined);
|
|
1407
|
+
if (directoryDetails === undefined ||
|
|
1408
|
+
!directoryDetails.isDirectory() ||
|
|
1409
|
+
directoryDetails.isSymbolicLink() ||
|
|
1410
|
+
directoryCanonical === undefined ||
|
|
1411
|
+
!isWithin(snapshotRoot, resolve(directoryCanonical))) {
|
|
1412
|
+
throw new EvePackagingError({
|
|
1413
|
+
code: "UNSUPPORTED_EVE_OUTPUT",
|
|
1414
|
+
subject: relativeDirectory,
|
|
1415
|
+
reason: "The prepared sandbox template tree escaped or changed during validation.",
|
|
1416
|
+
remediation: "Rebuild the candidate so the isolated builder extracts regular template files.",
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
1420
|
+
entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
1421
|
+
for (const entry of entries) {
|
|
1422
|
+
const relativePath = relativeDirectory.length === 0
|
|
1423
|
+
? entry.name
|
|
1424
|
+
: `${relativeDirectory}/${entry.name}`;
|
|
1425
|
+
const candidate = join(directory, entry.name);
|
|
1426
|
+
if (entry.isSymbolicLink()) {
|
|
1427
|
+
throw new EvePackagingError({
|
|
1428
|
+
code: "UNSUPPORTED_EVE_OUTPUT",
|
|
1429
|
+
subject: `${EVE_SANDBOX_CACHE_ROOT}/${relativePath}`,
|
|
1430
|
+
reason: "The prepared sandbox template tree contains a symbolic link.",
|
|
1431
|
+
remediation: "Rebuild the candidate so the isolated builder extracts regular template files only.",
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
if (entry.isDirectory()) {
|
|
1435
|
+
await visit(candidate, relativePath);
|
|
1436
|
+
continue;
|
|
1437
|
+
}
|
|
1438
|
+
if (!entry.isFile()) {
|
|
1439
|
+
throw new EvePackagingError({
|
|
1440
|
+
code: "UNSUPPORTED_EVE_OUTPUT",
|
|
1441
|
+
subject: `${EVE_SANDBOX_CACHE_ROOT}/${relativePath}`,
|
|
1442
|
+
reason: "The prepared sandbox template tree contains a device, socket, FIFO, or other unsupported file.",
|
|
1443
|
+
remediation: "Rebuild the candidate so the isolated builder extracts regular template files only.",
|
|
1444
|
+
});
|
|
1445
|
+
}
|
|
1446
|
+
let stable;
|
|
1447
|
+
try {
|
|
1448
|
+
stable = await readStableFile(candidate, snapshotRoot);
|
|
1449
|
+
}
|
|
1450
|
+
catch {
|
|
1451
|
+
throw new EvePackagingError({
|
|
1452
|
+
code: "UNSUPPORTED_EVE_OUTPUT",
|
|
1453
|
+
subject: `${EVE_SANDBOX_CACHE_ROOT}/${relativePath}`,
|
|
1454
|
+
reason: "The prepared sandbox template file is unreadable or changed during validation.",
|
|
1455
|
+
remediation: "Rebuild the candidate so the isolated builder extracts a stable template tree.",
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
totalBytes += stable.bytes.byteLength;
|
|
1459
|
+
if (totalBytes > EVE_SANDBOX_CACHE_MAX_BYTES) {
|
|
1460
|
+
throw new EvePackagingError({
|
|
1461
|
+
code: "UNSUPPORTED_EVE_OUTPUT",
|
|
1462
|
+
subject: EVE_SANDBOX_CACHE_ROOT,
|
|
1463
|
+
reason: `The prepared sandbox template tree exceeds the ${EVE_SANDBOX_CACHE_MAX_BYTES}-byte sanity bound.`,
|
|
1464
|
+
remediation: "Rebuild the candidate; the extracted template tree must contain only Eve's prepared templates.",
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
files.push({
|
|
1468
|
+
relativePath: `${EVE_SANDBOX_CACHE_ROOT}/${relativePath}`,
|
|
1469
|
+
sha256: stable.sha256,
|
|
1470
|
+
byteLength: stable.bytes.byteLength,
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
await visit(cacheRoot, "");
|
|
1475
|
+
return {
|
|
1476
|
+
present: true,
|
|
1477
|
+
root: EVE_SANDBOX_CACHE_ROOT,
|
|
1478
|
+
outputDigest: sha256(jsonBytes(files)),
|
|
1479
|
+
fileCount: files.length,
|
|
1480
|
+
totalBytes,
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1224
1483
|
async function assertGeneratedTreesExcludeSecrets(snapshotRoot) {
|
|
1225
1484
|
const roots = [
|
|
1226
1485
|
join(snapshotRoot, "node_modules"),
|
|
1227
1486
|
join(snapshotRoot, ".output"),
|
|
1487
|
+
join(snapshotRoot, EVE_SANDBOX_CACHE_ROOT),
|
|
1228
1488
|
];
|
|
1229
1489
|
const visit = async (directory, relativeDirectory) => {
|
|
1230
1490
|
const directoryDetails = await lstat(directory).catch(() => undefined);
|
|
@@ -1301,7 +1561,7 @@ async function assertGeneratedTreesExcludeSecrets(snapshotRoot) {
|
|
|
1301
1561
|
}
|
|
1302
1562
|
}
|
|
1303
1563
|
}
|
|
1304
|
-
function safeError(error) {
|
|
1564
|
+
export function safeError(error) {
|
|
1305
1565
|
return {
|
|
1306
1566
|
code: error.code,
|
|
1307
1567
|
subject: error.subject,
|
|
@@ -1447,12 +1707,11 @@ function blockedResult(error, extra = {}) {
|
|
|
1447
1707
|
status: "blocked",
|
|
1448
1708
|
returnCode: error.code,
|
|
1449
1709
|
deployable: false,
|
|
1450
|
-
project:
|
|
1710
|
+
project: null,
|
|
1451
1711
|
candidate: null,
|
|
1452
1712
|
snapshot: null,
|
|
1453
1713
|
toolchain: null,
|
|
1454
1714
|
image: null,
|
|
1455
|
-
runtime: null,
|
|
1456
1715
|
secrets: {
|
|
1457
1716
|
runtimeVariableNames: [],
|
|
1458
1717
|
valuesRecorded: false,
|
|
@@ -1464,19 +1723,39 @@ function blockedResult(error, extra = {}) {
|
|
|
1464
1723
|
excludedFromManifestsAndLogs: true,
|
|
1465
1724
|
redactionRegisteredBeforeChildren: false,
|
|
1466
1725
|
},
|
|
1467
|
-
checks:
|
|
1726
|
+
checks: [{
|
|
1468
1727
|
id: error.code,
|
|
1469
1728
|
status: "blocked",
|
|
1470
1729
|
subject: error.subject,
|
|
1471
1730
|
reason: error.message,
|
|
1472
1731
|
remediation: error.remediation,
|
|
1473
1732
|
}],
|
|
1733
|
+
sandboxResumePatch: "absent",
|
|
1474
1734
|
candidateImageId: null,
|
|
1475
1735
|
candidateImageRetainedLocally: false,
|
|
1476
1736
|
writtenPaths: extra.writtenPaths ?? [],
|
|
1477
1737
|
error: safeError(error),
|
|
1478
1738
|
};
|
|
1479
1739
|
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Decides the sandbox-resume patch outcome from the `node_modules` the
|
|
1742
|
+
* builder copied out of the finished image: the shipped just-bash binding is
|
|
1743
|
+
* the single source of truth and stays correct under Docker layer caching
|
|
1744
|
+
* (a cached patch step still ships the patched file). Reading never throws —
|
|
1745
|
+
* an unreadable tree counts as `absent`.
|
|
1746
|
+
*/
|
|
1747
|
+
async function detectEveSandboxResumePatch(snapshotRoot) {
|
|
1748
|
+
try {
|
|
1749
|
+
const packageJsonPath = await realpath(join(snapshotRoot, "node_modules/eve/package.json"));
|
|
1750
|
+
const binding = await readFile(join(dirname(packageJsonPath), EVE_JUST_BASH_BINDING_PATH), "utf8");
|
|
1751
|
+
return binding.includes(EVE_SANDBOX_RESUME_PATCH_SIGNATURE)
|
|
1752
|
+
? "applied"
|
|
1753
|
+
: "skipped";
|
|
1754
|
+
}
|
|
1755
|
+
catch {
|
|
1756
|
+
return "absent";
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1480
1759
|
async function currentInputIdentity(runtimeConfig) {
|
|
1481
1760
|
const token = (value) => {
|
|
1482
1761
|
if (typeof value === "string")
|
|
@@ -1743,7 +2022,9 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1743
2022
|
return blockedResult(cleanupError ?? dependencyError, { writtenPaths });
|
|
1744
2023
|
}
|
|
1745
2024
|
const eve = await resolveProjectLocalEve(snapshotRoot);
|
|
2025
|
+
const sandboxResumePatch = await detectEveSandboxResumePatch(snapshotRoot);
|
|
1746
2026
|
const output = await scanGeneratedOutput(snapshotRoot);
|
|
2027
|
+
const sandboxCache = await scanGeneratedSandboxCache(snapshotRoot);
|
|
1747
2028
|
await assertGeneratedTreesExcludeSecrets(snapshotRoot);
|
|
1748
2029
|
const snapshotSourceDigest = await snapshotDigest(snapshotRoot);
|
|
1749
2030
|
const runtimeManifestPath = join(generationRoot, "runtime-manifest.json");
|
|
@@ -1758,6 +2039,7 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1758
2039
|
sourceDigest: initialInputs.sourceDigest,
|
|
1759
2040
|
snapshotDigest: snapshotSourceDigest,
|
|
1760
2041
|
generatedOutput: output,
|
|
2042
|
+
sandboxCache,
|
|
1761
2043
|
artifactPath: EVE_ENTRYPOINT,
|
|
1762
2044
|
platform: "linux/amd64",
|
|
1763
2045
|
runtimeVariableNames,
|
|
@@ -1791,10 +2073,8 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1791
2073
|
excludedCategories: [...new Set(initialInputs.excludedRelativePaths.map((path) => isPathExcluded(path, undefined).category ?? "generated-state"))].sort(),
|
|
1792
2074
|
sourceRaceChecked: true,
|
|
1793
2075
|
};
|
|
1794
|
-
if (
|
|
1795
|
-
|
|
1796
|
-
(buildResult.imageId !== undefined &&
|
|
1797
|
-
buildResult.imagePlatform !== "linux/amd64")) {
|
|
2076
|
+
if (buildResult.imageId !== undefined &&
|
|
2077
|
+
!IMAGE_ID_PATTERN.test(buildResult.imageId)) {
|
|
1798
2078
|
const imageError = new EvePackagingError({
|
|
1799
2079
|
code: "DOCKER_PLATFORM_BLOCKED",
|
|
1800
2080
|
subject: "linux/amd64 image",
|
|
@@ -1835,6 +2115,7 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1835
2115
|
sourceDigest: initialInputs.sourceDigest,
|
|
1836
2116
|
snapshotDigest: snapshotSourceDigest,
|
|
1837
2117
|
generatedOutput: output,
|
|
2118
|
+
sandboxCache,
|
|
1838
2119
|
...(initialRuntimeInputIdentity === undefined
|
|
1839
2120
|
? {}
|
|
1840
2121
|
: { runtimeConfigInputIdentity: initialRuntimeInputIdentity }),
|
|
@@ -1868,7 +2149,6 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1868
2149
|
},
|
|
1869
2150
|
image,
|
|
1870
2151
|
candidate,
|
|
1871
|
-
runtime: null,
|
|
1872
2152
|
secrets: {
|
|
1873
2153
|
runtimeVariableNames,
|
|
1874
2154
|
valuesRecorded: false,
|
|
@@ -1916,7 +2196,17 @@ export async function buildEveProjectSnapshot(options) {
|
|
|
1916
2196
|
reason: "The resolved Eve executable is inside the isolated project dependency tree.",
|
|
1917
2197
|
remediation: null,
|
|
1918
2198
|
},
|
|
2199
|
+
...(sandboxResumePatch === "applied"
|
|
2200
|
+
? [{
|
|
2201
|
+
id: "EVE_SANDBOX_RESUME_PATCH",
|
|
2202
|
+
status: "pass",
|
|
2203
|
+
subject: "eve-sandbox-resume",
|
|
2204
|
+
reason: "applied temporary fix for eve#4440",
|
|
2205
|
+
remediation: null,
|
|
2206
|
+
}]
|
|
2207
|
+
: []),
|
|
1919
2208
|
],
|
|
2209
|
+
sandboxResumePatch,
|
|
1920
2210
|
candidateImageId: buildResult.imageId ?? null,
|
|
1921
2211
|
candidateImageRetainedLocally: buildResult.imageId !== undefined,
|
|
1922
2212
|
writtenPaths,
|
|
@@ -2049,15 +2339,7 @@ export function createDockerEveProjectBuilder(options) {
|
|
|
2049
2339
|
});
|
|
2050
2340
|
}
|
|
2051
2341
|
const imageIdFile = join(request.generationRoot, "image-id");
|
|
2052
|
-
const safeEnv =
|
|
2053
|
-
PATH: process.env.PATH,
|
|
2054
|
-
HOME: process.env.HOME,
|
|
2055
|
-
TMPDIR: process.env.TMPDIR,
|
|
2056
|
-
LANG: process.env.LANG,
|
|
2057
|
-
LC_ALL: process.env.LC_ALL,
|
|
2058
|
-
DOCKER_HOST: process.env.DOCKER_HOST,
|
|
2059
|
-
DOCKER_CONTEXT: process.env.DOCKER_CONTEXT,
|
|
2060
|
-
};
|
|
2342
|
+
const safeEnv = safeDockerEnvironment();
|
|
2061
2343
|
let containerId;
|
|
2062
2344
|
let imageBuilt = false;
|
|
2063
2345
|
let retainImage = false;
|
|
@@ -2100,7 +2382,7 @@ export function createDockerEveProjectBuilder(options) {
|
|
|
2100
2382
|
], { env: safeEnv, cwd: request.generationRoot, maxBuffer: 1024 * 1024 });
|
|
2101
2383
|
imageBuilt = true;
|
|
2102
2384
|
builtImageId = (await readFile(imageIdFile, "utf8")).trim();
|
|
2103
|
-
if (
|
|
2385
|
+
if (!IMAGE_ID_PATTERN.test(builtImageId)) {
|
|
2104
2386
|
throw new EvePackagingError({
|
|
2105
2387
|
code: "DOCKER_PLATFORM_BLOCKED",
|
|
2106
2388
|
subject: "image identity",
|
|
@@ -2139,6 +2421,30 @@ export function createDockerEveProjectBuilder(options) {
|
|
|
2139
2421
|
}
|
|
2140
2422
|
await execFileAsync(dockerCommand, ["cp", `${containerId}:/app/.output`, join(request.snapshotRoot, ".output")], { env: safeEnv, cwd: request.generationRoot });
|
|
2141
2423
|
await execFileAsync(dockerCommand, ["cp", `${containerId}:/app/node_modules`, join(request.snapshotRoot, "node_modules")], { env: safeEnv, cwd: request.generationRoot });
|
|
2424
|
+
// The builder stage's `eve build` prewarm writes the just-bash sandbox
|
|
2425
|
+
// template under its workdir; the runtime stage copies it to
|
|
2426
|
+
// /app/.eve/sandbox-cache (the mkdir in the Dockerfile guarantees the
|
|
2427
|
+
// path exists). Extract exactly that subtree so runtime sandboxes can
|
|
2428
|
+
// resolve their template; never the rest of `.eve` (sessions, locks,
|
|
2429
|
+
// builds). Treated as absent when the container has no such path.
|
|
2430
|
+
const sandboxCacheTarget = join(request.snapshotRoot, EVE_SANDBOX_CACHE_ROOT);
|
|
2431
|
+
await ensureSnapshotDirectory(request.snapshotRoot, dirname(sandboxCacheTarget));
|
|
2432
|
+
try {
|
|
2433
|
+
await execFileAsync(dockerCommand, ["cp", `${containerId}:/app/${EVE_SANDBOX_CACHE_ROOT}`, sandboxCacheTarget], { env: safeEnv, cwd: request.generationRoot });
|
|
2434
|
+
}
|
|
2435
|
+
catch (error) {
|
|
2436
|
+
const stderr = typeof error === "object" &&
|
|
2437
|
+
error !== null &&
|
|
2438
|
+
"stderr" in error &&
|
|
2439
|
+
typeof error.stderr === "string"
|
|
2440
|
+
? error.stderr
|
|
2441
|
+
: "";
|
|
2442
|
+
if (!/(?:could not find|no such|not found|does not exist)/iu.test(stderr)) {
|
|
2443
|
+
throw error;
|
|
2444
|
+
}
|
|
2445
|
+
// Absent: remove the `.eve` parent this extraction created.
|
|
2446
|
+
await rm(dirname(sandboxCacheTarget), { recursive: true, force: true }).catch(() => undefined);
|
|
2447
|
+
}
|
|
2142
2448
|
const result = {
|
|
2143
2449
|
imageId: builtImageId,
|
|
2144
2450
|
imagePlatform: "linux/amd64",
|
|
@@ -2174,15 +2480,7 @@ export function createDockerEveProjectBuilder(options) {
|
|
|
2174
2480
|
const imageReference = result.imageReference;
|
|
2175
2481
|
if (imageReference === undefined)
|
|
2176
2482
|
return;
|
|
2177
|
-
const safeEnv =
|
|
2178
|
-
PATH: process.env.PATH,
|
|
2179
|
-
HOME: process.env.HOME,
|
|
2180
|
-
TMPDIR: process.env.TMPDIR,
|
|
2181
|
-
LANG: process.env.LANG,
|
|
2182
|
-
LC_ALL: process.env.LC_ALL,
|
|
2183
|
-
DOCKER_HOST: process.env.DOCKER_HOST,
|
|
2184
|
-
DOCKER_CONTEXT: process.env.DOCKER_CONTEXT,
|
|
2185
|
-
};
|
|
2483
|
+
const safeEnv = safeDockerEnvironment();
|
|
2186
2484
|
await execFileAsync(dockerCommand, ["image", "rm", "--force", imageReference], { env: safeEnv });
|
|
2187
2485
|
const remainingImage = await execFileAsync(dockerCommand, ["image", "inspect", imageReference, "--format", "{{.Id}}"], { env: safeEnv }).catch(() => undefined);
|
|
2188
2486
|
if (remainingImage !== undefined && remainingImage.stdout.trim().length > 0) {
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
export declare const EVE_RESERVED_HOST_VARIABLES: readonly ["HOST", "NITRO_HOST", "PORT", "NITRO_PORT", "NODE_ENV", "NODE_EXTRA_CA_CERTS", "WORKFLOW_LOCAL_BASE_URL", "EDEN_WORLD_URL", "EDEN_EVE_DEPLOYMENT_ID", "EDEN_EVE_GENERATION_ID"];
|
|
2
2
|
export type EveReservedHostVariable = (typeof EVE_RESERVED_HOST_VARIABLES)[number];
|
|
3
3
|
export declare const EVE_START_COMMAND: readonly ["./node_modules/.bin/eve", "start", "--host", "0.0.0.0", "--port", "8080"];
|
|
4
|
+
export declare const EVE_HOST_ENVIRONMENT: Readonly<{
|
|
5
|
+
readonly HOST: "0.0.0.0";
|
|
6
|
+
readonly NITRO_HOST: "0.0.0.0";
|
|
7
|
+
readonly PORT: "8080";
|
|
8
|
+
readonly NITRO_PORT: "8080";
|
|
9
|
+
readonly NODE_ENV: "production";
|
|
10
|
+
}>;
|
|
4
11
|
type EveRuntimeValueMap = Readonly<Record<string, string>>;
|
|
5
12
|
export type EveRuntimeConfigErrorCode = "EVE_ENV_FILE_NOT_FOUND" | "EVE_ENV_FILE_INVALID" | "EVE_ENV_FILE_UNREADABLE" | "EVE_ENV_FILE_ENCODING" | "EVE_ENV_FILE_MALFORMED" | "EVE_ENV_FILE_DUPLICATE" | "EVE_ENV_RESERVED_VARIABLE" | "EVE_ENV_FILE_RACE" | "EVE_RUNTIME_INJECTION_INVALID" | "EVE_RUNTIME_PROTECTED_STORE_UNAVAILABLE" | "EVE_RUNTIME_PROTECTED_UPLOAD_FAILED" | "EVE_RUNTIME_LOCAL_INJECTION_UNSUPPORTED";
|
|
6
13
|
export declare class EveRuntimeConfigError extends Error {
|
|
@@ -119,8 +126,6 @@ export declare class EveRuntimeConfig {
|
|
|
119
126
|
export declare function readEveRuntimeConfig(inputPath: string, options?: {
|
|
120
127
|
readonly cwd?: string;
|
|
121
128
|
}): Promise<EveRuntimeConfig>;
|
|
122
|
-
export declare const parseEveRuntimeConfig: typeof readEveRuntimeConfig;
|
|
123
|
-
export declare const loadEveRuntimeConfig: typeof readEveRuntimeConfig;
|
|
124
129
|
export declare function prepareEveRuntimeInjection(config: EveRuntimeConfig, options: EveRuntimeInjectionOptions): Promise<EveRuntimeInjection>;
|
|
125
130
|
export {};
|
|
126
131
|
//# sourceMappingURL=eve-runtime-config.d.ts.map
|
|
@@ -21,6 +21,13 @@ export const EVE_START_COMMAND = Object.freeze([
|
|
|
21
21
|
"--port",
|
|
22
22
|
"8080",
|
|
23
23
|
]);
|
|
24
|
+
export const EVE_HOST_ENVIRONMENT = Object.freeze({
|
|
25
|
+
HOST: "0.0.0.0",
|
|
26
|
+
NITRO_HOST: "0.0.0.0",
|
|
27
|
+
PORT: "8080",
|
|
28
|
+
NITRO_PORT: "8080",
|
|
29
|
+
NODE_ENV: "production",
|
|
30
|
+
});
|
|
24
31
|
const EVE_ENVIRONMENT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
25
32
|
const EVE_RUNTIME_METADATA_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u;
|
|
26
33
|
const EVE_ENV_FILE_SOURCE = "--env-file";
|
|
@@ -323,8 +330,6 @@ export async function readEveRuntimeConfig(inputPath, options = {}) {
|
|
|
323
330
|
activeRedactionRegistries.add(redaction);
|
|
324
331
|
return EveRuntimeConfig.from(observation, values, redaction);
|
|
325
332
|
}
|
|
326
|
-
export const parseEveRuntimeConfig = readEveRuntimeConfig;
|
|
327
|
-
export const loadEveRuntimeConfig = readEveRuntimeConfig;
|
|
328
333
|
function validateProtectedPutResult(result) {
|
|
329
334
|
if (typeof result !== "object" ||
|
|
330
335
|
result === null ||
|