fix: design offline-first host-owned workspace table
Merged
KI
4mo ago+4785+4785+0123456789012345678901234567890123456789-1221-1221-0123456789012345678901234567890123456789
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/taskIdare 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/projectIdat create and the host rejects stale pins — dispatch already never reads the workspace table. - Open decisions: renderer read mechanism for ~25
useLiveQuerysites, fate of orphaned apps/web/workspacespages, host-side authz scoping, rollout/migration sequencing.
Test Plan
- Docs-only change; no runtime surface
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; newworkspace.list/workspace.update;workspace:changedevents; ensure‑main handles create races; memoizedhost.ensure; atomicrelinkLocalWorkspaceId; empty patches no‑op; PR branch updates flag rows for cloud sync. - Desktop:
useHostWorkspaces+HostWorkspacesProviderfan 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+v2ProjectIdwithv2WorkspaceId). - Automations: accept denormalized workspace pins; legacy cloud resolve remains until R3.
- CI:
scripts/check-cloud-workspace-usage.shblocks cloudv2Workspace.*inpackages/cliandpackages/sdk;packages/mcp-v2is exempt until R3 and flips later. - Docs: follow‑up plan added for hardening and the R3 cleanup.
- Host service: local‑first writes with a periodic reconciler; schema adds
-
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.
- Run
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.