erDiagram
User ||--o{ AuthRefreshToken : has
User ||--o{ GmailAccount : connects
User ||--o{ AnalysisRun : starts
User ||--|| SecurityChat : owns
GmailAccount ||--o{ ServiceAccount : contains
AnalysisRun ||--o{ ServiceAccount : produces
ServiceAccount ||--o{ RiskEvidence : has
ServiceAccount ||--o{ ActionItem : recommends
ServiceAccount ||--o{ ActionSession : opens
ActionSession ||--o{ ActionMessage : contains
ActionSession ||--o{ ActionAttempt : records
ActionItem ||--o{ ActionAttempt : attempted_by
SecurityChat ||--o{ SecurityChatMessage : contains
User {
String id PK
String name
String phone
String ageGroup
Boolean requiredTermsAgreed
DateTime requiredTermsAgreedAt
Boolean notificationAgreed
Boolean marketingAgreed
Boolean alertSuspiciousLogin
Boolean alertPasswordChange
Boolean alertNewDevice
Boolean alertRecoveryEmail
Boolean alertSecurityTip
Boolean alertEventPromo
DateTime lastLoginAt
DateTime createdAt
}
AuthRefreshToken {
String id PK
String userId FK
String tokenHash UK
DateTime expiresAt
DateTime revokedAt
DateTime createdAt
}
WithdrawalLog {
String id PK
String reason
String reasonDetail
DateTime deletedAt
}
GmailAccount {
String id PK
String userId FK
String email UK
String refreshToken
Boolean isPrimary
String label
String status
DateTime lastSyncedAt
DateTime lastEmailReceivedAt
DateTime createdAt
}
AnalysisRun {
String id PK
String userId FK
String status
String mode
Int progress
String currentStep
String displayMessage
String failedReason
Json reportSnapshot
DateTime startedAt
DateTime completedAt
}
ServiceAccount {
String id PK
String gmailAccountId FK
String analysisRunId FK
String aiAccountId
String serviceName
String displayName
String iconUrl
String iconLabel
String riskLevel
String status
String primaryRiskType
String headline
String summary
String interpretation
DateTime resolvedAt
DateTime skippedAt
DateTime dormantAt
String previousStatus
DateTime lastAnalyzedAt
DateTime createdAt
DateTime updatedAt
}
RiskEvidence {
String id PK
String serviceAccountId FK
String riskType
String sender
String subject
DateTime receivedAt
String summary
String evidenceHash UK
DateTime createdAt
}
ActionItem {
String id PK
String serviceAccountId FK
String type
String title
String description
String why
Boolean isRequired
String externalUrl
Int order
String status
DateTime createdAt
DateTime updatedAt
}
ActionSession {
String id PK
String serviceAccountId FK
String status
String activeActionItemId
Boolean feedbackEnabled
Boolean composerEnabled
String composerPlaceholder
DateTime startedAt
DateTime completedAt
DateTime updatedAt
}
ActionMessage {
String id PK
String sessionId FK
String role
String type
String content
Json metadata
DateTime createdAt
}
ActionAttempt {
String id PK
String sessionId FK
String actionItemId FK
String status
String reason
String reasonCategory
DateTime createdAt
}
SecurityChat {
String id PK
String userId FK
DateTime createdAt
DateTime updatedAt
}
SecurityChatMessage {
String id PK
String chatId FK
String role
String type
String content
Json metadata
DateTime createdAt
}
BetaApplicant {
String id PK
String email UK
String phone
DateTime createdAt
}
UserResponseLog {
String userId PK
String actionItemId PK
String status
DateTime createdAt
DateTime completedAt
}