feat(FN-2517): add remote access controls across dashboard and TUI

- Add project-scoped remote settings and control APIs for provider activation, tunnel lifecycle, token generation, URL, and QR retrieval
- Extend Settings modal with a dedicated Remote Access section, provider forms, status/actions, and coverage in SettingsModal tests
- Wire dashboard TUI settings state to remote configuration/status and add interactive remote shortcuts for start/stop/token/url/qr actions
- Document remote-access behavior in architecture, CLI, and settings references and include a patch changeset for @runfusion/fusion
This commit is contained in:
Fusion
2026-04-26 00:20:43 -07:00
committed by gsxdsm
parent 7bc8cf945f
commit 89c599abf6
12 changed files with 865 additions and 15 deletions

View File

@@ -350,6 +350,15 @@ Implemented in `agent-heartbeat.ts`:
- `NodeHealthMonitor` (`node-health-monitor.ts`) — remote node liveness/metrics checks
- `PeerExchangeService` (`peer-exchange-service.ts`) — peer sync orchestration
### Remote access runtime
- `remote-access/remote-access-manager.ts` supervises tunnel lifecycle with non-blocking child processes
- Provider adapters:
- `remote-access/providers/tailscale-adapter.ts` (`tailscale serve`, status probes)
- `remote-access/providers/cloudflare-adapter.ts` (`cloudflared tunnel run`, startup URL detection)
- Crash-safe lifecycle: graceful stop (`SIGTERM`), bounded wait, forced kill fallback (`SIGKILL`)
- Restore-on-start guardrails: only when remember-last-running is enabled and provider config/binaries are valid
- Short-lived token registry is in-memory and intentionally ephemeral (clears on process restart)
### Multi-runtime support + IPC
- Runtime contracts: `project-runtime.ts`
- Orchestration: `ProjectManager` and `HybridExecutor`
@@ -374,6 +383,7 @@ Implemented in `agent-heartbeat.ts`:
Key server capabilities:
- REST APIs for tasks, git, GitHub, agents, missions, planning, automations/routines, settings
- Remote access APIs (`/api/remote/*`) for provider config, activation, tunnel lifecycle, status, token issuance, authenticated URL generation, and QR payload generation
- Chat APIs (`/api/chat/*`) with streaming response support (`routes.ts`, `chat.ts`)
- Dev-server lifecycle + persistence APIs (`/api/dev-server/*`) backed by:
- `dev-server-routes.ts` (router factory + per-project runtime registry)
@@ -392,6 +402,7 @@ Key server capabilities:
- Dashboard/server runtime diagnostics use the shared `RuntimeLogger` contract (`packages/dashboard/src/runtime-logger.ts`) instead of ad hoc `console.*` calls.
- `createServer()` accepts `ServerOptions.runtimeLogger`; when omitted it defaults to a console-backed logger, preserving readable output in non-TTY/headless modes.
- CLI TTY dashboard sessions inject a logger backed by `DashboardLogSink`, so runtime diagnostics from server/routes are captured in the TUI log buffer.
- Sensitive remote-auth material is never logged raw; route/UI responses mask persistent token values unless explicitly requested by token-generation actions.
- Intentional startup/banner text in `fn dashboard` and `fn serve` remains direct plain output for readability and backward-compatible scripting behavior.
### Real-time channels

View File

@@ -76,15 +76,15 @@ fn dashboard --dev
### Interactive Terminal UI (TTY Mode)
When running in an interactive terminal (TTY), `fn dashboard` starts an
interactive TUI with five sections:
interactive TUI with sectioned views for system status, logs, settings, and
remote-access controls.
| Section | Description |
|---|---|
| **System** | Host, port, URL, auth mode, token, engine status, uptime |
| **Logs** | Real-time log entries with timestamps and severity levels |
| **Utilities** | Actions: refresh stats, clear logs, toggle engine pause |
| **Stats** | Task counts by column, active task count, agent state counts |
| **Settings** | Key settings from the task store |
Remote view/actions support:
- Switching active provider (`tailscale` / `cloudflare`)
- Manual tunnel lifecycle (`start` / `stop`)
- Persistent token regeneration
- Short-lived token URL generation (bounded TTL)
- QR hand-off (always includes the full authenticated URL)
On startup, the TUI opens on the **System** section by default so you can
immediately see host/port and access-token details.
@@ -204,6 +204,11 @@ fn serve --interactive
| `--interactive` | Interactive port selection. |
| `--daemon` | Enable bearer token authentication for CLI client connections. |
`fn serve` uses the same project-scoped Remote Access manager as `fn dashboard`.
When remote access is enabled/configured, the headless server exposes `/api/remote/*`
control/status endpoints and applies the same hybrid token validation rules for
remote routes (persistent token + optional short-lived token registry).
---
## `fn daemon`

View File

@@ -176,6 +176,34 @@ Defaults from `DEFAULT_PROJECT_SETTINGS`; key scope from `PROJECT_SETTINGS_KEYS`
| `showQuickChatFAB` | `boolean` | `false` | Show floating quick-chat button (chat remains available via More menu). |
| `experimentalFeatures` | `Record<string, boolean>` | `{}` | Project-scoped experimental feature flags. |
### Remote Access settings (project-scoped)
Remote access settings are project-only (stored in `.fusion/config.json`), not global.
| Setting | Type | Default | Description |
|---|---|---:|---|
| `remoteEnabled` | `boolean` | `false` | Master toggle for remote access orchestration. |
| `remoteActiveProvider` | `"tailscale" \| "cloudflare" \| null` | `null` | Currently selected provider. |
| `remoteTailscaleEnabled` | `boolean` | `false` | Enables Tailscale provider configuration. |
| `remoteTailscaleHostname` | `string` | `""` | Optional serve hostname label for Tailscale. |
| `remoteTailscaleTargetPort` | `number` | `4040` | Local port exposed by `tailscale serve`. |
| `remoteTailscaleAcceptRoutes` | `boolean` | `false` | Accept subnet routes when supported by local Tailscale config. |
| `remoteCloudflareEnabled` | `boolean` | `false` | Enables Cloudflare tunnel configuration. |
| `remoteCloudflareTunnelName` | `string` | `""` | Named tunnel identifier for `cloudflared tunnel run`. |
| `remoteCloudflareTunnelToken` | `string` | `null` | Tunnel token (stored in project config; masked by default in API/UI). |
| `remoteCloudflareIngressUrl` | `string` | `""` | Optional preferred public ingress URL for display. |
| `remotePersistentToken` | `string` | `null` | Persistent remote-auth token used for authenticated remote URLs. |
| `remoteShortLivedEnabled` | `boolean` | `false` | Enables short-lived token generation. |
| `remoteShortLivedTtlMs` | `number` | `900000` | Default short-lived token TTL in milliseconds (15 minutes). |
| `remoteShortLivedMaxTtlMs` | `number` | `86400000` | Maximum allowed short-lived token TTL (24 hours). |
| `remoteRememberLastRunning` | `boolean` | `false` | Restore prior running tunnel at startup when valid. |
| `remoteWasRunningOnShutdown` | `boolean` | `false` | Internal state flag persisted on shutdown. |
| `remoteLastStartedProvider` | `"tailscale" \| "cloudflare" \| null` | `null` | Internal last-known running provider for restore decisions. |
Short-lived token bounds are enforced server-side:
- Minimum TTL: `60_000` ms (60s)
- Maximum TTL: `86_400_000` ms (24h)
> **Note:** Agent `metadata.skills` is not a top-level project setting, but it is the primary mechanism for controlling execution-time skill selection. The engine's `buildSessionSkillContext` function reads this metadata from the assigned agent and uses it to resolve which skills are available in the agent session. If `metadata.skills` is absent or empty, the engine falls back to the built-in `fusion` skill.
---