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:
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user