fix: design offline-first host-owned workspace table

Merged
KI
4mo ago
+4785-1221

Summary

Design audit + decision log for moving v2_workspaces authority from Neon to the host-service local table (host.db), making workspaces offline-first by design. Doc at plans/20260703-offline-first-workspace-table.md.

  • Audit: maps the three workspace tables, current read/write flows (Electric shapes, optimistic collection writes, host-service cloud calls), and why writes are the offline blocker (synchronous cloud round-trips, cloud-minted IDs).
  • Cloud usage inventory: every consumer of the cloud table and its deprecation path — notably apps/api and apps/mobile have zero references, and chat_sessions.v2WorkspaceId / taskId are write-only tags never read cloud-side.
  • Decisions so far: (1) host-service owns workspaces outright, no cloud table usage; (2) cross-host visibility via renderer fan-out to hosts (local direct, remote via relay) with last-seen caching; (3) automations denormalize hostId/projectId at create and the host rejects stale pins — dispatch already never reads the workspace table.
  • Open decisions: renderer read mechanism for ~25 useLiveQuery sites, fate of orphaned apps/web /workspaces pages, host-side authz scoping, rollout/migration sequencing.

Test Plan

  • Docs-only change; no runtime surface

Open in Stage

Summary by cubic

Make workspaces offline‑first by moving authority to the host‑owned workspaces table. Desktop now reads via per‑host fan‑out with live events and offline snapshots; all writes route to the owning host with cloud dual‑write.

  • New Features

    • Host service: local‑first writes with a periodic reconciler; schema adds name, type, task_id, created_by_user_id, updated_at, cloud_synced_at, and a one‑main‑per‑project index; startup backfill is fill‑only; new workspace.list/workspace.update; workspace:changed events; ensure‑main handles create races; memoized host.ensure; atomic relinkLocalWorkspaceId; empty patches no‑op; PR branch updates flag rows for cloud sync.
    • Desktop: useHostWorkspaces + HostWorkspacesProvider fan out to hosts (local direct, remote via relay), patch via events, and persist snapshots in IndexedDB; readers moved off Electric with its view as a read‑only fallback; mutations route to the owning host with optimistic UI; networkMode “always”, background refetch, and bounded retries fix offline empty‑state and readiness hangs.
    • CLI/SDK: list/update/delete/open/terminal/agent resolve the owning host by fanning out across reachable hosts and route to that host; warn on unreachable hosts; CLI lists fall back to the local manifest if cloud discovery fails; SDK workspaces/terminals/agents updated and docs advise sending the denormalized pin (targetHostId + v2ProjectId with v2WorkspaceId).
    • Automations: accept denormalized workspace pins; legacy cloud resolve remains until R3.
    • CI: scripts/check-cloud-workspace-usage.sh blocks cloud v2Workspace.* in packages/cli and packages/sdk; packages/mcp-v2 is exempt until R3 and flips later.
    • Docs: follow‑up plan added for hardening and the R3 cleanup.
  • Migration

    • Run 0008_workspace_full_fields; run the startup backfill while the cloud table exists (fill‑only).
    • Dual‑write: local ops are never blocked; the reconciler later pushes pending changes and tombstoned deletes with CAS mark‑synced.
    • Desktop reads host‑first with IndexedDB snapshots and falls back to the Electric view; no Electron‑main IPC changes.
    • Rollout: R1+R2 ship together; R3 removes cloud v2Workspace.* endpoints and flips MCP to fan‑out.

Summary by CodeRabbit

  • Documentation
    • Added an offline-first workspace v2 design note describing the shift of workspace authority to host-service, including host-backed list merging and persisted per-host caching for restarts.
    • Documented the staged migration approach (read-through fallback, host-service–driven create/rename/update/delete, and reconnect behavior) along with required workspace:* event updates.
    • Added an ExecPlan outlining rollout milestones (R1–R3), including migration sequencing and the eventual removal of cloud workspace surfaces and related pages.