Workspaces

The workspace IS the project: a named container with its own members, connections, shared files, history, and default target connection.

Status
current
Phase
7

This is an engineering document. Specs are written for people building DataGripe: they record what a subsystem does and why the alternatives were rejected, and some of them describe things that are not built yet. If you are using DataGripe, the documentation is the place to be — it is maintained for you and this is not.

Supersedes: nothing (extends docs/spec/auth-and-hardening.md, docs/spec/multiplayer.md)

Goal

The workspace IS the project: a named container with its own members, connections, shared files, history, and default target connection. Users create workspaces, switch between them, and keep private IndexedDB scratchpads that never sync.

Non-goals

  • A separate "project" concept (explicitly rejected — workspaces are it).
  • Per-workspace color themes or layout templates.
  • Workspace deletion/archival UI.

Model

Scope Contents
Workspace (server) members + roles, connections, shared documents, query history, default connection
Local (browser) scratchpads, drafts, per-workspace layouts, per-document connection picks

Switching

  • The socket binds to a workspace at upgrade (/ws?workspace=<id>), validated against workspace_members; an unknown/stale id falls back to the account's default workspace.
  • Switching reconnects the socket; every onOpen listener rescopes: connections reload, presence/explorer/executions reset, shared files re-sync, and the per-workspace layout (ws:<id> in IndexedDB) replaces the dock. Scratchpad editors stay open across switches.
  • The confirmed binding comes from workspace.open; the client treats it as the source of truth (confirmWorkspace).

Documents

  • Scratchpads (shared: false) live in IndexedDB only and appear in every workspace. They never hit the server — not even on save.
  • Workspace files (shared: true) are server rows shared with all members, synced on open and live via document.changed broadcasts (create/save/archive). Docs synced before the flag existed self-repair on next sync.
  • A broadcast skips the socket that caused it. The event is sent while the action is still running, so it reaches the sender before the response to their own save does: the sender saw a revision ahead of theirs while their document was still dirty, which is the definition of a conflict, and every shared save raised the banner against itself. The socket is identified by socketId rather than sessionId, so a second tab of the same session is still told. Everybody else needs the event; the sender has a better answer coming.
  • The sidebar shows "Workspace files" and "Scratchpads" as two roots of the one Files section, each with its own new (docs/spec/datasource-paths.md "What the sidebar shows"); the header has "New scratchpad" and "New shared file".

Default connection

workspaces.default_connection_ref (managed UUID or predefined:<slug>, migration 0007). The results toolbar falls back to it when a document has no explicit pick, labels it "workspace default", and editors can pin the current pick via workspace.set-default-connection (editor role and up).

Open questions

  • Title collisions across members — two people creating query-1.sql in the same second. A name is deduplicated against what the client can see (docs/spec/editor-workspace.md "Naming a document"), which is everything it has synced; two simultaneous creates are still two files with one name until somebody renames one.
  • Whether scratchpads should ever be promotable to shared files.

This page as Markdown, for an agent or a diff.