Cosmo Docs
Server

Workspace Sync Module

File sync, blob storage, and SSE change feed

The Workspace Sync module provides cloud storage for all content files (profiles, onboarding data, memory, artifacts) and a real-time SSE change feed. Source: packages/server/src/modules/workspace-sync/.

REST Endpoints

All endpoints are prefixed with /api/v1/sync and require ClerkAuthGuard.

Profile & Onboarding

MethodPathDescription
PUT/sync/profileStore user profile JSON
GET/sync/profileRetrieve user profile JSON
PUT/sync/org-onboardingStore org onboarding JSON
GET/sync/org-onboardingRetrieve org onboarding JSON

Memory

MethodPathDescription
PUT/sync/memory/:scopeStore memory (scope: user or org)
GET/sync/memory/:scopeRetrieve memory
PUT/sync/memory/workspace/:workspaceId/:fileNameStore workspace memory file
GET/sync/memory/workspace/:workspaceId/:fileNameGet workspace memory file
GET/sync/memory/workspace/:workspaceIdList workspace memory files

Files (General)

MethodPathDescription
POST/sync/filesUpload a file
GET/sync/files/:idDownload file content
GET/sync/filesList files (with filters)
DELETE/sync/files/:idDelete a file
PUT/sync/files/:idUpdate file content

Query params for GET /sync/files:

ParamDescription
kindStorageKind filter
scopeSHARED or PERSONAL
workspaceIdFilter by workspace
prefixKey prefix filter

Manifest & Changes

MethodPathDescription
GET/sync/manifestGet metadata index for the whole org
GET/sync/changesSSE change feed

Workspace Sync Service (services/workspace-sync.service.ts)

Storage Layout

All blobs are stored in R2/S3 under an org-scoped path:

/{orgId}/shared/hub-memory/          ← Org-level AI memory
/{orgId}/shared/brand/               ← Logos, icons
/{orgId}/shared/templates/           ← Shared templates
/{orgId}/teams/{teamId}/memory/      ← Team memory files
/{orgId}/workspaces/{workspaceId}/   ← Workspace artifacts + memory
/{orgId}/personal/{userId}/          ← Personal files + user memory

Profile & Onboarding Methods

MethodDescription
putUserProfile(orgId, userId, data)Write profile.json to personal scope
getUserProfile(orgId, userId)Read profile.json; returns parsed object or null
putOrgOnboarding(orgId, data, userId)Write org.json to shared scope
getOrgOnboarding(orgId)Read org.json; returns parsed object or null

Memory Methods

MethodDescription
putMemory(orgId, userId, scope, content)Store user-memory.md or org-memory.md
getMemory(orgId, userId, scope)Retrieve memory file content
putWorkspaceMemory(orgId, workspaceId, fileName, content, userId)Store named file in workspace memory dir
getWorkspaceMemory(orgId, workspaceId, fileName)Retrieve workspace memory file
mergeWorkspaceMemory(orgId, workspaceId, fileName, content, userId, expectedVersion)Merge with optimistic version check; throws 409 on conflict
listWorkspaceMemory(orgId, workspaceId)List all memory files in workspace

File Methods

MethodDescription
putFile(orgId, blobPath, buffer, mimeType, metadata)Upload blob + create StorageObject metadata record
getFile(orgId, id)Returns { body: Buffer, metadata: StorageObject }
deleteFile(orgId, id, userId)Remove blob + delete metadata record
listFiles(orgId, filters)Query StorageObject table with optional filters
updateFile(orgId, id, buffer, userId)Replace blob + bump version + update checksum

Manifest

getManifest(orgId) returns an array of all StorageObject metadata records for the org. Used by the desktop client to detect stale local files without downloading them.

SSE Change Feed

GET /api/v1/sync/changes opens a Server-Sent Events connection.

  • Server sends a heartbeat comment every 30 seconds to keep the connection alive through proxies.
  • When any file changes (via putFile, deleteFile, updateFile, putMemory, etc.), the service calls notifyChange(orgId, event).
  • All connected clients for that orgId receive the event.

Change event structure:

{
  type: 'file-changed' | 'file-deleted';
  storageKey: string;    // R2/S3 key
  path: string;          // Logical path
  checksum?: string;     // SHA-256 (on change)
  version?: number;      // New version number
  changedBy?: string;    // userId who made the change
  timestamp: string;     // ISO timestamp
}

Storage Kinds

KindDescription
ARTIFACTAI-generated documents, reports, dashboards
HUB_MEMORYOrg-level AI memory
TEAM_MEMORYTeam-scoped AI memory
WORKSPACE_MEMORYWorkspace-scoped AI memory
TEMPLATEReusable templates
BRAND_ASSETLogos, icons, brand images

Storage Scopes

ScopeDescription
SHAREDVisible to all team members
PERSONALVisible only to the owning user

Blob Storage Provider (services/blob-storage.provider.ts)

Wraps the R2/S3 SDK with a consistent interface:

MethodDescription
getBlob(key)Download a blob by key
putBlob(key, body, metadata)Upload a blob
deleteBlob(key)Delete a blob
listBlobs(prefix)List blobs under a prefix
headBlob(key)Get blob metadata without downloading