@jigging/jig 0.1.0-alpha.26 → 0.1.0-alpha.29
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/libexec/evaluator/project-evaluator-worker.js +423 -23
- package/libexec/installed-cli.js +604 -362
- package/libexec/linux-rootless-supervisor.js +54 -0
- package/libexec/macos-native-supervisor.js +3 -1
- package/libexec/markdown-runtime.js +3 -3
- package/libexec/preparation/bun-native-preparation-worker.js +40 -21
- package/package.json +1 -1
|
@@ -20,6 +20,7 @@ var POLICY = Object.freeze(["--no-env-file", "--no-install", "--config=/dev/null
|
|
|
20
20
|
var SANDBOX_BUN = "/jig-runtime/bun";
|
|
21
21
|
var SANDBOX_LIBRARY_PATH = "/jig-runtime/lib";
|
|
22
22
|
var MAX_CONTROL_BYTES = 64 * 1024;
|
|
23
|
+
var CORE_DUMP_POLL_MS = 250;
|
|
23
24
|
var MODULE_DESTINATION = "/jig/linux-rootless-supervisor.ts";
|
|
24
25
|
var DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
25
26
|
var OWNER_TOKEN = /^[0-9a-f]{64}$/;
|
|
@@ -112,6 +113,9 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
|
|
|
112
113
|
let exitSignal = null;
|
|
113
114
|
let evidence = emptyEvidence();
|
|
114
115
|
let terminal;
|
|
116
|
+
let coreDumpTimer;
|
|
117
|
+
let coreDumpCheck;
|
|
118
|
+
let monitoringClosed = false;
|
|
115
119
|
try {
|
|
116
120
|
await mkdir(runCgroup, { mode: 493 });
|
|
117
121
|
cgroupCreated = true;
|
|
@@ -162,6 +166,19 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
|
|
|
162
166
|
});
|
|
163
167
|
childExit = childClose(launched);
|
|
164
168
|
child = launched;
|
|
169
|
+
coreDumpTimer = setInterval(() => {
|
|
170
|
+
if (monitoringClosed || stopReason !== undefined || coreDumpCheck !== undefined)
|
|
171
|
+
return;
|
|
172
|
+
coreDumpCheck = privateHasCoreDumpingProcess(runCgroup, limits.pids).then((dumping) => {
|
|
173
|
+
if (dumping && !monitoringClosed && stopReason === undefined)
|
|
174
|
+
stop("core_dump");
|
|
175
|
+
}).catch(() => {
|
|
176
|
+
if (!monitoringClosed && stopReason === undefined)
|
|
177
|
+
stop("setup_failed");
|
|
178
|
+
}).finally(() => {
|
|
179
|
+
coreDumpCheck = undefined;
|
|
180
|
+
});
|
|
181
|
+
}, CORE_DUMP_POLL_MS);
|
|
165
182
|
launched.stdio[4].on("error", () => stop("setup_failed"));
|
|
166
183
|
const ready = await readReady(launched);
|
|
167
184
|
if (configuration.output) {
|
|
@@ -187,12 +204,16 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
|
|
|
187
204
|
process.stderr.write(`${errorText(error)}
|
|
188
205
|
`);
|
|
189
206
|
} finally {
|
|
207
|
+
monitoringClosed = true;
|
|
208
|
+
clearInterval(coreDumpTimer);
|
|
190
209
|
clearTimeout(deadline);
|
|
191
210
|
await outputDirectory?.close();
|
|
192
211
|
let cleanupError;
|
|
193
212
|
try {
|
|
194
213
|
child?.kill("SIGKILL");
|
|
195
214
|
await killRun();
|
|
215
|
+
if (coreDumpCheck !== undefined)
|
|
216
|
+
await withinTimeout(coreDumpCheck, limits.cleanupTimeoutMs, "core-dump check did not settle");
|
|
196
217
|
if (childExit !== undefined) {
|
|
197
218
|
await withinTimeout(childExit.catch(() => {
|
|
198
219
|
return;
|
|
@@ -225,6 +246,36 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
|
|
|
225
246
|
control.end();
|
|
226
247
|
}
|
|
227
248
|
}
|
|
249
|
+
async function privateHasCoreDumpingProcess(runCgroup, maxProcesses, readText = (path) => readFile(path, "utf8")) {
|
|
250
|
+
const processes = (await readText(`${runCgroup}/cgroup.procs`)).trim();
|
|
251
|
+
const pids = processes === "" ? [] : processes.split(`
|
|
252
|
+
`);
|
|
253
|
+
if (!positiveInteger(maxProcesses) || pids.length > maxProcesses || pids.some((pid) => !/^[1-9][0-9]*$/.test(pid) || !Number.isSafeInteger(Number(pid))))
|
|
254
|
+
throw new Error("invalid owned process observation");
|
|
255
|
+
const membership = `0::${runCgroup.slice("/sys/fs/cgroup".length)}`;
|
|
256
|
+
for (const pid of pids) {
|
|
257
|
+
try {
|
|
258
|
+
const status = await readText(`/proc/${pid}/status`);
|
|
259
|
+
if (status.length > MAX_CONTROL_BYTES)
|
|
260
|
+
throw new Error("oversized owned process status");
|
|
261
|
+
if (!/^CoreDumping:/m.test(status))
|
|
262
|
+
continue;
|
|
263
|
+
const dumping = /^CoreDumping:[ \t]+([01])$/m.exec(status);
|
|
264
|
+
if (dumping === null)
|
|
265
|
+
throw new Error("kernel core-dump observation is unavailable");
|
|
266
|
+
if (dumping[1] !== "1")
|
|
267
|
+
continue;
|
|
268
|
+
if ((await readText(`/proc/${pid}/cgroup`)).split(`
|
|
269
|
+
`).includes(membership))
|
|
270
|
+
return true;
|
|
271
|
+
} catch (error) {
|
|
272
|
+
const code = error.code;
|
|
273
|
+
if (code !== "ENOENT" && code !== "ESRCH")
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
228
279
|
async function enterMain(arguments_) {
|
|
229
280
|
requireFixedBunPosture("entry trampoline");
|
|
230
281
|
if (arguments_.length < 7)
|
|
@@ -792,3 +843,6 @@ if (import.meta.main) {
|
|
|
792
843
|
process.exitCode = 70;
|
|
793
844
|
});
|
|
794
845
|
}
|
|
846
|
+
export {
|
|
847
|
+
privateHasCoreDumpingProcess
|
|
848
|
+
};
|
|
@@ -1375,7 +1375,9 @@ function requirePrivateMacosGuardianStorage(storage, files, cwd) {
|
|
|
1375
1375
|
if (storage === null || typeof storage !== "object" || Object.keys(storage).sort().join() !== "bytes,collect,mountPath" || typeof storage.mountPath !== "string" || !storage.mountPath.startsWith("/") || storage.mountPath === "/" || posix3.normalize(storage.mountPath) !== storage.mountPath || !Number.isSafeInteger(storage.bytes) || storage.bytes < 16 * 1024 * 1024 || storage.bytes > 512 * 1024 * 1024 || storage.bytes % (1024 * 1024) !== 0 || ![null, "output", "work"].includes(storage.collect))
|
|
1376
1376
|
throw new TypeError("invalid macOS guardian storage");
|
|
1377
1377
|
const roots = ["work", "tmp", "output"].map((name) => join5(storage.mountPath, name));
|
|
1378
|
-
|
|
1378
|
+
const inputs = join5(storage.mountPath, "inputs");
|
|
1379
|
+
const readOnlyInputCwd = files.writableTrees.length === 0 && storage.collect === null && files.readOnlyTrees.includes(inputs) && (cwd === inputs || cwd.startsWith(`${inputs}/`));
|
|
1380
|
+
if (files.writableTrees.some((path) => !roots.includes(path)) || !roots.some((root) => cwd === root || cwd.startsWith(`${root}/`)) && !readOnlyInputCwd)
|
|
1379
1381
|
throw new TypeError("macOS writable projection is outside bounded storage");
|
|
1380
1382
|
}
|
|
1381
1383
|
async function preparePrivateMacosGuardianStorage(owner, token, storage, signal) {
|
|
@@ -20228,6 +20228,7 @@ async function captureAttempt(root, backing, selection) {
|
|
|
20228
20228
|
const directories = new Set([identityKey(root.information)]);
|
|
20229
20229
|
let totalBytes = 0;
|
|
20230
20230
|
let directoryCount = 0;
|
|
20231
|
+
const copyBuffer = new Uint8Array(COPY_CHUNK_BYTES);
|
|
20231
20232
|
async function walk(directory, logicalDirectory) {
|
|
20232
20233
|
directoryCount += 1;
|
|
20233
20234
|
if (directoryCount > MAX_DIRECTORIES) {
|
|
@@ -20253,7 +20254,7 @@ async function captureAttempt(root, backing, selection) {
|
|
|
20253
20254
|
invalid("PACKAGE_LIMIT", "selected dependency source exceeds its capture budget", logicalPath);
|
|
20254
20255
|
await rejectKnownOversizeFile(entry.handle, entry.information, logicalPath);
|
|
20255
20256
|
const offset = totalBytes;
|
|
20256
|
-
const size = await copyToBacking(entry.handle, backing, offset, totalBytes, logicalPath, selection?.maximumBytes);
|
|
20257
|
+
const size = await copyToBacking(entry.handle, backing, offset, totalBytes, logicalPath, copyBuffer, selection?.maximumBytes);
|
|
20257
20258
|
totalBytes += size;
|
|
20258
20259
|
if (selection !== undefined && totalBytes > selection.maximumBytes)
|
|
20259
20260
|
invalid("PACKAGE_LIMIT", "selected dependency source exceeds its capture budget", logicalPath);
|
|
@@ -20277,10 +20278,9 @@ async function captureAttempt(root, backing, selection) {
|
|
|
20277
20278
|
}
|
|
20278
20279
|
return { records, fingerprints };
|
|
20279
20280
|
}
|
|
20280
|
-
async function copyToBacking(source, backing, backingOffset, priorTotal, logicalPath, maximumBytes = MAX_TOTAL_BYTES2) {
|
|
20281
|
+
async function copyToBacking(source, backing, backingOffset, priorTotal, logicalPath, buffer, maximumBytes = MAX_TOTAL_BYTES2) {
|
|
20281
20282
|
let sourceOffset = 0;
|
|
20282
20283
|
while (true) {
|
|
20283
|
-
const buffer = new Uint8Array(COPY_CHUNK_BYTES);
|
|
20284
20284
|
let bytesRead;
|
|
20285
20285
|
try {
|
|
20286
20286
|
({ bytesRead } = await source.read(buffer, 0, buffer.byteLength, sourceOffset));
|
|
@@ -188,6 +188,33 @@ function ordinaryRecord(value) {
|
|
|
188
188
|
return value;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
// src/internal/bun-native-inputs.ts
|
|
192
|
+
async function privateBunNativeInputs(input) {
|
|
193
|
+
const manifests = [
|
|
194
|
+
"package.json",
|
|
195
|
+
...input.members?.map((path) => `${path}/package.json`) ?? []
|
|
196
|
+
];
|
|
197
|
+
const paths = new Set(manifests);
|
|
198
|
+
if (input.paths.includes("bun.lock"))
|
|
199
|
+
paths.add("bun.lock");
|
|
200
|
+
let patches = {};
|
|
201
|
+
for (const path of manifests) {
|
|
202
|
+
const bytes = await input.read(path);
|
|
203
|
+
if (bytes.byteLength > 1024 * 1024)
|
|
204
|
+
throw new TypeError("oversized native manifest");
|
|
205
|
+
const manifest = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
206
|
+
requirePrivateBunResolutionManifest(manifest, input.members === undefined ? undefined : path === "package.json" ? "root" : "member");
|
|
207
|
+
if (path === "package.json")
|
|
208
|
+
patches = requirePrivateBunPatches(manifest.patchedDependencies);
|
|
209
|
+
}
|
|
210
|
+
for (const path of Object.values(patches)) {
|
|
211
|
+
if ((await input.read(path)).byteLength > 1024 * 1024)
|
|
212
|
+
throw new TypeError("oversized captured patch");
|
|
213
|
+
paths.add(path);
|
|
214
|
+
}
|
|
215
|
+
return Object.freeze({ paths, patches });
|
|
216
|
+
}
|
|
217
|
+
|
|
191
218
|
// src/package/normalization-data-15.1.ts
|
|
192
219
|
var CANONICAL_CLASS_15_1 = new Map([
|
|
193
220
|
[768, 230],
|
|
@@ -5014,29 +5041,21 @@ try {
|
|
|
5014
5041
|
if (!(await iterator.next()).done) {
|
|
5015
5042
|
throw new WorkerFailure("PACKAGE_BUN_PROTOCOL", "preparation source has trailing data");
|
|
5016
5043
|
}
|
|
5017
|
-
|
|
5018
|
-
"package.json",
|
|
5019
|
-
"bun.lock",
|
|
5020
|
-
...workspace?.members.map((path) => `${path}/package.json`) ?? []
|
|
5021
|
-
]);
|
|
5044
|
+
let inputPaths;
|
|
5022
5045
|
let patches = {};
|
|
5023
5046
|
try {
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
...workspace
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
}
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
if (file === undefined || decodeBase64(file.content, path).byteLength > 1024 * 1024)
|
|
5037
|
-
throw new TypeError("missing or oversized captured patch");
|
|
5038
|
-
inputPaths.add(path);
|
|
5039
|
-
}
|
|
5047
|
+
const native = await privateBunNativeInputs({
|
|
5048
|
+
paths: source.files.map(({ path }) => path),
|
|
5049
|
+
...workspace === undefined ? {} : { members: workspace.members },
|
|
5050
|
+
read(path) {
|
|
5051
|
+
const file = source.files.find((file2) => file2.path === path);
|
|
5052
|
+
if (file === undefined)
|
|
5053
|
+
throw new TypeError("missing native input");
|
|
5054
|
+
return decodeBase64(file.content, path);
|
|
5055
|
+
}
|
|
5056
|
+
});
|
|
5057
|
+
inputPaths = native.paths;
|
|
5058
|
+
patches = native.patches;
|
|
5040
5059
|
} catch {
|
|
5041
5060
|
throw new WorkerFailure("PACKAGE_BUN_SOURCE_UNSUPPORTED", "native manifests or declared patch inputs are unsupported or incomplete");
|
|
5042
5061
|
}
|