fix(fusion): prevent nested .fusion roots and safe fn version lookup

This commit is contained in:
gsxdsm
2026-05-03 02:02:25 -07:00
parent 757d304a1a
commit 43a9cad3b9
14 changed files with 362 additions and 20 deletions

View File

@@ -85,6 +85,7 @@ function makeMockStore() {
updatePrInfo: vi.fn().mockResolvedValue({}),
logEntry: vi.fn().mockResolvedValue(undefined),
updateTask: vi.fn().mockResolvedValue({}),
getRootDir: vi.fn().mockReturnValue("/tmp/test"),
getFusionDir: vi.fn().mockReturnValue("/tmp/test/.fusion"),
getGlobalSettingsStore: vi.fn(() => ({
getSettings: mockGlobalSettingsGetSettings,

View File

@@ -72,6 +72,7 @@ const mocks = vi.hoisted(() => {
init: vi.fn().mockResolvedValue(undefined),
watch: vi.fn().mockResolvedValue(undefined),
close: vi.fn(),
getRootDir: vi.fn().mockReturnValue(`/repo${projectId ? `/${projectId}` : ""}`),
getFusionDir: vi.fn().mockReturnValue(`/repo${projectId ? `/${projectId}` : ""}/.fusion`),
getGlobalSettingsStore: vi.fn(() => ({
getSettings: vi.fn().mockResolvedValue({}),
@@ -879,12 +880,12 @@ describe("runServe — Plugin wiring", () => {
await triggerSignal("SIGINT");
});
it("initializes PluginStore with the task store's fusion directory", async () => {
it("initializes PluginStore with the task store's project root", async () => {
const { PluginStore } = await import("@fusion/core");
await runServe(4040, {});
expect(PluginStore).toHaveBeenCalledWith("/repo/.fusion");
expect(PluginStore).toHaveBeenCalledWith("/repo");
await triggerSignal("SIGINT");
});

View File

@@ -1,5 +1,5 @@
import type { AddressInfo } from "node:net";
import { join, resolve as pathResolve } from "node:path";
import { dirname, join, resolve as pathResolve } from "node:path";
import { execFile as execFileCb } from "node:child_process";
import { promisify } from "node:util";
import { stat, readdir, readFile as fsReadFile } from "node:fs/promises";
@@ -1062,7 +1062,7 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
const pluginStoreRootDir =
typeof (store as { getRootDir?: () => string }).getRootDir === "function"
? store.getRootDir()
: store.getFusionDir();
: dirname(store.getFusionDir());
const pluginStore = new PluginStore(pluginStoreRootDir);
await pluginStore.init();

View File

@@ -10,7 +10,7 @@
*/
import type { AddressInfo } from "node:net";
import { join } from "node:path";
import { dirname, join } from "node:path";
import {
CentralCore,
PluginStore,
@@ -413,7 +413,7 @@ export async function runServe(
const pluginStoreRootDir =
typeof (store as { getRootDir?: () => string }).getRootDir === "function"
? store.getRootDir()
: store.getFusionDir();
: dirname(store.getFusionDir());
const pluginStore = new PluginStore(pluginStoreRootDir);
await pluginStore.init();