@ricsam/r5d-worker 0.0.13 → 0.0.14

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/dist/cjs/main.cjs CHANGED
@@ -32,6 +32,7 @@ __export(main_exports, {
32
32
  ensureVisibleGitCheckout: () => ensureVisibleGitCheckout,
33
33
  isArtifactEnvPath: () => isArtifactEnvPath,
34
34
  prepareArtifactEnvForShell: () => prepareArtifactEnvForShell,
35
+ resolveProjectFilePath: () => resolveProjectFilePath,
35
36
  syncSessionArtifacts: () => syncSessionArtifacts
36
37
  });
37
38
  module.exports = __toCommonJS(main_exports);
@@ -548,9 +549,12 @@ function getInternalStatus(context) {
548
549
  function hasInternalWorktreeChanges(context) {
549
550
  return getInternalStatus(context).trim().length > 0;
550
551
  }
552
+ function isInsideBranchPath(branchPath, filePath) {
553
+ const relative = import_node_path.default.relative(import_node_path.default.resolve(branchPath), import_node_path.default.resolve(filePath));
554
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${import_node_path.default.sep}`) && !import_node_path.default.isAbsolute(relative);
555
+ }
551
556
  function assertInsideBranch(branchPath, filePath) {
552
- const relative = import_node_path.default.relative(branchPath, filePath);
553
- if (relative === ".." || relative.startsWith(`..${import_node_path.default.sep}`) || import_node_path.default.isAbsolute(relative)) {
557
+ if (!isInsideBranchPath(branchPath, filePath)) {
554
558
  throw new Error("File path escapes the project branch");
555
559
  }
556
560
  }
@@ -558,17 +562,27 @@ function resolveProjectFilePath(branchPath, virtualPath) {
558
562
  if (typeof virtualPath !== "string" || !virtualPath.startsWith("/") || virtualPath.includes("\0")) {
559
563
  throw new Error(`File path must be an absolute project path starting with /. Got: ${JSON.stringify(virtualPath)}`);
560
564
  }
565
+ const checkoutAbsolutePath = import_node_path.default.resolve(virtualPath);
566
+ if (isInsideBranchPath(branchPath, checkoutAbsolutePath)) {
567
+ const checkoutVirtualPath = toVirtualPath(import_node_path.default.resolve(branchPath), checkoutAbsolutePath);
568
+ if (checkoutVirtualPath !== virtualPath) {
569
+ return resolveProjectFilePath(branchPath, checkoutVirtualPath);
570
+ }
571
+ }
572
+ if (virtualPath.split("/").includes("..")) {
573
+ throw new Error(`Invalid project file path: ${virtualPath}`);
574
+ }
561
575
  const normalized = import_node_path.default.posix.normalize(virtualPath);
562
- if (normalized === "/" || normalized.startsWith("/../")) {
576
+ if (normalized.startsWith("/../")) {
563
577
  throw new Error(`Invalid project file path: ${virtualPath}`);
564
578
  }
565
- const repoRelativePath = normalized.slice(1);
579
+ const repoRelativePath = normalized === "/" ? "" : normalized.slice(1);
566
580
  if (repoRelativePath === ".git" || repoRelativePath.startsWith(".git/")) {
567
581
  throw new Error("Refusing to access .git through worker file tools");
568
582
  }
569
- const absolutePath = import_node_path.default.resolve(branchPath, ...repoRelativePath.split("/"));
583
+ const absolutePath = repoRelativePath ? import_node_path.default.resolve(branchPath, ...repoRelativePath.split("/")) : import_node_path.default.resolve(branchPath);
570
584
  assertInsideBranch(branchPath, absolutePath);
571
- return { absolutePath, virtualPath: `/${repoRelativePath}`, repoRelativePath };
585
+ return { absolutePath, virtualPath: repoRelativePath ? `/${repoRelativePath}` : "/", repoRelativePath };
572
586
  }
573
587
  function branchLockKey(projectId, branchName) {
574
588
  return `${projectId}:${branchName}`;
@@ -2238,5 +2252,6 @@ if (isCliEntrypoint()) {
2238
2252
  ensureVisibleGitCheckout,
2239
2253
  isArtifactEnvPath,
2240
2254
  prepareArtifactEnvForShell,
2255
+ resolveProjectFilePath,
2241
2256
  syncSessionArtifacts
2242
2257
  });
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "type": "commonjs"
5
5
  }
package/dist/mjs/main.mjs CHANGED
@@ -511,9 +511,12 @@ function getInternalStatus(context) {
511
511
  function hasInternalWorktreeChanges(context) {
512
512
  return getInternalStatus(context).trim().length > 0;
513
513
  }
514
+ function isInsideBranchPath(branchPath, filePath) {
515
+ const relative = path.relative(path.resolve(branchPath), path.resolve(filePath));
516
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
517
+ }
514
518
  function assertInsideBranch(branchPath, filePath) {
515
- const relative = path.relative(branchPath, filePath);
516
- if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
519
+ if (!isInsideBranchPath(branchPath, filePath)) {
517
520
  throw new Error("File path escapes the project branch");
518
521
  }
519
522
  }
@@ -521,17 +524,27 @@ function resolveProjectFilePath(branchPath, virtualPath) {
521
524
  if (typeof virtualPath !== "string" || !virtualPath.startsWith("/") || virtualPath.includes("\0")) {
522
525
  throw new Error(`File path must be an absolute project path starting with /. Got: ${JSON.stringify(virtualPath)}`);
523
526
  }
527
+ const checkoutAbsolutePath = path.resolve(virtualPath);
528
+ if (isInsideBranchPath(branchPath, checkoutAbsolutePath)) {
529
+ const checkoutVirtualPath = toVirtualPath(path.resolve(branchPath), checkoutAbsolutePath);
530
+ if (checkoutVirtualPath !== virtualPath) {
531
+ return resolveProjectFilePath(branchPath, checkoutVirtualPath);
532
+ }
533
+ }
534
+ if (virtualPath.split("/").includes("..")) {
535
+ throw new Error(`Invalid project file path: ${virtualPath}`);
536
+ }
524
537
  const normalized = path.posix.normalize(virtualPath);
525
- if (normalized === "/" || normalized.startsWith("/../")) {
538
+ if (normalized.startsWith("/../")) {
526
539
  throw new Error(`Invalid project file path: ${virtualPath}`);
527
540
  }
528
- const repoRelativePath = normalized.slice(1);
541
+ const repoRelativePath = normalized === "/" ? "" : normalized.slice(1);
529
542
  if (repoRelativePath === ".git" || repoRelativePath.startsWith(".git/")) {
530
543
  throw new Error("Refusing to access .git through worker file tools");
531
544
  }
532
- const absolutePath = path.resolve(branchPath, ...repoRelativePath.split("/"));
545
+ const absolutePath = repoRelativePath ? path.resolve(branchPath, ...repoRelativePath.split("/")) : path.resolve(branchPath);
533
546
  assertInsideBranch(branchPath, absolutePath);
534
- return { absolutePath, virtualPath: `/${repoRelativePath}`, repoRelativePath };
547
+ return { absolutePath, virtualPath: repoRelativePath ? `/${repoRelativePath}` : "/", repoRelativePath };
535
548
  }
536
549
  function branchLockKey(projectId, branchName) {
537
550
  return `${projectId}:${branchName}`;
@@ -2200,5 +2213,6 @@ export {
2200
2213
  ensureVisibleGitCheckout,
2201
2214
  isArtifactEnvPath,
2202
2215
  prepareArtifactEnvForShell,
2216
+ resolveProjectFilePath,
2203
2217
  syncSessionArtifacts
2204
2218
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "type": "module"
5
5
  }
@@ -20,6 +20,11 @@ type GitAuth = {
20
20
  extraHeaderUrl: string;
21
21
  header: string;
22
22
  };
23
+ export declare function resolveProjectFilePath(branchPath: string, virtualPath: string): {
24
+ absolutePath: string;
25
+ virtualPath: string;
26
+ repoRelativePath: string;
27
+ };
23
28
  export declare function ensureVisibleGitCheckout(input: {
24
29
  projectRoot: string;
25
30
  branchName: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/main.cjs",
6
6
  "module": "./dist/mjs/main.mjs",