Files
fusion/packages/dashboard/src/routes
Fusion fff18ea313 feat(FN-3282): add durable review addressing snapshots
This merge adds two substantial features: a rooms and chat sidebar system (FN-3806) with a new `CreateRoomModal` and enriched `ChatView`, wired through plugin routes and a new `listTasksModifiedSince` core API; and a durable review addressing workflow (FN-3282) that persists snapshots, renders addre

Fusion-Task-Id: FN-3282
2026-05-09 10:31:05 -07:00
..
2026-04-26 18:11:09 -07:00
2026-04-26 18:11:09 -07:00

Dashboard API route registrars

packages/dashboard/src/routes.ts remains the single public entrypoint (createApiRoutes(store, options)), but route definitions are registered by domain modules in this directory.

Shared context contract

All registrars receive ApiRoutesContext from ./types.ts, built by createApiRoutesContext() in ./context.ts.

Registrars should be typed as ApiRouteRegistrar so modules share one explicit registration contract.

The context centralizes cross-cutting dependencies so registrars preserve behavior without re-implementing plumbing.

Some registrars (for example register-task-workflow-routes.ts) also take a narrow dependency-injection object for non-context helpers that must stay source-of-truth in routes.ts (git helpers, background refresh helpers, multer upload middleware). This avoids helper duplication while preserving runtime parity.

The context provides core cross-cutting plumbing:

  • Request/project scoping: getProjectIdFromRequest, getScopedStore, getProjectContext
    • These are also exported from context.ts as canonical helpers for future extraction tasks.
  • Engine-aware fallback behavior for project-bound and root-store APIs
  • Runtime loggers and diagnostics emitters (runtimeLogger, planningLogger, chatLogger)
  • Proxy/auth/audit helpers (emitRemoteRouteDiagnostic, emitAuthSyncAuditLog)
  • Automation/routine resolvers and scope parsing helpers
  • Shared error normalization (rethrowAsApiError)

Registrar module map

  • register-settings-memory-routes.ts — settings APIs and memory backend/file/insight routes (excluding node-to-node sync endpoints)
  • register-project-routes.ts/projects CRUD + /projects/across-nodes, /projects/detect, health/config/pause/resume routes
  • register-node-routes.ts/nodes CRUD + operational endpoints (/health-check, /metrics, /version, /sync-plugins, /compatibility)
  • register-settings-sync-routes.ts — node settings/auth sync routes (/nodes/:id/settings*, /nodes/:id/auth/sync)
  • register-mesh-routes.ts — mesh topology routes (/mesh/state, /mesh/sync)
  • register-discovery-routes.ts — discovery routes (/discovery/status|start|stop|nodes|connect) with options?.centralCore reuse
  • register-settings-sync-inbound-routes.ts — inbound sync/auth endpoints (/settings/sync-receive, /settings/auth-receive, /settings/auth-export)
  • register-settings-sync-helpers.ts — shared sync-domain helpers (fetchFromRemoteNode, readStoredAuthProvidersFromDisk)
  • register-task-workflow-routes.ts — task/workflow domain (/tasks*, /documents, task comments/docs/checkout/spec/attachments, PR+issue status, task lifecycle/workflow endpoints)
  • register-planning-subtask-routes.ts — planning sessions and subtask breakdown routes
  • register-chat-routes.ts — chat session/list/mutation/stream routes
  • register-messaging-scripts.ts — scripts API and mailbox/message routes
  • register-git-github.ts — git/GitHub workflows and related helpers
    • Git plumbing routes: /git/remotes*, /git/status, /git/commits*, /git/branches*, /git/worktrees, /git/fetch|pull|push, /git/stashes*, /git/diff*, /git/changes, /git/stage|unstage|commit|discard
    • GitHub import/integration routes: /github/issues/*, /github/pulls/*, /github/webhooks, /github/batch/status (includes shared batch-import rate limiter state + reset export)
    • Task-scoped GitHub routes: /tasks/:id/pr/* and /tasks/:id/issue/* status/refresh/create flows
  • register-model-routes.ts/models endpoint, favorites projection, and useClaudeCli filtering for pi-claude-cli entries
  • register-auth-routes.ts — auth/provider domain (/auth/status, /auth/login, /auth/logout, /auth/api-key, /auth/claude-cli, /providers/claude-cli/status)
  • register-usage-routes.ts/usage endpoint with fetchAllProviderUsage(options?.authStorage) integration
  • register-files-terminal-workspaces.ts — infrastructure aggregator for file/workspace + session-diff + terminal routes
    • Calls register-session-diff-routes.ts first (session changed files + task diff endpoints)
    • Calls register-file-workspace-routes.ts second (task/workspace file browsing and file operations)
    • Calls register-terminal-routes.ts last (terminal command/session + PTY lifecycle endpoints)
  • register-file-workspace-routes.ts — task/workspace file domain:
    • Task files: /tasks/:id/files, /tasks/:id/files/{*filepath} (read/write)
    • Workspace discovery/files: /workspaces, /files, /files/markdown-list, /files/search, /files/{*filepath}
    • File operations: /files/{*filepath}/copy|move|delete|rename, /files/{*filepath}/download, /files/{*filepath}/download-zip
    • Generic wildcard write: /files/{*filepath} (must remain after operation routes)
    • Project markdown search: /project-files/md
  • register-session-diff-routes.ts — task session/diff domain:
    • Session changed-file list: /tasks/:id/session-files
    • Aggregate task diff: /tasks/:id/diff
    • Per-file diffs: /tasks/:id/file-diffs
    • Caches: module-level sessionFilesCache and fileDiffsCache (10-second TTL)
  • resolve-diff-base.ts — shared git diff-base utilities:
    • runGitCommand(args, cwd, timeoutMs)
    • resolveDiffBase(task, cwd) + ResolveDiffBaseTaskInput type
  • register-terminal-routes.ts — terminal execution and PTY endpoints:
    • Command execution + streaming: /terminal/exec, /terminal/sessions/:id, /terminal/sessions/:id/stream, /terminal/sessions/:id/kill
    • PTY lifecycle: /terminal/sessions (create/list) and /terminal/sessions/:id (delete)
  • register-agent-core-routes.ts — core agent CRUD, lookups, stats/org-tree, hierarchy aliases (/agents/:id/children|employees)
  • register-agent-runtime-routes.ts — agent runtime/control-plane, heartbeats/runs, access/permissions, soul/memory, revisions/budget/keys, task/inbox surfaces
  • register-agent-reflection-rating-routes.ts — reflection/performance/context endpoints and ratings APIs
  • register-agent-import-export-generation-routes.ts — agent import/export, companies catalog, and /agents/generate/* session/spec lifecycle
  • register-agent-skills-routes.ts — skills discovery/content/execution/catalog endpoints coupled to agent capability flow
  • register-plugins-automation.ts — plugin CRUD, automation, routines/webhooks
  • register-proxy-routes.ts — remote-node proxy forwarding and SSE proxy routes
    • Injected dependencies: { store, runtimeLogger }
    • Endpoint inventory (must remain in this order):
      1. GET /proxy/:nodeId/health
      2. GET /proxy/:nodeId/projects
      3. GET /proxy/:nodeId/tasks
      4. GET /proxy/:nodeId/project-health
      5. GET /proxy/:nodeId/events (SSE pass-through, 30s timeout, client-disconnect cleanup)
      6. ALL /proxy/:nodeId/{*splat} (generic wildcard forwarder)
    • Shared diagnostics: imports emitRemoteRouteDiagnostic and classifyRemoteRouteError from routes/context.ts so proxy and non-proxy registrars (for example mesh/sync routes) keep one diagnostic classification contract.

createApiRoutes mount sequence (current)

createApiRoutes() mounts registrars in this precedence-sensitive order:

  1. registerSettingsMemoryRoutes(...)
  2. registerTaskWorkflowRoutes(...)
  3. registerPlanningSubtaskRoutes(...)
  4. registerChatRoutes(...)
  5. registerMessagingScriptRoutes(...)
  6. registerGitGitHubRoutes(...)
  7. registerFilesTerminalWorkspaceRoutes(...)
  8. registerAgentsProjectsNodesRoutes(...)
  9. registerPluginsAutomationRoutes(...)
  10. (later) registerAgentSkillsRoutes(...)
  11. (last) registerProxyRoutes(...)

Compatibility re-exports that must remain on routes.ts for tests and existing importers:

  • resolveDiffBase + ResolveDiffBaseTaskInput (from resolve-diff-base.ts)
  • __resetBatchImportRateLimiter (from register-git-github.ts)
  • __setCreateFnAgentForRefine (defined in routes.ts)

Ordering rules (critical)

Express matches in registration order. Keep registrar and in-registrar route ordering stable:

  1. Specific operation routes before generic parameterized routes (/runs, /runs/:id, /copy, /delete before /:id style handlers)
  2. Specific operation routes before wildcard paths (/files/{*filepath}/copy|move|delete|rename|download|download-zip before POST /files/{*filepath})
    • Why: Express route matching is first-win. If the wildcard write route is registered first, paths like /files/somefolder/delete will be treated as file writes instead of delete operations.
  3. Do not move proxy/script/message/file wildcards ahead of specific routes
    • For proxy routes specifically, keep all explicit GET /proxy/:nodeId/* handlers ahead of ALL /proxy/:nodeId/{*splat} and keep proxy registration last in createApiRoutes().
  4. Project/node/sync/discovery ordering constraints must stay intact:
    • /projects/across-nodes and /projects/detect must be registered before /projects/:id
    • /nodes/:id/settings must be registered before /nodes/:id/settings/push|pull|sync-status and before /nodes/:id/auth/sync
    • /mesh/state must be registered before /mesh/sync
    • Discovery routes stay grouped after mesh routes
    • Inbound /settings/sync-receive|auth-receive|auth-export routes mount after discovery routes
  5. Auth/model/usage ordering constraints must stay intact:
    • Keep /models registration before auth-dependent picker/settings flows that rely on consistent model filtering
    • Keep auth registrar routes grouped as currently mounted (status/diagnostic + mutation endpoints) so no wildcard handler can shadow /providers/claude-cli/status
    • Keep /usage mounted as a standalone registrar route (not under auth paths) with unchanged error mapping semantics
  6. Agent ordering constraints must stay intact:
    • /agents/stats, /agents/org-tree, /agents/resolve/:shortname before /agents/:id
    • /agents/:id/runs/stop before /agents/:id/runs/:runId
    • /agents/:id/reflections/latest before /agents/:id/reflections

If adding a new endpoint, place it in the domain registrar and verify it does not shadow existing handlers.

Integrated routers

Integrated routers are mounted through register-integrated-routers.ts and intentionally called from routes.ts at precedence-sensitive points:

  • registerIntegratedRouters(...) mounts:
    • createMissionRouter/api/missions
    • createInsightsRouter/api/insights
    • createTodoRouter/api/todos
  • Roadmap endpoints are plugin-owned and exposed under /api/plugins/roadmap-planner/....
  • registerIntegratedDevServerRouter(...) mounts:
    • createDevServerRouter/api/dev-server

Keep these calls in their current positions inside createApiRoutes() unless an explicit route-ordering migration is planned and regression-tested.