// Mosaic Stack Database Schema // PostgreSQL 17 with pgvector extension generator client { provider = "prisma-client-js" previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") extensions = [pgvector(map: "vector"), uuid_ossp(map: "uuid-ossp")] } // ============================================ // ENUMS // ============================================ enum TaskStatus { NOT_STARTED IN_PROGRESS PAUSED COMPLETED ARCHIVED } enum TaskPriority { LOW MEDIUM HIGH } enum ProjectStatus { PLANNING ACTIVE PAUSED COMPLETED ARCHIVED } enum WorkspaceMemberRole { OWNER ADMIN MEMBER GUEST } enum ActivityAction { CREATED UPDATED DELETED COMPLETED ASSIGNED COMMENTED } enum EntityType { TASK EVENT PROJECT WORKSPACE USER } // ============================================ // MODELS // ============================================ model User { id String @id @default(uuid()) @db.Uuid email String @unique name String authProviderId String? @unique @map("auth_provider_id") preferences Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz // Relations ownedWorkspaces Workspace[] @relation("WorkspaceOwner") workspaceMemberships WorkspaceMember[] assignedTasks Task[] @relation("TaskAssignee") createdTasks Task[] @relation("TaskCreator") createdEvents Event[] @relation("EventCreator") createdProjects Project[] @relation("ProjectCreator") activityLogs ActivityLog[] @@map("users") } model Workspace { id String @id @default(uuid()) @db.Uuid name String ownerId String @map("owner_id") @db.Uuid settings Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz // Relations owner User @relation("WorkspaceOwner", fields: [ownerId], references: [id], onDelete: Cascade) members WorkspaceMember[] tasks Task[] events Event[] projects Project[] activityLogs ActivityLog[] memoryEmbeddings MemoryEmbedding[] @@index([ownerId]) @@map("workspaces") } model WorkspaceMember { workspaceId String @map("workspace_id") @db.Uuid userId String @map("user_id") @db.Uuid role WorkspaceMemberRole @default(MEMBER) joinedAt DateTime @default(now()) @map("joined_at") @db.Timestamptz // Relations workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@id([workspaceId, userId]) @@index([userId]) @@map("workspace_members") } model Task { id String @id @default(uuid()) @db.Uuid workspaceId String @map("workspace_id") @db.Uuid title String description String? @db.Text status TaskStatus @default(NOT_STARTED) priority TaskPriority @default(MEDIUM) dueDate DateTime? @map("due_date") @db.Timestamptz assigneeId String? @map("assignee_id") @db.Uuid creatorId String @map("creator_id") @db.Uuid projectId String? @map("project_id") @db.Uuid parentId String? @map("parent_id") @db.Uuid sortOrder Int @default(0) @map("sort_order") metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz completedAt DateTime? @map("completed_at") @db.Timestamptz // Relations workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) assignee User? @relation("TaskAssignee", fields: [assigneeId], references: [id], onDelete: SetNull) creator User @relation("TaskCreator", fields: [creatorId], references: [id], onDelete: Cascade) project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull) parent Task? @relation("TaskSubtasks", fields: [parentId], references: [id], onDelete: Cascade) subtasks Task[] @relation("TaskSubtasks") @@index([workspaceId]) @@index([workspaceId, status]) @@index([workspaceId, dueDate]) @@index([assigneeId]) @@index([projectId]) @@index([parentId]) @@map("tasks") } model Event { id String @id @default(uuid()) @db.Uuid workspaceId String @map("workspace_id") @db.Uuid title String description String? @db.Text startTime DateTime @map("start_time") @db.Timestamptz endTime DateTime? @map("end_time") @db.Timestamptz allDay Boolean @default(false) @map("all_day") location String? recurrence Json? creatorId String @map("creator_id") @db.Uuid projectId String? @map("project_id") @db.Uuid metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz // Relations workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) creator User @relation("EventCreator", fields: [creatorId], references: [id], onDelete: Cascade) project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull) @@index([workspaceId]) @@index([workspaceId, startTime]) @@index([creatorId]) @@index([projectId]) @@map("events") } model Project { id String @id @default(uuid()) @db.Uuid workspaceId String @map("workspace_id") @db.Uuid name String description String? @db.Text status ProjectStatus @default(PLANNING) startDate DateTime? @map("start_date") @db.Date endDate DateTime? @map("end_date") @db.Date creatorId String @map("creator_id") @db.Uuid color String? metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz // Relations workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) creator User @relation("ProjectCreator", fields: [creatorId], references: [id], onDelete: Cascade) tasks Task[] events Event[] @@index([workspaceId]) @@index([workspaceId, status]) @@index([creatorId]) @@map("projects") } model ActivityLog { id String @id @default(uuid()) @db.Uuid workspaceId String @map("workspace_id") @db.Uuid userId String @map("user_id") @db.Uuid action ActivityAction entityType EntityType @map("entity_type") entityId String @map("entity_id") @db.Uuid details Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz // Relations workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([workspaceId]) @@index([workspaceId, createdAt]) @@index([entityType, entityId]) @@index([userId]) @@map("activity_logs") } model MemoryEmbedding { id String @id @default(uuid()) @db.Uuid workspaceId String @map("workspace_id") @db.Uuid content String @db.Text // Note: vector dimension (1536) must match EMBEDDING_DIMENSION constant in @mosaic/shared embedding Unsupported("vector(1536)")? entityType EntityType? @map("entity_type") entityId String? @map("entity_id") @db.Uuid metadata Json @default("{}") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz // Relations workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) @@index([workspaceId]) @@map("memory_embeddings") }