fix(FN-XXXX): narrow backup matcher and isolate version probes
Two follow-up corrections to the in-process auto-backup interception: - The matcher previously hijacked any `fn backup …` / `fusion backup …` / `runfusion.ai backup …` form. The in-process replacement only knows how to do `--create` + cleanup, so scheduling `--list`, `--cleanup`, or `--restore <file>` would have silently executed a create instead of the requested operation. The matcher is now anchored to `backup --create` (with optional trailing flags), with positive/negative unit tests. - Step-based automations (`AutomationStep` with `type: "command"`) also shell out — the legacy-command interception alone left that path vulnerable. `executeCommandStep` now applies the same in-process backup detour, factored through a shared `runBackupActionInProcess` helper. Independently, `runProbe` in fn-binary now spawns with `cwd: tmpdir()`. The dashboard's `/system/fn-binary/status` route runs `<bin> --version` on whatever fusion binary happens to be on PATH — older releases (e.g. v0.13.0) initialise an engine and create a fresh `.fusion/<project>/ .fusion/` tree as a side effect. Pinning the probe's cwd to the OS temp directory keeps any such artefacts off the developer's project. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { CronRunner, createAiPromptExecutor } from "../cron-runner.js";
|
||||
import { CronRunner, createAiPromptExecutor, isInProcessBackupCommand } from "../cron-runner.js";
|
||||
import type { AiPromptExecutor } from "../cron-runner.js";
|
||||
import type { TaskStore, AutomationStore, ScheduledTask, AutomationRunResult, AutomationStep, Settings } from "@fusion/core";
|
||||
import { randomUUID } from "node:crypto";
|
||||
@@ -1778,4 +1778,47 @@ describe("CronRunner", () => {
|
||||
expect(calls[1][0]).toBe("project-boundary");
|
||||
});
|
||||
});
|
||||
|
||||
describe("isInProcessBackupCommand", () => {
|
||||
const positives = [
|
||||
"fn backup --create",
|
||||
"fusion backup --create",
|
||||
"runfusion.ai backup --create",
|
||||
"runfusion backup --create",
|
||||
"@runfusion/fusion backup --create",
|
||||
"npx runfusion.ai backup --create",
|
||||
"npx @runfusion/fusion backup --create",
|
||||
"FN BACKUP --CREATE",
|
||||
"fn backup --create --some-other-flag",
|
||||
" fn backup --create ",
|
||||
];
|
||||
|
||||
const negatives = [
|
||||
// Wrong subcommand — must not be intercepted, the in-process path
|
||||
// only does create+cleanup and would silently swallow these.
|
||||
"fn backup --list",
|
||||
"fn backup --restore /tmp/old.db",
|
||||
"fn backup --cleanup",
|
||||
"fn backup",
|
||||
"fn task list",
|
||||
"echo hello",
|
||||
"fn-other backup --create",
|
||||
"fnbackup --create",
|
||||
"fnext backup --create",
|
||||
"",
|
||||
undefined,
|
||||
];
|
||||
|
||||
for (const cmd of positives) {
|
||||
it(`intercepts: ${cmd}`, () => {
|
||||
expect(isInProcessBackupCommand(cmd)).toBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
for (const cmd of negatives) {
|
||||
it(`does NOT intercept: ${JSON.stringify(cmd)}`, () => {
|
||||
expect(isInProcessBackupCommand(cmd)).toBe(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user