schema.prisma 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // EKS Support Relay — persistence layer.
  2. // SQLite for now; the schema deliberately avoids SQLite-only features so a
  3. // later move to PostgreSQL only needs a datasource/provider change.
  4. generator client {
  5. provider = "prisma-client-js"
  6. output = "../node_modules/.prisma/client"
  7. }
  8. datasource db {
  9. provider = "sqlite"
  10. url = env("DATABASE_URL")
  11. }
  12. /// One row per inbound source message. Primary idempotency guard for the
  13. /// Chatwoot webhook: (source, messageId) is unique.
  14. model ProcessedMessage {
  15. id String @id @default(cuid())
  16. source String
  17. messageId String
  18. conversationId Int
  19. /// queued | processing | replied | skipped | ticket | failed | spam
  20. status String
  21. reason String?
  22. createdAt DateTime @default(now())
  23. updatedAt DateTime @updatedAt
  24. @@unique([source, messageId])
  25. @@index([conversationId])
  26. @@index([status])
  27. }
  28. /// Async work item. The webhook persists a job and returns 202; the in-process
  29. /// worker picks it up, with retries and exponential backoff.
  30. model Job {
  31. id String @id @default(cuid())
  32. /// chatwoot_message
  33. type String
  34. /// queued | processing | done | failed | dead
  35. status String @default("queued")
  36. attempts Int @default(0)
  37. maxAttempts Int @default(3)
  38. /// Redacted, minimal payload — never full secrets.
  39. payloadJson String
  40. /// Redacted error text.
  41. lastError String?
  42. runAfter DateTime @default(now())
  43. startedAt DateTime?
  44. finishedAt DateTime?
  45. createdAt DateTime @default(now())
  46. updatedAt DateTime @updatedAt
  47. @@index([status, runAfter])
  48. }
  49. /// Handoff record. conversationId is unique so repeated new_ticket calls for
  50. /// the same conversation always resolve to the same ticket number.
  51. model Ticket {
  52. id String @id @default(cuid())
  53. conversationId Int @unique
  54. ticketNumber String
  55. reason String?
  56. createdAt DateTime @default(now())
  57. }
  58. /// Non-secret audit trail of decisions taken per message/conversation.
  59. model AuditEvent {
  60. id String @id @default(cuid())
  61. conversationId Int?
  62. messageId String?
  63. eventType String
  64. summary String
  65. /// Redacted JSON metadata.
  66. metaJson String?
  67. createdAt DateTime @default(now())
  68. @@index([conversationId])
  69. @@index([eventType])
  70. @@index([createdAt])
  71. }