@abelxiaoxing/cadence 1.4.1 → 1.5.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.
@@ -1,5 +1,6 @@
1
1
  // Generated by scripts/build-workspace-io.mjs; edit workspace-io-entry.mjs and its source modules.
2
2
  // src/workspace-io-entry.mjs
3
+ import { rmSync as rmSync2 } from "node:fs";
3
4
  import { parentPort, workerData } from "node:worker_threads";
4
5
 
5
6
  // src/artifact-store.ts
@@ -196,19 +197,229 @@ class ArtifactStore {
196
197
  }
197
198
  }
198
199
 
200
+ // src/verification-environment-io.ts
201
+ import {
202
+ constants as constants2,
203
+ cpSync,
204
+ lstatSync as lstatSync2,
205
+ mkdirSync as mkdirSync2,
206
+ readdirSync,
207
+ realpathSync,
208
+ rmSync,
209
+ symlinkSync,
210
+ writeFileSync as writeFileSync2
211
+ } from "node:fs";
212
+ import path2 from "node:path";
213
+ var CACHES = [".vite", ".vite-temp"];
214
+ function within(root, candidate) {
215
+ const relative = path2.relative(root, candidate);
216
+ return relative !== ".." && !relative.startsWith(`..${path2.sep}`) && !path2.isAbsolute(relative);
217
+ }
218
+ function prepareVerificationEnvironmentIo(root, dependencyOwner, runnerBindings, profile, environment, checkCancelled, privateRoot) {
219
+ const cleanup = () => rmSync(privateRoot, { recursive: true, force: true });
220
+ try {
221
+ const local = profile.mode === "local-trusted";
222
+ if (local && realpathSync(root) === realpathSync(dependencyOwner))
223
+ throw new Error("trusted-candidate-required");
224
+ const mounts = [
225
+ { source: privateRoot, target: "/cadence", writable: true }
226
+ ];
227
+ for (const directory of [
228
+ "home",
229
+ "cache",
230
+ "tmp",
231
+ "reports",
232
+ "dependencies"
233
+ ]) {
234
+ mkdirSync2(path2.join(privateRoot, directory), { mode: 448 });
235
+ }
236
+ writeFileSync2(path2.join(privateRoot, "home/user.npmrc"), "");
237
+ writeFileSync2(path2.join(privateRoot, "home/global.npmrc"), "");
238
+ const dependencies = path2.join(dependencyOwner, "node_modules");
239
+ const stat = lstatSync2(dependencies, { throwIfNoEntry: false });
240
+ if (stat) {
241
+ const target = path2.join(root, "node_modules");
242
+ const targetStat = lstatSync2(target, { throwIfNoEntry: false });
243
+ if (!stat.isDirectory() || stat.isSymbolicLink() || targetStat && (!targetStat.isDirectory() || targetStat.isSymbolicLink())) {
244
+ throw new Error("dependency-path-unsafe");
245
+ }
246
+ if (!targetStat)
247
+ mkdirSync2(target, { mode: 448 });
248
+ const view = path2.join(privateRoot, "dependencies");
249
+ mounts.push({ source: view, target: "/workspace/node_modules" });
250
+ const entries = readdirSync(dependencies);
251
+ if (entries.length > 20000)
252
+ throw new Error("dependency-view-too-large");
253
+ const canonical = realpathSync(dependencies);
254
+ let viewEntries = 0;
255
+ const projectEntry = (name) => {
256
+ checkCancelled();
257
+ if (++viewEntries > 20000)
258
+ throw new Error("dependency-view-too-large");
259
+ if (CACHES.includes(name))
260
+ return;
261
+ const source = path2.join(dependencies, name);
262
+ const placeholder = path2.join(view, name);
263
+ const entry = lstatSync2(source);
264
+ if (entry.isSymbolicLink()) {
265
+ const resolved = realpathSync(source);
266
+ if (within(canonical, resolved)) {
267
+ symlinkSync(path2.relative(path2.dirname(source), resolved), placeholder);
268
+ } else if (within(realpathSync(dependencyOwner), resolved)) {
269
+ const relative = path2.relative(realpathSync(dependencyOwner), resolved);
270
+ const candidate = path2.join(root, relative);
271
+ if (!lstatSync2(candidate, { throwIfNoEntry: false }))
272
+ throw new Error("workspace-dependency-missing");
273
+ symlinkSync(local ? candidate : `/workspace/${relative.split(path2.sep).join("/")}`, placeholder);
274
+ } else
275
+ throw new Error("dependency-path-unsafe");
276
+ } else if (entry.isDirectory() && name.startsWith("@") && !name.includes(path2.sep)) {
277
+ mkdirSync2(placeholder);
278
+ for (const child of readdirSync(source))
279
+ projectEntry(path2.join(name, child));
280
+ } else {
281
+ if (entry.isDirectory())
282
+ mkdirSync2(placeholder);
283
+ else if (entry.isFile())
284
+ writeFileSync2(placeholder, "");
285
+ else
286
+ throw new Error("dependency-path-unsafe");
287
+ mounts.push({
288
+ source,
289
+ target: `/workspace/node_modules/${name.split(path2.sep).join("/")}`
290
+ });
291
+ }
292
+ };
293
+ for (const name of entries)
294
+ projectEntry(name);
295
+ for (const cache of CACHES) {
296
+ mkdirSync2(path2.join(view, cache));
297
+ const source = path2.join(privateRoot, "cache", cache);
298
+ mkdirSync2(source);
299
+ mounts.push({
300
+ source,
301
+ target: `/workspace/node_modules/${cache}`,
302
+ writable: true
303
+ });
304
+ }
305
+ }
306
+ if (local && stat) {
307
+ const copyEntry = (name) => {
308
+ checkCancelled();
309
+ const source = path2.join(dependencies, name);
310
+ const destination = path2.join(root, "node_modules", name);
311
+ if (CACHES.includes(name)) {
312
+ mkdirSync2(destination, { recursive: true });
313
+ return;
314
+ }
315
+ removeEntry(destination, checkCancelled);
316
+ const stat2 = lstatSync2(source);
317
+ if (stat2.isSymbolicLink()) {
318
+ const resolved = realpathSync(source);
319
+ const translated = within(canonicalRoot(dependencyOwner), resolved) ? path2.join(root, path2.relative(canonicalRoot(dependencyOwner), resolved)) : resolved;
320
+ symlinkSync(translated, destination);
321
+ } else if (stat2.isDirectory() && name.startsWith("@") && !name.includes(path2.sep)) {
322
+ mkdirSync2(destination);
323
+ for (const child of readdirSync(source))
324
+ copyEntry(path2.join(name, child));
325
+ } else
326
+ cpSync(source, destination, {
327
+ recursive: true,
328
+ filter: () => {
329
+ checkCancelled();
330
+ return true;
331
+ },
332
+ mode: constants2.COPYFILE_FICLONE,
333
+ verbatimSymlinks: true
334
+ });
335
+ };
336
+ for (const name of readdirSync(path2.join(privateRoot, "dependencies")))
337
+ copyEntry(name);
338
+ }
339
+ const sources = new Map;
340
+ const bindings = runnerBindings.map((binding) => {
341
+ if (local || !binding.mountSource)
342
+ return { ...binding };
343
+ const source = path2.resolve(binding.mountSource);
344
+ const stat2 = lstatSync2(source);
345
+ const executable = realpathSync(binding.executablePath);
346
+ if (!stat2.isDirectory() || stat2.isSymbolicLink() || !within(source, executable)) {
347
+ throw new Error("runner-mount-unavailable");
348
+ }
349
+ let target = sources.get(source);
350
+ if (!target) {
351
+ target = `/cadence-runners/${sources.size}`;
352
+ sources.set(source, target);
353
+ mounts.push({ source, target });
354
+ }
355
+ const translate = (file) => path2.posix.join(target, ...path2.relative(source, file).split(path2.sep));
356
+ return {
357
+ ...binding,
358
+ executablePath: translate(executable),
359
+ ...binding.fixedArgs ? {
360
+ fixedArgs: binding.fixedArgs.map((arg) => path2.isAbsolute(arg) && within(source, arg) ? translate(arg) : arg)
361
+ } : {}
362
+ };
363
+ });
364
+ checkCancelled();
365
+ return {
366
+ privateRoot,
367
+ mounts,
368
+ bindings,
369
+ reportRoot: local ? privateRoot : "/cadence",
370
+ environment: {
371
+ ...local ? Object.fromEntries(profile.inheritEnvironment.flatMap((name) => environment[name] === undefined ? [] : [[name, environment[name] ?? ""]])) : {},
372
+ CI: "1",
373
+ HOME: local ? path2.join(privateRoot, "home") : "/cadence/home",
374
+ XDG_CACHE_HOME: local ? path2.join(privateRoot, "cache") : "/cadence/cache",
375
+ TMPDIR: local ? path2.join(privateRoot, "tmp") : "/cadence/tmp",
376
+ npm_config_cache: local ? path2.join(privateRoot, "cache/npm") : "/cadence/cache/npm",
377
+ npm_config_userconfig: local ? path2.join(privateRoot, "home/user.npmrc") : "/cadence/home/user.npmrc",
378
+ npm_config_globalconfig: local ? path2.join(privateRoot, "home/global.npmrc") : "/cadence/home/global.npmrc",
379
+ PATH: [
380
+ ...new Set([
381
+ ...bindings.filter((binding) => binding.mountSource),
382
+ ...bindings.filter((binding) => !binding.mountSource)
383
+ ].map((binding) => path2.posix.dirname(binding.executablePath))),
384
+ ...local ? (environment.PATH ?? "").split(path2.delimiter) : [],
385
+ "/usr/local/bin",
386
+ "/usr/bin",
387
+ "/bin"
388
+ ].join(":")
389
+ }
390
+ };
391
+ } catch (error) {
392
+ cleanup();
393
+ throw error;
394
+ }
395
+ }
396
+ function canonicalRoot(root) {
397
+ return realpathSync(root);
398
+ }
399
+ function removeEntry(file, checkCancelled) {
400
+ checkCancelled();
401
+ const stat = lstatSync2(file, { throwIfNoEntry: false });
402
+ if (!stat)
403
+ return;
404
+ if (stat.isDirectory())
405
+ for (const name of readdirSync(file))
406
+ removeEntry(path2.join(file, name), checkCancelled);
407
+ rmSync(file, { recursive: stat.isDirectory(), force: true });
408
+ }
409
+
199
410
  // src/verification-identity.ts
200
411
  import { createHash as createHash2 } from "node:crypto";
201
412
  import {
202
413
  closeSync as closeSync2,
203
- constants as constants2,
414
+ constants as constants3,
204
415
  fstatSync,
205
- lstatSync as lstatSync2,
416
+ lstatSync as lstatSync3,
206
417
  openSync as openSync2,
207
- readdirSync,
418
+ readdirSync as readdirSync2,
208
419
  readlinkSync,
209
420
  readSync
210
421
  } from "node:fs";
211
- import path2 from "node:path";
422
+ import path3 from "node:path";
212
423
  function verificationEnvironmentDigest(roots, checkCancelled = () => {}) {
213
424
  const digest2 = createHash2("sha256");
214
425
  let entries = 0;
@@ -219,7 +430,7 @@ function verificationEnvironmentDigest(roots, checkCancelled = () => {}) {
219
430
  checkCancelled();
220
431
  if (++entries > 500000 || Date.now() - started > 60000)
221
432
  throw new Error("verification-environment-limit");
222
- const stat = lstatSync2(file, { throwIfNoEntry: false });
433
+ const stat = lstatSync3(file, { throwIfNoEntry: false });
223
434
  digest2.update(JSON.stringify([relative, stat ? stat.mode & 511 : null]));
224
435
  if (!stat) {
225
436
  digest2.update("absent");
@@ -231,16 +442,16 @@ function verificationEnvironmentDigest(roots, checkCancelled = () => {}) {
231
442
  }
232
443
  if (stat.isDirectory()) {
233
444
  digest2.update("directory");
234
- for (const name of readdirSync(file).sort()) {
445
+ for (const name of readdirSync2(file).sort()) {
235
446
  if (dependencyRoot && [".vite", ".vite-temp"].includes(name))
236
447
  continue;
237
- visit(path2.join(file, name), `${relative}/${name}`, false);
448
+ visit(path3.join(file, name), `${relative}/${name}`, false);
238
449
  }
239
450
  return;
240
451
  }
241
452
  if (!stat.isFile())
242
453
  throw new Error("verification-environment-unsafe");
243
- const fd = openSync2(file, constants2.O_RDONLY | constants2.O_NOFOLLOW);
454
+ const fd = openSync2(file, constants3.O_RDONLY | constants3.O_NOFOLLOW);
244
455
  try {
245
456
  const before = fstatSync(fd);
246
457
  if (before.ino !== stat.ino || before.dev !== stat.dev)
@@ -265,7 +476,7 @@ function verificationEnvironmentDigest(roots, checkCancelled = () => {}) {
265
476
  }
266
477
  };
267
478
  for (const root of [...new Set(roots)].sort())
268
- visit(root, root, path2.basename(root) === "node_modules");
479
+ visit(root, root, path3.basename(root) === "node_modules");
269
480
  return digest2.digest("hex");
270
481
  }
271
482
 
@@ -275,17 +486,17 @@ import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypt
275
486
  import {
276
487
  chmodSync as chmodSync2,
277
488
  closeSync as closeSync3,
278
- constants as constants3,
489
+ constants as constants4,
279
490
  fsyncSync as fsyncSync2,
280
- lstatSync as lstatSync4,
281
- mkdirSync as mkdirSync2,
491
+ lstatSync as lstatSync5,
492
+ mkdirSync as mkdirSync3,
282
493
  openSync as openSync3,
283
494
  readFileSync as readFileSync2,
284
495
  renameSync as renameSync2,
285
496
  unlinkSync as unlinkSync2,
286
- writeFileSync as writeFileSync2
497
+ writeFileSync as writeFileSync3
287
498
  } from "node:fs";
288
- import path4 from "node:path";
499
+ import path5 from "node:path";
289
500
  import { promisify } from "node:util";
290
501
 
291
502
  // src/canonical.ts
@@ -404,15 +615,15 @@ function isValidRelativePath(p) {
404
615
  }
405
616
 
406
617
  // src/safe-path.ts
407
- import { lstatSync as lstatSync3 } from "node:fs";
408
- import path3 from "node:path";
618
+ import { lstatSync as lstatSync4 } from "node:fs";
619
+ import path4 from "node:path";
409
620
  function observeSafePath(root, relative) {
410
621
  if (!isValidRelativePath(relative)) {
411
622
  return { kind: "unsafe", reason: "invalid-path" };
412
623
  }
413
624
  try {
414
- const resolvedRoot = path3.resolve(root);
415
- const rootStat = lstatSync3(resolvedRoot, { throwIfNoEntry: false });
625
+ const resolvedRoot = path4.resolve(root);
626
+ const rootStat = lstatSync4(resolvedRoot, { throwIfNoEntry: false });
416
627
  if (!rootStat?.isDirectory() || rootStat.isSymbolicLink()) {
417
628
  return { kind: "unsafe", reason: "root-unavailable" };
418
629
  }
@@ -421,11 +632,11 @@ function observeSafePath(root, relative) {
421
632
  let current = resolvedRoot;
422
633
  const parts = relative.split("/");
423
634
  for (const [index, part] of parts.entries()) {
424
- current = path3.join(current, part);
425
- if (!current.startsWith(`${resolvedRoot}${path3.sep}`)) {
635
+ current = path4.join(current, part);
636
+ if (!current.startsWith(`${resolvedRoot}${path4.sep}`)) {
426
637
  return { kind: "unsafe", reason: "invalid-path" };
427
638
  }
428
- const stat = lstatSync3(current, { throwIfNoEntry: false });
639
+ const stat = lstatSync4(current, { throwIfNoEntry: false });
429
640
  if (!stat)
430
641
  return { kind: "absent" };
431
642
  if (stat.isSymbolicLink()) {
@@ -528,7 +739,7 @@ function revisionId(parentRevisionId, manifest) {
528
739
  return hash("cadence-workspace-revision", parentRevisionId ?? "", manifest);
529
740
  }
530
741
  function ensureDirectory2(directory) {
531
- const stat = lstatSync4(directory, { throwIfNoEntry: false });
742
+ const stat = lstatSync5(directory, { throwIfNoEntry: false });
532
743
  if (stat) {
533
744
  if (stat.isSymbolicLink() || !stat.isDirectory()) {
534
745
  throw new Error("unsafe-workspace-path");
@@ -536,26 +747,26 @@ function ensureDirectory2(directory) {
536
747
  chmodSync2(directory, 448);
537
748
  return;
538
749
  }
539
- let cursor = path4.dirname(directory);
540
- while (cursor !== path4.dirname(cursor)) {
541
- const ancestor = lstatSync4(cursor, { throwIfNoEntry: false });
750
+ let cursor = path5.dirname(directory);
751
+ while (cursor !== path5.dirname(cursor)) {
752
+ const ancestor = lstatSync5(cursor, { throwIfNoEntry: false });
542
753
  if (ancestor) {
543
754
  if (ancestor.isSymbolicLink() || !ancestor.isDirectory()) {
544
755
  throw new Error("unsafe-workspace-path");
545
756
  }
546
757
  break;
547
758
  }
548
- cursor = path4.dirname(cursor);
759
+ cursor = path5.dirname(cursor);
549
760
  }
550
- mkdirSync2(directory, { recursive: true, mode: 448 });
551
- const created = lstatSync4(directory);
761
+ mkdirSync3(directory, { recursive: true, mode: 448 });
762
+ const created = lstatSync5(directory);
552
763
  if (created.isSymbolicLink() || !created.isDirectory()) {
553
764
  throw new Error("unsafe-workspace-path");
554
765
  }
555
766
  chmodSync2(directory, 448);
556
767
  }
557
768
  function syncDirectory2(directory) {
558
- const descriptor = openSync3(directory, constants3.O_RDONLY);
769
+ const descriptor = openSync3(directory, constants4.O_RDONLY);
559
770
  try {
560
771
  fsyncSync2(descriptor);
561
772
  } finally {
@@ -563,12 +774,12 @@ function syncDirectory2(directory) {
563
774
  }
564
775
  }
565
776
  function writeAtomic2(target, bytes) {
566
- const directory = path4.dirname(target);
777
+ const directory = path5.dirname(target);
567
778
  ensureDirectory2(directory);
568
- const temporary = path4.join(directory, `.${path4.basename(target)}.${process.pid}.${randomUUID2()}.tmp`);
569
- const descriptor = openSync3(temporary, constants3.O_CREAT | constants3.O_EXCL | constants3.O_WRONLY, 384);
779
+ const temporary = path5.join(directory, `.${path5.basename(target)}.${process.pid}.${randomUUID2()}.tmp`);
780
+ const descriptor = openSync3(temporary, constants4.O_CREAT | constants4.O_EXCL | constants4.O_WRONLY, 384);
570
781
  try {
571
- writeFileSync2(descriptor, bytes);
782
+ writeFileSync3(descriptor, bytes);
572
783
  fsyncSync2(descriptor);
573
784
  } finally {
574
785
  closeSync3(descriptor);
@@ -649,10 +860,10 @@ class WorkspaceStore {
649
860
  constructor(root, artifacts, options = {}) {
650
861
  this.#checkCancelled = options.checkCancelled ?? (() => {});
651
862
  this.#onMetrics = options.onMetrics;
652
- if (!path4.isAbsolute(root))
863
+ if (!path5.isAbsolute(root))
653
864
  throw new Error("workspace-store-root-invalid");
654
- this.root = path4.resolve(root);
655
- this.#revisions = path4.join(this.root, "revisions");
865
+ this.root = path5.resolve(root);
866
+ this.#revisions = path5.join(this.root, "revisions");
656
867
  this.#artifacts = artifacts;
657
868
  ensureDirectory2(this.root);
658
869
  ensureDirectory2(this.#revisions);
@@ -660,7 +871,7 @@ class WorkspaceStore {
660
871
  #revisionPath(id) {
661
872
  if (!SHA2562.test(id))
662
873
  throw new Error("workspace-revision-id-invalid");
663
- return path4.join(this.#revisions, id.slice(0, 2), `${id}.json`);
874
+ return path5.join(this.#revisions, id.slice(0, 2), `${id}.json`);
664
875
  }
665
876
  #storeRevision(parentRevisionId, rawEntries) {
666
877
  const entries = stableEntries(rawEntries);
@@ -673,7 +884,7 @@ class WorkspaceStore {
673
884
  entries
674
885
  };
675
886
  const target = this.#revisionPath(id);
676
- const existing = lstatSync4(target, { throwIfNoEntry: false });
887
+ const existing = lstatSync5(target, { throwIfNoEntry: false });
677
888
  if (existing) {
678
889
  const stored = this.getRevision(id);
679
890
  if (JSON.stringify(stored) !== JSON.stringify(revision)) {
@@ -705,8 +916,8 @@ class WorkspaceStore {
705
916
  return false;
706
917
  }
707
918
  captureBaseline(input) {
708
- const consumerRoot = path4.resolve(input.consumerRoot);
709
- const rootStat = lstatSync4(consumerRoot, { throwIfNoEntry: false });
919
+ const consumerRoot = path5.resolve(input.consumerRoot);
920
+ const rootStat = lstatSync5(consumerRoot, { throwIfNoEntry: false });
710
921
  if (!rootStat?.isDirectory() || rootStat.isSymbolicLink()) {
711
922
  throw new Error("unsafe-workspace-path");
712
923
  }
@@ -719,7 +930,7 @@ class WorkspaceStore {
719
930
  const timeout = input.gitTimeoutMs ?? 30000;
720
931
  if (!Number.isSafeInteger(timeout) || timeout < 1 || timeout > 30000)
721
932
  throw new Error("workspace-git-timeout-invalid");
722
- const consumerRoot = path4.resolve(input.consumerRoot);
933
+ const consumerRoot = path5.resolve(input.consumerRoot);
723
934
  let tracked;
724
935
  try {
725
936
  tracked = parseNullSeparated(execFileSync("git", ["ls-files", "-z", "--cached"], {
@@ -753,10 +964,10 @@ class WorkspaceStore {
753
964
  }
754
965
  if (observation.kind !== "file")
755
966
  throw new Error("unsafe-workspace-path");
756
- const absolute = path4.join(consumerRoot, ...relative.split("/"));
967
+ const absolute = path5.join(consumerRoot, ...relative.split("/"));
757
968
  const bytes = readFileSync2(absolute);
758
969
  const artifact = this.#artifacts.put(bytes);
759
- const stat = lstatSync4(absolute);
970
+ const stat = lstatSync5(absolute);
760
971
  entries[relative] = {
761
972
  kind: "file",
762
973
  hash: artifact.hash,
@@ -777,7 +988,7 @@ class WorkspaceStore {
777
988
  }
778
989
  getRevision(id) {
779
990
  const target = this.#revisionPath(id);
780
- const stat = lstatSync4(target, { throwIfNoEntry: false });
991
+ const stat = lstatSync5(target, { throwIfNoEntry: false });
781
992
  if (!stat?.isFile() || stat.isSymbolicLink()) {
782
993
  throw new Error("workspace-revision-unavailable");
783
994
  }
@@ -856,7 +1067,7 @@ class WorkspaceStore {
856
1067
  }
857
1068
  materialize(revisionIdValue, destination) {
858
1069
  const revision = this.getRevision(revisionIdValue);
859
- const root = path4.resolve(destination);
1070
+ const root = path5.resolve(destination);
860
1071
  ensureDirectory2(root);
861
1072
  for (const [relative, entry] of Object.entries(revision.entries)) {
862
1073
  this.#checkCancelled();
@@ -875,10 +1086,10 @@ class WorkspaceStore {
875
1086
  const segments = relative.split("/");
876
1087
  let parent = root;
877
1088
  for (const segment of segments.slice(0, -1)) {
878
- parent = path4.join(parent, segment);
1089
+ parent = path5.join(parent, segment);
879
1090
  ensureDirectory2(parent);
880
1091
  }
881
- const target = path4.join(root, ...segments);
1092
+ const target = path5.join(root, ...segments);
882
1093
  if (observation.kind !== "absent") {
883
1094
  throw new Error("workspace-materialize-conflict");
884
1095
  }
@@ -890,8 +1101,8 @@ class WorkspaceStore {
890
1101
  }
891
1102
  async captureBaselineWithGit(input, signal) {
892
1103
  signal?.throwIfAborted();
893
- const consumerRoot = path4.resolve(input.consumerRoot);
894
- const stat = lstatSync4(consumerRoot, { throwIfNoEntry: false });
1104
+ const consumerRoot = path5.resolve(input.consumerRoot);
1105
+ const stat = lstatSync5(consumerRoot, { throwIfNoEntry: false });
895
1106
  if (!stat?.isDirectory() || stat.isSymbolicLink())
896
1107
  throw new Error("unsafe-workspace-path");
897
1108
  const excluded = [".git", "node_modules", ...input.excludedPaths ?? []];
@@ -951,7 +1162,14 @@ var checkCancelled = () => {
951
1162
  throw new Error("cancelled");
952
1163
  };
953
1164
  try {
954
- if (workerData.operation === "verificationIdentity") {
1165
+ if (workerData.operation === "prepareVerification") {
1166
+ const [root, owner, bindings, profile, environment, scratch] = workerData.args;
1167
+ const result = prepareVerificationEnvironmentIo(root, owner, bindings, profile, environment, checkCancelled, scratch);
1168
+ parentPort.postMessage({ ok: true, result, files: 0, bytes: 0 });
1169
+ } else if (workerData.operation === "cleanupVerification") {
1170
+ rmSync2(workerData.args[0], { recursive: true, force: true });
1171
+ parentPort.postMessage({ ok: true, files: 0, bytes: 0 });
1172
+ } else if (workerData.operation === "verificationIdentity") {
955
1173
  const result = verificationEnvironmentDigest(workerData.args[0], checkCancelled);
956
1174
  parentPort.postMessage({ ok: true, result, files: 0, bytes: 0 });
957
1175
  } else {
@@ -1,7 +1,12 @@
1
1
  import { Worker } from "node:worker_threads";
2
2
 
3
3
  export interface WorkspaceIoMetrics {
4
- operation: "captureBaseline" | "materialize" | "verificationIdentity";
4
+ operation:
5
+ | "captureBaseline"
6
+ | "materialize"
7
+ | "verificationIdentity"
8
+ | "prepareVerification"
9
+ | "cleanupVerification";
5
10
  elapsedMs: number;
6
11
  files: number;
7
12
  bytes: number;