feat(desktop,cli): host-owned sidebar sections (workspace groups)

Closed
YO
21d ago
+4929-449

Links

Summary

  • Sidebar sections ("workspace groups") move from desktop-local state to a host-owned sidebar_sections table on host-service, synced via a new sections tRPC router — so groups are visible to both the desktop app and the CLI, not just the machine that created them.
  • Existing local sidebar sections migrate automatically to host-owned storage on first launch (SidebarSectionsMigration, useMigrateSidebarSectionsToHost).
  • New CLI commands: workspaces groups create/add/remove/rename/delete/list/move and workspaces move.
  • CLI docs (apps/docs/content/docs/cli/cli-reference.mdx) updated with the new commands.

Why / Context

Sidebar groups previously lived only in the desktop app's local IndexedDB-backed state, so there was no way to see or manage them outside the desktop UI. Moving them to host-service (the same place workspace/PTY state already lives) makes them a first-class, host-owned concept the CLI can read and mutate directly — enabling scripted/automated workspace organization instead of drag-and-drop only.

How It Works

  • packages/host-service/src/db/schema.ts: new sidebar_sections SQLite table (id, project_id, name, color, tab_order), plus section_id/tab_order columns on workspaces.
  • packages/host-service/src/trpc/router/sections/: CRUD + moveWorkspace + reorderLane mutations, backed by sidebar-sections-store.ts.
  • packages/shared/src/sidebar-order.ts: shared tab-order comparison/insertion helpers used by host-service, CLI, and desktop so ordering logic isn't duplicated three times.
  • packages/cli/src/lib/host-sections/: resolves a group or workspace by name or id (scoped to a project when ambiguous) against a single host's client. Host selection itself is the caller's job — see the rebase note below.
  • Desktop: useDashboardSidebarState, useSidebarDnd, and the workspace/project context menus now read/write sections through the host instead of local Collections state; SidebarSectionsMigration runs once per host to backfill any pre-existing local sections.

Rebased onto the single-host CLI model

This branch was opened before #5885 ("single-host reads with explicit host targeting") and #5731 ("local-first projects") landed. Merging main in required reworking the CLI surface, so re-review the CLI commits rather than assuming the earlier review still applies:

  • listHostWorkspaces is gone. The org-wide fan-out this branch was built on was deleted upstream and replaced with the single-host workspacesOnHost.ts. listWorkspacesOnHost now also returns the host's sections (tolerating a NOT_FOUND sections router on an older host as "no groups").
  • Group commands take --host / --local, defaulting to this machine. They previously searched the org for the workspace's host. groups add/remove and workspaces move no longer derive the host — they follow the same convention as workspaces delete/update.
  • workspaces list drops the HOST column (the listing is single-host now) and keeps GROUP.
  • resolveProjectId reads the host's project.list instead of the retired cloud v2Project.list, so --project <name> resolves against host-owned projects.
  • Migration renumbered 0010 → 0012, since main took 0010/0011. Content is unchanged.
  • relinkLocalWorkspaceId and the workspace cloud-sync helpers were deleted upstream, so this branch's sectionId/tabOrder additions to them went away with them.

A follow-up commit also removed two duplicate code paths this branch had accumulated: an inline copy of the compareTopLevelItems tie-break in getFlattenedV2WorkspaceIds, and moveWorkspaceToSectionAtIndex, which lost its last caller when the DnD commit path moved to the batched reorderSectionMembers (one plan instead of N).

Manual QA

⚠️ Needs re-running. The checklist below passed against the pre-rebase fan-out CLI, which no longer exists — the commands still parse, but host resolution changed underneath them. Treating these as verified would be misleading, so they're unchecked pending a re-run against a local dev stack (./.superset/setup.local.sh + bun run dev):

  • workspaces groups create <name> --project <p> creates a group on this machine (and --host <id> targets another)
  • workspaces groups add <workspaceId> <group> moves a workspace in, sets sectionId + sequential tabOrder
  • workspaces groups list reports correct workspaceCount; workspaces list reports correct groupName per workspace
  • workspaces groups remove <workspaceId> moves a workspace back out (sectionId: null); no-op case returns a message instead of erroring
  • workspaces groups rename <group> <newName> renames without touching membership
  • workspaces groups delete <group> deletes the group and ungroups its members — members are not deleted
  • --project <name> resolves against the host's project list (not the retired cloud table)
  • sidebar_sections rows in host-service's local SQLite (host.db) match CLI output
  • Desktop UI: drag-and-drop create/reorder/collapse persistence and context-menu actions, against the post-merge sidebar (main restyled it and added project filter/sort in the meantime)

Testing

  • bun run lint — clean (5488 files)
  • bun run typecheck — 35/35 packages pass
  • bun run test — 14/14 task packages pass, 0 failures (measured directly: desktop 2297, host-service 910, shared 704, CLI 48)

Open in Stage

Summary by cubic

Make sidebar groups host-owned and synced across desktop and CLI. Adds a sections API with transactional reordering, shared ordering helpers, and CLI commands, plus a one-time migration from legacy local state.

  • New Features

    • Host service: sidebar_sections table; section_id/tab_order on workspaces; sections tRPC router (CRUD, reorderLane, moveWorkspace) with strict validation; section:changed event sends the full list; workspace list includes sectionId/tabOrder.
    • Desktop: sidebar reads/writes groups via host; DnD batches a single reorder plan (optimistic rollback offline); cross-host grouping blocked; old hosts fall back to persisted local tabOrder; create-then-move awaits create; delete preflights owner and sequences cross-host ungroup; sidebar ordering now uses @superset/shared/sidebar-order.
    • CLI: workspaces groups create/add/remove/rename/delete/list, workspaces groups move, and workspaces move; workspaces list shows GROUP; workspaces create supports --group and --after; UUID/name resolution is case-insensitive; old-host NOT_FOUND distinguished from transient failures.
    • Shared: @superset/shared sidebar-order helpers unify ordering and handle all-negative lanes; all surfaces use getNextTabOrder.
  • Migration

    • First launch per org runs SidebarSectionsMigration (useMigrateSidebarSectionsToHost) to move legacy local sections to host storage; marks complete only after every placement succeeds and skips already-adopted orgs.
    • Collapse state stays per-client via v2SectionUiState (not synced).

Summary by CodeRabbit

  • New Features
    • Added workspace groups in the desktop sidebar, including creation, renaming, color updates, deletion, collapsing, grouping, and reordering.
    • Added host-synced group data with offline snapshot support and live updates.
    • Added CLI commands to list, create, rename, delete, move, and manage workspace groups.
    • Workspace creation and listing now support group placement and group details.
  • Bug Fixes
    • Improved drag-and-drop ordering, cross-host validation, optimistic updates, rollback behavior, and workspace navigation.
    • Added migration of existing sidebar groups and preserved group membership during workspace removal.