@@ -344,6 +344,9 @@ model AISession {
344344 title String ? @db.VarChar
345345 status String @default (" active " ) @db.VarChar // active, completed, failed
346346 metadata Json ? @db.JsonB
347+ // The execution that opened this system session (null for user sessions and
348+ // for system sessions predating executions — no backfill by design).
349+ executionId String ? @map (" execution_id " ) @db.VarChar
347350 createTime DateTime @default (now () ) @map (" create_time " ) @db.Timestamp (6 )
348351 updateTime DateTime @default (now () ) @updatedAt @map (" update_time " ) @db.Timestamp (6 )
349352 messages AIMessage []
@@ -356,27 +359,42 @@ model AISession {
356359 @@map (" ai_sessions " )
357360}
358361
362+ enum TurnKind {
363+ rca_execution
364+ rca_followup
365+ chat
366+ detector
367+ digest
368+ }
369+
359370// AI Messages - Individual messages within an AI session
360371model AIMessage {
361- id String @id @default (cuid () ) @db.VarChar
362- workspaceId String @map (" workspace_id " ) @db.VarChar // direct workspace pointer for per-kind aggregation (detector scans have no session)
363- sessionId String ? @map (" session_id " ) @db.VarChar // nullable: detector scans have no chat session
364- kind String @default (" chat " ) @db.VarChar // "chat" | "rca" | "detector" | "digest-summary" — categorical tag; usage metering aggregates only chat|rca|detector (digest-summary is recorded, not metered)
365- role String @db.VarChar // user, assistant, tool
366- content String @db.Text
367- metadata Json ? @db.JsonB // tool name, tool result, etc.
368- model String ? @db.VarChar
369- provider String ? @db.VarChar
370- isByok Boolean ? @map (" is_byok " )
371- inputTokens Int ? @map (" input_tokens " )
372- outputTokens Int ? @map (" output_tokens " )
373- cost Decimal ? @map (" cost_usd " ) @db.Decimal (10 , 6 )
374- createTime DateTime @default (now () ) @map (" create_time " ) @db.Timestamp (6 )
375- workspace Workspace @relation (fields : [workspaceId ] , references : [id ] , onDelete : Cascade , onUpdate : NoAction )
376- session AISession ? @relation (fields : [sessionId ] , references : [id ] , onDelete : Cascade , onUpdate : NoAction )
372+ id String @id @default (cuid () ) @db.VarChar
373+ workspaceId String @map (" workspace_id " ) @db.VarChar // direct workspace pointer for per-kind aggregation (detector scans have no session)
374+ sessionId String ? @map (" session_id " ) @db.VarChar // nullable: detector scans have no chat session
375+ kind String @default (" chat " ) @db.VarChar // "chat" | "rca" | "detector" | "digest-summary" — categorical tag; usage metering aggregates only chat|rca|detector (digest-summary is recorded, not metered)
376+ // Per-turn attribution. `kind` is kept one release for old readers and is
377+ // derived from turnKind at write time; metering will move to turnKind (E-09 follow-up).
378+ turnKind TurnKind @default (chat ) @map (" turn_kind " )
379+ executionId String ? @map (" execution_id " ) @db.VarChar
380+ initiatorUserId String ? @map (" initiator_user_id " ) @db.VarChar
381+ role String @db.VarChar // user, assistant, tool
382+ content String @db.Text
383+ metadata Json ? @db.JsonB // tool name, tool result, etc.
384+ model String ? @db.VarChar
385+ provider String ? @db.VarChar
386+ isByok Boolean ? @map (" is_byok " )
387+ inputTokens Int ? @map (" input_tokens " )
388+ outputTokens Int ? @map (" output_tokens " )
389+ cost Decimal ? @map (" cost_usd " ) @db.Decimal (10 , 6 )
390+ createTime DateTime @default (now () ) @map (" create_time " ) @db.Timestamp (6 )
391+ workspace Workspace @relation (fields : [workspaceId ] , references : [id ] , onDelete : Cascade , onUpdate : NoAction )
392+ session AISession ? @relation (fields : [sessionId ] , references : [id ] , onDelete : Cascade , onUpdate : NoAction )
393+ execution DetectorRcaExecution ? @relation (fields : [executionId ] , references : [id ] , onDelete : SetNull )
377394
378395 @@index ([sessionId ] , map : " ix_ai_message_session_id " )
379396 @@index ([workspaceId , kind , createTime ] , map : " ix_ai_message_workspace_kind_time " )
397+ @@index ([workspaceId , turnKind , createTime ] , map : " ix_ai_message_workspace_turnkind_time " )
380398 @@map (" ai_messages " )
381399}
382400
@@ -516,6 +534,7 @@ model DetectorRcaExecution {
516534 rca DetectorRca @relation (" rcaExecutions " , fields : [findingId ] , references : [findingId ] , onDelete : Cascade )
517535 session AISession ? @relation (fields : [sessionId ] , references : [id ] , onDelete : SetNull )
518536 latestOf DetectorRca ? @relation (" latestExecution " )
537+ messages AIMessage []
519538
520539 @@unique ([findingId , attempt ] , map : " uq_rca_execution_finding_attempt " )
521540 @@index ([projectId ] , map : " ix_rca_execution_project_id " )
0 commit comments