fix(FN-2525): harden remote access auth and tunnel regression coverage

- Add regression tests across CLI, core, dashboard, and engine for remote access auth, settings parity, and serve/TUI callback wiring
- Expand dashboard route and modal coverage for remote settings/auth flows including node environment behaviors
- Redact provider-switch failure details in tunnel process manager to avoid leaking sensitive provider diagnostics
- Update route registration and engine lifecycle tests to lock in remote-access behavior under real execution paths
This commit is contained in:
Fusion
2026-04-26 06:35:46 -07:00
committed by gsxdsm
parent 559e908865
commit f09346a9da
13 changed files with 815 additions and 19 deletions

View File

@@ -360,6 +360,16 @@ const mocks = vi.hoisted(() => {
});
const notifier = notifierCtor();
const remoteStatus = {
provider: "cloudflare" as const,
state: "running" as const,
pid: 1234,
startedAt: new Date().toISOString(),
stoppedAt: null,
url: "https://remote.example.com",
lastError: null,
};
const engine = {
start: vi.fn(async () => {
await store.init();
@@ -412,6 +422,15 @@ const mocks = vi.hoisted(() => {
getMissionAutopilot: () => missionAutopilot,
getMissionExecutionLoop: () => missionExecutionLoop,
})),
getRemoteTunnelManager: vi.fn(() => ({ getStatus: vi.fn(() => remoteStatus) })),
getRemoteTunnelRestoreDiagnostics: vi.fn(() => ({
outcome: "skipped",
reason: "not_attempted",
at: new Date().toISOString(),
provider: null,
})),
startRemoteTunnel: vi.fn(async () => remoteStatus),
stopRemoteTunnel: vi.fn(async () => ({ ...remoteStatus, state: "stopped" as const, provider: null, pid: null, url: null })),
onMerge: vi.fn().mockResolvedValue(undefined),
};
projectEngineInstances.push(engine);
@@ -693,6 +712,22 @@ describe("runServe", () => {
await triggerSignal("SIGINT");
});
it("passes remote-capable engine hooks into headless createServer for fn serve parity", async () => {
const { createServer } = await import("@fusion/dashboard");
await runServe(0, {});
expect(createServer).toHaveBeenCalledTimes(1);
const serverOptions = createServer.mock.calls[0][1];
expect(serverOptions).toMatchObject({ headless: true });
expect(serverOptions.engine).toBeDefined();
expect(typeof serverOptions.engine.startRemoteTunnel).toBe("function");
expect(typeof serverOptions.engine.stopRemoteTunnel).toBe("function");
expect(typeof serverOptions.engine.getRemoteTunnelManager).toBe("function");
await triggerSignal("SIGINT");
});
it("sets enginePaused when started with paused=true", async () => {
await runServe(0, { paused: true });

View File

@@ -471,6 +471,44 @@ describe("Settings view", () => {
unmount();
});
it("wires P/U remote actions to persistent token refresh and URL handoff state", async () => {
const controller = newController();
controller.setSystemInfo(makeSystemInfo());
const regeneratePersistentToken = vi.fn(async () => ({
maskedToken: "tok_****",
tokenType: "persistent" as const,
expiresAt: null,
}));
const getRemoteUrl = vi.fn(async () => ({
url: "https://remote.example.com/remote-login?rt=masked",
tokenType: "persistent" as const,
expiresAt: null,
}));
controller.setInteractiveData(makeInteractiveData({
remote: {
regeneratePersistentToken,
getRemoteUrl,
},
}));
controller.setMode("interactive");
controller.setInteractiveView("settings");
const { lastFrame, stdin, unmount } = render(renderDashboardAppNode(controller));
stdin.write("\t");
await new Promise((r) => setTimeout(r, 20));
stdin.write("P");
await waitForFrameContains(lastFrame, "Persistent token: tok_****");
expect(regeneratePersistentToken).toHaveBeenCalledTimes(1);
stdin.write("U");
await waitForFrameContains(lastFrame, "Auth URL: https://remote.example.com/remote-login?rt=masked");
expect(getRemoteUrl).toHaveBeenCalledWith("persistent", undefined);
unmount();
});
it("keeps global shortcuts inactive during TTL input", async () => {
const controller = newController();
controller.setSystemInfo(makeSystemInfo());