feat: data encryption key

This commit is contained in:
Steve Korshakov 2025-09-07 22:04:59 -07:00
parent a2fa1dbd01
commit 31bb2892f2
7 changed files with 23 additions and 3 deletions

View File

@ -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:

View File

@ -86,6 +86,8 @@ spec:
key: /handy-github
- extract:
key: /handy-files
- extract:
key: /handy-e2b
---
apiVersion: v1
kind: Service

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Session" ADD COLUMN "dataEncryptionKey" BYTEA;

View File

@ -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())

View File

@ -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(),

View File

@ -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(),

View File

@ -40,6 +40,7 @@ declare global {
metadataVersion: number;
agentState: string | null;
agentStateVersion: number;
dataEncryptionKey: string | null;
active: boolean;
activeAt: number;
createdAt: number;