feat(FN-2585): remove top-level remote access toggle

- Remove the standalone remoteEnabled setting from CLI, core settings defaults/types, and dashboard settings APIs/UI
- Treat remote access as enabled when an active provider is selected and that provider is configured as enabled
- Update remote auth and engine lifecycle checks to gate on provider activation instead of a global flag
- Adjust tests and add a changeset documenting the remote access configuration simplification
This commit is contained in:
Fusion
2026-04-26 09:19:03 -07:00
committed by gsxdsm
parent e89fc73bd7
commit 70fe99f936
19 changed files with 26 additions and 57 deletions

View File

@@ -34,7 +34,7 @@ function makeInteractiveData(opts: {
models?: ModelItem[];
taskDetail?: TaskDetailData | null;
remote?: Partial<{
getSettings: () => Promise<{ remoteEnabled: boolean; activeProvider: "tailscale" | "cloudflare" | null; tailscaleEnabled: boolean; cloudflareEnabled: boolean; shortLivedEnabled: boolean; shortLivedTtlMs: number }>;
getSettings: () => Promise<{ activeProvider: "tailscale" | "cloudflare" | null; tailscaleEnabled: boolean; cloudflareEnabled: boolean; shortLivedEnabled: boolean; shortLivedTtlMs: number }>;
getStatus: () => Promise<{ provider: "tailscale" | "cloudflare" | null; state: "stopped" | "starting" | "running" | "error"; url: string | null; lastError: string | null }>;
activateProvider: (provider: "tailscale" | "cloudflare") => Promise<void>;
startTunnel: () => Promise<void>;
@@ -58,7 +58,6 @@ function makeInteractiveData(opts: {
pollIntervalMs: 60000,
enginePaused: false,
globalPause: false,
remoteEnabled: false,
remoteActiveProvider: null,
remoteShortLivedEnabled: false,
remoteShortLivedTtlMs: 900000,
@@ -66,7 +65,6 @@ function makeInteractiveData(opts: {
const models = opts.models ?? [];
const remoteDefaults = {
getSettings: async () => ({
remoteEnabled: settings.remoteEnabled,
activeProvider: settings.remoteActiveProvider,
tailscaleEnabled: true,
cloudflareEnabled: true,
@@ -353,7 +351,6 @@ describe("Settings view", () => {
pollIntervalMs: 60000,
enginePaused: false,
globalPause: false,
remoteEnabled: true,
remoteActiveProvider: "tailscale",
remoteShortLivedEnabled: true,
remoteShortLivedTtlMs: 600000,
@@ -401,7 +398,6 @@ describe("Settings view", () => {
pollIntervalMs: 60000,
enginePaused: false,
globalPause: false,
remoteEnabled: true,
remoteActiveProvider: "cloudflare",
remoteShortLivedEnabled: true,
remoteShortLivedTtlMs: 600000,

View File

@@ -448,7 +448,6 @@ function SettingsPanel({ state, isFocused }: { state: DashboardState; isFocused:
["pollMs", `${s.pollIntervalMs}`],
["paused", s.enginePaused ? "yes" : "no"],
["globalPause", s.globalPause ? "yes" : "no"],
["remoteEnabled", s.remoteEnabled ? "enabled" : "disabled"],
["remoteProvider", s.remoteActiveProvider ?? "none"],
["remoteState", s.remoteStatus?.state ?? "unknown"],
] as Array<[string, string]>
@@ -2105,7 +2104,7 @@ function AgentsView({ state }: { state: DashboardState }) {
// ── Settings interactive view ─────────────────────────────────────────────────
type SettingKey = "maxConcurrent" | "maxWorktrees" | "autoMerge" | "mergeStrategy" | "pollIntervalMs" | "enginePaused" | "globalPause" | "remoteEnabled" | "remoteActiveProvider" | "remoteShortLivedEnabled" | "remoteShortLivedTtlMs";
type SettingKey = "maxConcurrent" | "maxWorktrees" | "autoMerge" | "mergeStrategy" | "pollIntervalMs" | "enginePaused" | "globalPause" | "remoteActiveProvider" | "remoteShortLivedEnabled" | "remoteShortLivedTtlMs";
interface SettingDef {
key: SettingKey;
@@ -2122,7 +2121,6 @@ const SETTING_DEFS: SettingDef[] = [
{ key: "pollIntervalMs", label: "Poll Interval (ms)", type: "number" },
{ key: "enginePaused", label: "Engine Paused", type: "boolean" },
{ key: "globalPause", label: "Global Pause", type: "boolean" },
{ key: "remoteEnabled", label: "Remote Access", type: "boolean" },
{ key: "remoteActiveProvider", label: "Remote Provider", type: "enum", options: ["tailscale", "cloudflare"] },
{ key: "remoteShortLivedEnabled", label: "Short-Lived Tokens", type: "boolean" },
{ key: "remoteShortLivedTtlMs", label: "Short-Lived TTL (ms)", type: "number" },
@@ -2513,8 +2511,6 @@ function SettingsInteractiveView({ state, controller }: { state: DashboardState;
<Text color={localSettings.remoteStatus?.state === "running" ? "green" : "yellow"}>{localSettings.remoteStatus?.state ?? "unknown"}</Text>
</Box>
<Box flexDirection="row" gap={1}>
<Text dimColor>Enabled:</Text>
<Text>{localSettings.remoteSettingsSnapshot?.remoteEnabled ? "yes" : "no"}</Text>
<Text dimColor>Short-lived:</Text>
<Text>{localSettings.remoteSettingsSnapshot?.shortLivedEnabled ? "on" : "off"}</Text>
</Box>

View File

@@ -75,7 +75,6 @@ export interface RemoteQrPayload {
}
export interface RemoteSettingsSnapshot {
remoteEnabled: boolean;
activeProvider: RemoteProvider | null;
tailscaleEnabled: boolean;
cloudflareEnabled: boolean;
@@ -91,7 +90,6 @@ export interface SettingsValues {
pollIntervalMs: number;
enginePaused: boolean;
globalPause: boolean;
remoteEnabled: boolean;
remoteActiveProvider: RemoteProvider | null;
remoteShortLivedEnabled: boolean;
remoteShortLivedTtlMs: number;

View File

@@ -722,7 +722,6 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
pollIntervalMs: fullSettings.pollIntervalMs ?? 60_000,
enginePaused: fullSettings.enginePaused ?? false,
globalPause: fullSettings.globalPause ?? false,
remoteEnabled: Boolean(fullSettings.remoteEnabled),
remoteActiveProvider: (fullSettings.remoteActiveProvider as "tailscale" | "cloudflare" | null) ?? null,
remoteShortLivedEnabled: Boolean(fullSettings.remoteShortLivedEnabled),
remoteShortLivedTtlMs: Number(fullSettings.remoteShortLivedTtlMs ?? 900_000),
@@ -736,7 +735,6 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
pollIntervalMs: 60_000,
enginePaused: paused,
globalPause: false,
remoteEnabled: false,
remoteActiveProvider: null,
remoteShortLivedEnabled: false,
remoteShortLivedTtlMs: 900_000,
@@ -874,7 +872,6 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
pollIntervalMs: settings.pollIntervalMs ?? 60_000,
enginePaused: settings.enginePaused ?? false,
globalPause: settings.globalPause ?? false,
remoteEnabled: Boolean(settings.remoteEnabled),
remoteActiveProvider: (settings.remoteActiveProvider as "tailscale" | "cloudflare" | null) ?? null,
remoteShortLivedEnabled: Boolean(settings.remoteShortLivedEnabled),
remoteShortLivedTtlMs: Number(settings.remoteShortLivedTtlMs ?? 900_000),
@@ -1846,7 +1843,6 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
pollIntervalMs: settings.pollIntervalMs ?? 60_000,
enginePaused: settings.enginePaused ?? false,
globalPause: settings.globalPause ?? false,
remoteEnabled: Boolean(settings.remoteEnabled),
remoteActiveProvider: (settings.remoteActiveProvider as "tailscale" | "cloudflare" | null) ?? null,
remoteShortLivedEnabled: Boolean(settings.remoteShortLivedEnabled),
remoteShortLivedTtlMs: Number(settings.remoteShortLivedTtlMs ?? 900_000),
@@ -1986,12 +1982,10 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
pollIntervalMs: s.pollIntervalMs ?? 60_000,
enginePaused: s.enginePaused ?? false,
globalPause: s.globalPause ?? false,
remoteEnabled: Boolean(s.remoteEnabled),
remoteActiveProvider: (s.remoteActiveProvider as "tailscale" | "cloudflare" | null) ?? null,
remoteShortLivedEnabled: Boolean(s.remoteShortLivedEnabled),
remoteShortLivedTtlMs: Number(s.remoteShortLivedTtlMs ?? 900_000),
remoteSettingsSnapshot: {
remoteEnabled: Boolean(s.remoteEnabled),
activeProvider: (s.remoteActiveProvider as "tailscale" | "cloudflare" | null) ?? null,
tailscaleEnabled: Boolean(s.remoteTailscaleEnabled),
cloudflareEnabled: Boolean(s.remoteCloudflareEnabled),
@@ -2010,7 +2004,6 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
if (partial.pollIntervalMs !== undefined) mapped.pollIntervalMs = partial.pollIntervalMs;
if (partial.enginePaused !== undefined) mapped.enginePaused = partial.enginePaused;
if (partial.globalPause !== undefined) mapped.globalPause = partial.globalPause;
if (partial.remoteEnabled !== undefined) mapped.remoteEnabled = partial.remoteEnabled;
if (partial.remoteActiveProvider !== undefined) mapped.remoteActiveProvider = partial.remoteActiveProvider;
if (partial.remoteShortLivedEnabled !== undefined) mapped.remoteShortLivedEnabled = partial.remoteShortLivedEnabled;
if (partial.remoteShortLivedTtlMs !== undefined) mapped.remoteShortLivedTtlMs = partial.remoteShortLivedTtlMs;
@@ -2037,7 +2030,6 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
}
const payload = await response.json();
return {
remoteEnabled: Boolean(payload?.settings?.remoteEnabled),
activeProvider: (payload?.settings?.remoteActiveProvider as "tailscale" | "cloudflare" | null) ?? null,
tailscaleEnabled: Boolean(payload?.settings?.remoteTailscaleEnabled),
cloudflareEnabled: Boolean(payload?.settings?.remoteCloudflareEnabled),