diff --git a/CLAUDE.md b/CLAUDE.md index d95a9a4..ae36ef3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -135,6 +135,7 @@ This document contains the development guidelines and instructions for the Happy - Use "inTx" to wrap database operations in transactions - Do not update schema without absolute necessity - For complex fields, use "Json" type +- NEVER DO MIGRATION YOURSELF. Only run yarn generate when new types needed ### Current Schema Status The project has pending Prisma migrations that need to be applied: diff --git a/deploy/handy.yaml b/deploy/handy.yaml index 94adbe1..b03ced3 100644 --- a/deploy/handy.yaml +++ b/deploy/handy.yaml @@ -86,6 +86,8 @@ spec: key: /handy-github - extract: key: /handy-files + - extract: + key: /handy-e2b --- apiVersion: v1 kind: Service diff --git a/prisma/migrations/20250908050408_add_data_encryption_key/migration.sql b/prisma/migrations/20250908050408_add_data_encryption_key/migration.sql new file mode 100644 index 0000000..dd5c399 --- /dev/null +++ b/prisma/migrations/20250908050408_add_data_encryption_key/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Session" ADD COLUMN "dataEncryptionKey" BYTEA; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8dfc2ea..6ace9f4 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -90,6 +90,7 @@ model Session { metadataVersion Int @default(0) agentState String? agentStateVersion Int @default(0) + dataEncryptionKey Bytes? seq Int @default(0) active Boolean @default(true) lastActiveAt DateTime @default(now()) diff --git a/sources/app/api/routes/sessionRoutes.ts b/sources/app/api/routes/sessionRoutes.ts index f1ddbcf..f71888f 100644 --- a/sources/app/api/routes/sessionRoutes.ts +++ b/sources/app/api/routes/sessionRoutes.ts @@ -28,6 +28,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: true, agentState: true, agentStateVersion: true, + dataEncryptionKey: true, active: true, lastActiveAt: true, // messages: { @@ -61,6 +62,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: v.metadataVersion, agentState: v.agentState, agentStateVersion: v.agentStateVersion, + dataEncryptionKey: v.dataEncryptionKey ? Buffer.from(v.dataEncryptionKey).toString('base64') : null, lastMessage: null }; }) @@ -96,6 +98,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: true, agentState: true, agentStateVersion: true, + dataEncryptionKey: true, active: true, lastActiveAt: true, } @@ -113,6 +116,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: v.metadataVersion, agentState: v.agentState, agentStateVersion: v.agentStateVersion, + dataEncryptionKey: v.dataEncryptionKey ? Buffer.from(v.dataEncryptionKey).toString('base64') : null, })) }); }); @@ -174,6 +178,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: true, agentState: true, agentStateVersion: true, + dataEncryptionKey: true, active: true, lastActiveAt: true, } @@ -202,6 +207,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: v.metadataVersion, agentState: v.agentState, agentStateVersion: v.agentStateVersion, + dataEncryptionKey: v.dataEncryptionKey ? Buffer.from(v.dataEncryptionKey).toString('base64') : null, })), nextCursor, hasNext @@ -214,13 +220,14 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { body: z.object({ tag: z.string(), metadata: z.string(), - agentState: z.string().nullish() + agentState: z.string().nullish(), + dataEncryptionKey: z.string().nullish() }) }, preHandler: app.authenticate }, async (request, reply) => { const userId = request.userId; - const { tag, metadata } = request.body; + const { tag, metadata, dataEncryptionKey } = request.body; const session = await db.session.findFirst({ where: { @@ -238,6 +245,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: session.metadataVersion, agentState: session.agentState, agentStateVersion: session.agentStateVersion, + dataEncryptionKey: session.dataEncryptionKey ? Buffer.from(session.dataEncryptionKey).toString('base64') : null, active: session.active, activeAt: session.lastActiveAt.getTime(), createdAt: session.createdAt.getTime(), @@ -256,7 +264,8 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { data: { accountId: userId, tag: tag, - metadata: metadata + metadata: metadata, + dataEncryptionKey: dataEncryptionKey ? Buffer.from(dataEncryptionKey, 'base64') : undefined } }); log({ module: 'session-create', sessionId: session.id, userId }, `Session created: ${session.id}`); @@ -284,6 +293,7 @@ export function sessionRoutes(app: Fastify, eventRouter: EventRouter) { metadataVersion: session.metadataVersion, agentState: session.agentState, agentStateVersion: session.agentStateVersion, + dataEncryptionKey: session.dataEncryptionKey ? Buffer.from(session.dataEncryptionKey).toString('base64') : null, active: session.active, activeAt: session.lastActiveAt.getTime(), createdAt: session.createdAt.getTime(), diff --git a/sources/app/events/eventRouter.ts b/sources/app/events/eventRouter.ts index 4c9d3f8..a94d1d5 100644 --- a/sources/app/events/eventRouter.ts +++ b/sources/app/events/eventRouter.ts @@ -56,6 +56,7 @@ export type UpdateEvent = { metadataVersion: number; agentState: string | null; agentStateVersion: number; + dataEncryptionKey: string | null; active: boolean; activeAt: number; createdAt: number; @@ -266,6 +267,7 @@ export function buildNewSessionUpdate(session: { metadataVersion: number; agentState: string | null; agentStateVersion: number; + dataEncryptionKey: Uint8Array | null; active: boolean; lastActiveAt: Date; createdAt: Date; @@ -282,6 +284,7 @@ export function buildNewSessionUpdate(session: { metadataVersion: session.metadataVersion, agentState: session.agentState, agentStateVersion: session.agentStateVersion, + dataEncryptionKey: session.dataEncryptionKey ? Buffer.from(session.dataEncryptionKey).toString('base64') : null, active: session.active, activeAt: session.lastActiveAt.getTime(), createdAt: session.createdAt.getTime(), diff --git a/sources/storage/types.ts b/sources/storage/types.ts index 406d338..cb7616f 100644 --- a/sources/storage/types.ts +++ b/sources/storage/types.ts @@ -40,6 +40,7 @@ declare global { metadataVersion: number; agentState: string | null; agentStateVersion: number; + dataEncryptionKey: string | null; active: boolean; activeAt: number; createdAt: number;