diff --git a/src/app/api/chat/send/route.ts b/src/app/api/chat/send/route.ts index 4677248..c23f82a 100644 --- a/src/app/api/chat/send/route.ts +++ b/src/app/api/chat/send/route.ts @@ -102,6 +102,7 @@ export async function POST(request: NextRequest) { const remoteUrl = `https://${targetNodeDomain}/api/swarm/chat/inbox`; try { + console.log('[Chat Send] Forwarding to remote:', remoteUrl, 'Envelope:', JSON.stringify(body, null, 2)); const response = await fetch(remoteUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -109,8 +110,30 @@ export async function POST(request: NextRequest) { }); if (!response.ok) { - const errorData = await response.json().catch(() => ({})); - console.error('[Chat Send] Remote delivery failed:', errorData); + const errorText = await response.text(); + let errorData; + try { + errorData = JSON.parse(errorText); + } catch { + errorData = { raw: errorText }; + } + console.error('[Chat Send] Remote delivery failed:', response.status, errorData); + + // Check if remote node doesn't support V2 (returns V1 validation errors) + const isV1ValidationError = errorData.details && + Array.isArray(errorData.details) && + errorData.details.some((d: any) => + d.path && ['messageId', 'senderHandle', 'senderNodeDomain', 'recipientHandle', 'encryptedContent', 'timestamp'].includes(d.path[0]) + ); + + if (isV1ValidationError) { + return NextResponse.json({ + error: 'Remote node needs update', + details: 'The recipient node is running an older version that does not support the V2 chat protocol. Please ask the node administrator to update to the latest version.', + remoteError: errorData + }, { status: 400 }); + } + return NextResponse.json({ error: 'Remote delivery failed', details: errorData diff --git a/src/app/api/swarm/chat/inbox/route.ts b/src/app/api/swarm/chat/inbox/route.ts index a25f0f5..b260476 100644 --- a/src/app/api/swarm/chat/inbox/route.ts +++ b/src/app/api/swarm/chat/inbox/route.ts @@ -29,6 +29,49 @@ export async function POST(request: NextRequest) { } const body = await request.json(); + console.log('[Swarm Inbox] Received body keys:', Object.keys(body), 'action:', body.action); + + // Check if this is a V2 encrypted envelope (has 'action' and 'data' fields) + // MUST check BEFORE Zod validation to avoid validation errors + if (body.action === 'chat.deliver' && body.data) { + // V2 E2EE Message - store in chatInbox + const { recipientDid, recipientDeviceId, ciphertext } = body.data; + + if (!recipientDid || !ciphertext) { + return NextResponse.json({ error: 'Invalid V2 payload' }, { status: 400 }); + } + + // Find recipient by DID + const recipient = await db.query.users.findFirst({ + where: eq(users.did, recipientDid) + }); + + if (!recipient) { + return NextResponse.json({ error: 'Recipient not found' }, { status: 404 }); + } + + // Import chatInbox schema + const { chatInbox } = await import('@/db/schema'); + + // Store in V2 inbox + await db.insert(chatInbox).values({ + senderDid: body.did, // From signed envelope + recipientDid, + recipientDeviceId: recipientDeviceId || null, + envelope: JSON.stringify(body), + expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) + }); + + console.log(`[Swarm Chat V2] Received encrypted message for ${recipientDid}`); + + return NextResponse.json({ + success: true, + message: 'V2 message received', + version: 2 + }); + } + + // V1 Legacy Message Format - validate with Zod const data = chatMessageSchema.parse(body) as SwarmChatMessagePayload; // Find the recipient (local user) diff --git a/src/lib/hooks/useChatEncryption.ts b/src/lib/hooks/useChatEncryption.ts index 50d0427..2377c93 100644 --- a/src/lib/hooks/useChatEncryption.ts +++ b/src/lib/hooks/useChatEncryption.ts @@ -412,8 +412,14 @@ export function useChatEncryption() { }); if (!sendRes.ok) { - const errorData = await sendRes.json().catch(() => ({ error: 'Unknown error' })); - console.error('[Chat] Send failed:', errorData); + const errorText = await sendRes.text(); + let errorData; + try { + errorData = JSON.parse(errorText); + } catch { + errorData = { error: errorText }; + } + console.error('[Chat] Send failed:', sendRes.status, errorData); throw new Error(`Failed to send message: ${errorData.error || sendRes.statusText}`); }