diff --git a/apps/backend/drizzle/0008_migrate_messages_ciphertext.sql b/apps/backend/drizzle/0008_migrate_messages_ciphertext.sql new file mode 100644 index 00000000..6f0034ef --- /dev/null +++ b/apps/backend/drizzle/0008_migrate_messages_ciphertext.sql @@ -0,0 +1,11 @@ +-- Drop the full-text search index that relied on the plaintext content column. +DROP INDEX IF EXISTS "messages_content_search_idx";--> statement-breakpoint + +-- Add the new nullable ciphertext column for single-blob E2EE messages. +ALTER TABLE "messages" ADD COLUMN "ciphertext" text;--> statement-breakpoint + +-- Migrate existing plaintext content into ciphertext so no data is lost. +UPDATE "messages" SET "ciphertext" = "content" WHERE "deleted_at" IS NULL;--> statement-breakpoint + +-- Drop the old plaintext content column. +ALTER TABLE "messages" DROP COLUMN "content"; diff --git a/apps/backend/src/__tests__/conversations.cache.test.ts b/apps/backend/src/__tests__/conversations.cache.test.ts index fdc93b69..7eb854c3 100644 --- a/apps/backend/src/__tests__/conversations.cache.test.ts +++ b/apps/backend/src/__tests__/conversations.cache.test.ts @@ -62,7 +62,7 @@ vi.mock('../db/schema.js', () => ({ id: 'id', conversationId: 'conversationId', senderId: 'senderId', - content: 'content', + ciphertext: 'ciphertext', createdAt: 'createdAt', deletedAt: 'deletedAt', }, diff --git a/apps/backend/src/__tests__/conversations.routes.test.ts b/apps/backend/src/__tests__/conversations.routes.test.ts index 20f12028..db1c9f44 100644 --- a/apps/backend/src/__tests__/conversations.routes.test.ts +++ b/apps/backend/src/__tests__/conversations.routes.test.ts @@ -54,7 +54,7 @@ vi.mock('../db/schema.js', () => ({ id: 'id', conversationId: 'conversationId', senderId: 'senderId', - content: 'content', + ciphertext: 'ciphertext', createdAt: 'createdAt', deletedAt: 'deletedAt', }, diff --git a/apps/backend/src/__tests__/messages.routes.test.ts b/apps/backend/src/__tests__/messages.routes.test.ts index aa5361b3..12e27da6 100644 --- a/apps/backend/src/__tests__/messages.routes.test.ts +++ b/apps/backend/src/__tests__/messages.routes.test.ts @@ -43,7 +43,7 @@ vi.mock('../db/schema.js', () => ({ id: 'id', conversationId: 'conversationId', senderId: 'senderId', - content: 'content', + ciphertext: 'ciphertext', createdAt: 'createdAt', deletedAt: 'deletedAt', }, @@ -86,7 +86,7 @@ describe('DELETE /messages/:id', () => { id: 'msg-1', conversationId: 'conv-1', senderId: 'user-2', - content: 'hello', + ciphertext: 'hello', deletedAt: null, }); @@ -101,7 +101,7 @@ describe('DELETE /messages/:id', () => { id: 'msg-1', conversationId: 'conv-1', senderId: 'user-1', - content: 'hello', + ciphertext: 'hello', deletedAt: null, }); diff --git a/apps/backend/src/socket/messaging.ts b/apps/backend/src/socket/messaging.ts index 5426137c..ba9b44bd 100644 --- a/apps/backend/src/socket/messaging.ts +++ b/apps/backend/src/socket/messaging.ts @@ -636,7 +636,7 @@ export function registerMessagingHandlers(io: Server, socket: AuthSocket): void const response = await fetch('http://localhost:8000/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ message: content, conversation_id: conversationId }), + body: JSON.stringify({ message: ciphertext, conversation_id: conversationId }), }); if (!response.ok) {