create-chaaskit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add-infra.d.ts +6 -0
- package/dist/commands/add-infra.d.ts.map +1 -0
- package/dist/commands/add-infra.js +160 -0
- package/dist/commands/add-infra.js.map +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +63 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/db-sync.d.ts +13 -0
- package/dist/commands/db-sync.d.ts.map +1 -0
- package/dist/commands/db-sync.js +108 -0
- package/dist/commands/db-sync.js.map +1 -0
- package/dist/commands/dev.d.ts +7 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +61 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +214 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/.env.example +24 -0
- package/dist/templates/README.md +81 -0
- package/dist/templates/app/components/AcceptInviteClient.tsx +10 -0
- package/dist/templates/app/components/AdminDashboardClient.tsx +10 -0
- package/dist/templates/app/components/AdminTeamClient.tsx +10 -0
- package/dist/templates/app/components/AdminTeamsClient.tsx +10 -0
- package/dist/templates/app/components/AdminUsersClient.tsx +10 -0
- package/dist/templates/app/components/ApiKeysClient.tsx +10 -0
- package/dist/templates/app/components/AutomationsClient.tsx +10 -0
- package/dist/templates/app/components/ChatClient.tsx +13 -0
- package/dist/templates/app/components/ClientOnly.tsx +6 -0
- package/dist/templates/app/components/DocumentsClient.tsx +10 -0
- package/dist/templates/app/components/OAuthConsentClient.tsx +10 -0
- package/dist/templates/app/components/PricingClient.tsx +10 -0
- package/dist/templates/app/components/TeamSettingsClient.tsx +10 -0
- package/dist/templates/app/components/VerifyEmailClient.tsx +10 -0
- package/dist/templates/app/entry.client.tsx +12 -0
- package/dist/templates/app/entry.server.tsx +67 -0
- package/dist/templates/app/root.tsx +91 -0
- package/dist/templates/app/routes/_index.tsx +82 -0
- package/dist/templates/app/routes/admin._index.tsx +57 -0
- package/dist/templates/app/routes/admin.teams.$teamId.tsx +57 -0
- package/dist/templates/app/routes/admin.teams._index.tsx +57 -0
- package/dist/templates/app/routes/admin.users.tsx +57 -0
- package/dist/templates/app/routes/api-keys.tsx +57 -0
- package/dist/templates/app/routes/automations.tsx +57 -0
- package/dist/templates/app/routes/chat._index.tsx +11 -0
- package/dist/templates/app/routes/chat.admin._index.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.teams.$teamId.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.teams._index.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.users.tsx +10 -0
- package/dist/templates/app/routes/chat.api-keys.tsx +10 -0
- package/dist/templates/app/routes/chat.automations.tsx +10 -0
- package/dist/templates/app/routes/chat.documents.tsx +10 -0
- package/dist/templates/app/routes/chat.team.$teamId.settings.tsx +10 -0
- package/dist/templates/app/routes/chat.thread.$threadId.tsx +11 -0
- package/dist/templates/app/routes/chat.tsx +39 -0
- package/dist/templates/app/routes/documents.tsx +57 -0
- package/dist/templates/app/routes/invite.$token.tsx +10 -0
- package/dist/templates/app/routes/login.tsx +334 -0
- package/dist/templates/app/routes/oauth.consent.tsx +10 -0
- package/dist/templates/app/routes/pricing.tsx +10 -0
- package/dist/templates/app/routes/privacy.tsx +197 -0
- package/dist/templates/app/routes/register.tsx +398 -0
- package/dist/templates/app/routes/shared.$shareId.tsx +226 -0
- package/dist/templates/app/routes/team.$teamId.settings.tsx +57 -0
- package/dist/templates/app/routes/terms.tsx +173 -0
- package/dist/templates/app/routes/thread.$threadId.tsx +102 -0
- package/dist/templates/app/routes/verify-email.tsx +10 -0
- package/dist/templates/app/routes.ts +47 -0
- package/dist/templates/config/app.config.ts +216 -0
- package/dist/templates/docs/admin.md +257 -0
- package/dist/templates/docs/api-keys.md +403 -0
- package/dist/templates/docs/authentication.md +247 -0
- package/dist/templates/docs/configuration.md +1212 -0
- package/dist/templates/docs/custom-pages.md +466 -0
- package/dist/templates/docs/deployment.md +362 -0
- package/dist/templates/docs/development.md +411 -0
- package/dist/templates/docs/documents.md +293 -0
- package/dist/templates/docs/extensions.md +639 -0
- package/dist/templates/docs/index.md +139 -0
- package/dist/templates/docs/installation.md +286 -0
- package/dist/templates/docs/mcp.md +952 -0
- package/dist/templates/docs/native-tools.md +688 -0
- package/dist/templates/docs/queue.md +514 -0
- package/dist/templates/docs/scheduled-prompts.md +279 -0
- package/dist/templates/docs/settings.md +415 -0
- package/dist/templates/docs/slack.md +318 -0
- package/dist/templates/docs/styling.md +288 -0
- package/dist/templates/extensions/agents/.gitkeep +0 -0
- package/dist/templates/extensions/pages/.gitkeep +0 -0
- package/dist/templates/extensions/payment-plans/.gitkeep +0 -0
- package/dist/templates/index.html +16 -0
- package/dist/templates/infra-aws/.github/workflows/deploy.yml +95 -0
- package/dist/templates/infra-aws/README.md +207 -0
- package/dist/templates/infra-aws/bin/cdk.ts +18 -0
- package/dist/templates/infra-aws/cdk.json +43 -0
- package/dist/templates/infra-aws/config/deployment.ts +156 -0
- package/dist/templates/infra-aws/lib/chaaskit-stack.ts +419 -0
- package/dist/templates/infra-aws/package.json +27 -0
- package/dist/templates/infra-aws/scripts/build-app.sh +63 -0
- package/dist/templates/infra-aws/tsconfig.json +25 -0
- package/dist/templates/package.json +46 -0
- package/dist/templates/prisma/schema/base.prisma +584 -0
- package/dist/templates/prisma/schema/custom.prisma +24 -0
- package/dist/templates/prisma/schema.prisma +271 -0
- package/dist/templates/public/favicon.svg +4 -0
- package/dist/templates/public/logo.svg +4 -0
- package/dist/templates/react-router.config.ts +11 -0
- package/dist/templates/server.js +52 -0
- package/dist/templates/src/main.tsx +8 -0
- package/dist/templates/tsconfig.json +26 -0
- package/dist/templates/vite.config.ts +26 -0
- package/package.json +46 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Base Schema - @chat-saas/db
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// This file contains the core models provided by @chat-saas/db.
|
|
5
|
+
// DO NOT MODIFY THIS FILE - it will be overwritten by `chat-saas-server db:sync`.
|
|
6
|
+
//
|
|
7
|
+
// For custom models, create or edit `custom.prisma` in this same directory.
|
|
8
|
+
// =============================================================================
|
|
9
|
+
|
|
10
|
+
generator client {
|
|
11
|
+
provider = "prisma-client-js"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
datasource db {
|
|
15
|
+
provider = "postgresql"
|
|
16
|
+
url = env("DATABASE_URL")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
model User {
|
|
20
|
+
id String @id @default(cuid())
|
|
21
|
+
email String @unique
|
|
22
|
+
passwordHash String?
|
|
23
|
+
name String?
|
|
24
|
+
avatarUrl String?
|
|
25
|
+
|
|
26
|
+
// Auth
|
|
27
|
+
emailVerified Boolean @default(false)
|
|
28
|
+
oauthProvider String?
|
|
29
|
+
oauthId String?
|
|
30
|
+
|
|
31
|
+
// Admin flag
|
|
32
|
+
isAdmin Boolean @default(false)
|
|
33
|
+
|
|
34
|
+
// Subscription
|
|
35
|
+
plan String @default("free")
|
|
36
|
+
stripeCustomerId String? @unique
|
|
37
|
+
credits Int @default(0)
|
|
38
|
+
messagesThisMonth Int @default(0)
|
|
39
|
+
|
|
40
|
+
// User settings/context (JSON)
|
|
41
|
+
settings Json @default("{}")
|
|
42
|
+
themePreference String?
|
|
43
|
+
|
|
44
|
+
// Relations
|
|
45
|
+
threads Thread[]
|
|
46
|
+
projects Project[]
|
|
47
|
+
teamMemberships TeamMember[]
|
|
48
|
+
feedback MessageFeedback[]
|
|
49
|
+
templates PromptTemplate[]
|
|
50
|
+
magicLinks MagicLink[]
|
|
51
|
+
mcpCredentials MCPCredential[]
|
|
52
|
+
apiKeys ApiKey[]
|
|
53
|
+
documents Document[]
|
|
54
|
+
|
|
55
|
+
// OAuth relations
|
|
56
|
+
oauthClients OAuthClient[]
|
|
57
|
+
oauthAuthCodes OAuthAuthorizationCode[]
|
|
58
|
+
oauthTokens OAuthToken[]
|
|
59
|
+
|
|
60
|
+
// Scheduled prompts
|
|
61
|
+
scheduledPrompts ScheduledPrompt[]
|
|
62
|
+
|
|
63
|
+
// Email verification
|
|
64
|
+
emailVerifications EmailVerification[]
|
|
65
|
+
|
|
66
|
+
createdAt DateTime @default(now())
|
|
67
|
+
updatedAt DateTime @updatedAt
|
|
68
|
+
|
|
69
|
+
@@index([email])
|
|
70
|
+
@@index([stripeCustomerId])
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
model Thread {
|
|
74
|
+
id String @id @default(cuid())
|
|
75
|
+
title String @default("New Chat")
|
|
76
|
+
userId String?
|
|
77
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
78
|
+
|
|
79
|
+
// Agent used for this thread (null = default agent)
|
|
80
|
+
agentId String?
|
|
81
|
+
|
|
82
|
+
// For team threads
|
|
83
|
+
teamId String?
|
|
84
|
+
team Team? @relation(fields: [teamId], references: [id], onDelete: SetNull)
|
|
85
|
+
|
|
86
|
+
// For project threads
|
|
87
|
+
projectId String?
|
|
88
|
+
project Project? @relation(fields: [projectId], references: [id], onDelete: SetNull)
|
|
89
|
+
|
|
90
|
+
// Branching support
|
|
91
|
+
parentThreadId String?
|
|
92
|
+
parentMessageId String?
|
|
93
|
+
parentThread Thread? @relation("ThreadBranches", fields: [parentThreadId], references: [id], onDelete: SetNull)
|
|
94
|
+
branches Thread[] @relation("ThreadBranches")
|
|
95
|
+
|
|
96
|
+
// Archived threads (hidden but preserved)
|
|
97
|
+
archivedAt DateTime?
|
|
98
|
+
|
|
99
|
+
// Relations
|
|
100
|
+
messages Message[]
|
|
101
|
+
sharedLinks SharedThread[]
|
|
102
|
+
slackEvents SlackMessageEvent[]
|
|
103
|
+
scheduledPrompts ScheduledPrompt[]
|
|
104
|
+
|
|
105
|
+
createdAt DateTime @default(now())
|
|
106
|
+
updatedAt DateTime @updatedAt
|
|
107
|
+
|
|
108
|
+
@@index([userId])
|
|
109
|
+
@@index([teamId])
|
|
110
|
+
@@index([projectId])
|
|
111
|
+
@@index([parentThreadId])
|
|
112
|
+
@@index([agentId])
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
model Message {
|
|
116
|
+
id String @id @default(cuid())
|
|
117
|
+
threadId String
|
|
118
|
+
thread Thread @relation(fields: [threadId], references: [id], onDelete: Cascade)
|
|
119
|
+
role String // 'user' | 'assistant' | 'system'
|
|
120
|
+
content String
|
|
121
|
+
|
|
122
|
+
// File attachments (JSON array)
|
|
123
|
+
files Json?
|
|
124
|
+
|
|
125
|
+
// Tool calls and results (JSON)
|
|
126
|
+
toolCalls Json?
|
|
127
|
+
toolResults Json?
|
|
128
|
+
|
|
129
|
+
// Token usage
|
|
130
|
+
inputTokens Int?
|
|
131
|
+
outputTokens Int?
|
|
132
|
+
|
|
133
|
+
// Relations
|
|
134
|
+
feedback MessageFeedback[]
|
|
135
|
+
|
|
136
|
+
createdAt DateTime @default(now())
|
|
137
|
+
|
|
138
|
+
@@index([threadId])
|
|
139
|
+
@@index([createdAt])
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
model MessageFeedback {
|
|
143
|
+
id String @id @default(cuid())
|
|
144
|
+
messageId String
|
|
145
|
+
message Message @relation(fields: [messageId], references: [id], onDelete: Cascade)
|
|
146
|
+
userId String
|
|
147
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
148
|
+
type String // 'up' | 'down'
|
|
149
|
+
comment String?
|
|
150
|
+
createdAt DateTime @default(now())
|
|
151
|
+
|
|
152
|
+
@@unique([messageId, userId])
|
|
153
|
+
@@index([messageId])
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
model SharedThread {
|
|
157
|
+
id String @id @default(cuid())
|
|
158
|
+
shareId String @unique @default(cuid())
|
|
159
|
+
threadId String
|
|
160
|
+
thread Thread @relation(fields: [threadId], references: [id], onDelete: Cascade)
|
|
161
|
+
expiresAt DateTime?
|
|
162
|
+
createdAt DateTime @default(now())
|
|
163
|
+
|
|
164
|
+
@@index([shareId])
|
|
165
|
+
@@index([threadId])
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
model PromptTemplate {
|
|
169
|
+
id String @id @default(cuid())
|
|
170
|
+
userId String
|
|
171
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
172
|
+
name String
|
|
173
|
+
prompt String
|
|
174
|
+
variables Json @default("[]")
|
|
175
|
+
createdAt DateTime @default(now())
|
|
176
|
+
updatedAt DateTime @updatedAt
|
|
177
|
+
|
|
178
|
+
@@index([userId])
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
model MagicLink {
|
|
182
|
+
id String @id @default(cuid())
|
|
183
|
+
token String @unique
|
|
184
|
+
userId String
|
|
185
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
186
|
+
expiresAt DateTime
|
|
187
|
+
usedAt DateTime?
|
|
188
|
+
createdAt DateTime @default(now())
|
|
189
|
+
|
|
190
|
+
@@index([token])
|
|
191
|
+
@@index([userId])
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
model PasswordReset {
|
|
195
|
+
id String @id @default(cuid())
|
|
196
|
+
token String @unique
|
|
197
|
+
email String
|
|
198
|
+
expiresAt DateTime
|
|
199
|
+
usedAt DateTime?
|
|
200
|
+
createdAt DateTime @default(now())
|
|
201
|
+
|
|
202
|
+
@@index([token])
|
|
203
|
+
@@index([email])
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Projects - organizational folders for threads with AI context
|
|
207
|
+
model Project {
|
|
208
|
+
id String @id @default(cuid())
|
|
209
|
+
name String
|
|
210
|
+
context String? // AI context for project threads
|
|
211
|
+
color String // hex color from preset list
|
|
212
|
+
sharing String @default("private") // 'private' | 'team'
|
|
213
|
+
userId String // creator
|
|
214
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
215
|
+
teamId String? // optional team association
|
|
216
|
+
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
217
|
+
threads Thread[]
|
|
218
|
+
documents Document[]
|
|
219
|
+
archivedAt DateTime? // null = active, set = archived
|
|
220
|
+
createdAt DateTime @default(now())
|
|
221
|
+
updatedAt DateTime @updatedAt
|
|
222
|
+
|
|
223
|
+
@@index([userId])
|
|
224
|
+
@@index([teamId])
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Team workspaces
|
|
228
|
+
model Team {
|
|
229
|
+
id String @id @default(cuid())
|
|
230
|
+
name String
|
|
231
|
+
context String? // Additional context passed to AI agent for team threads
|
|
232
|
+
archivedAt DateTime? // null = active, set = archived
|
|
233
|
+
|
|
234
|
+
// Billing fields
|
|
235
|
+
plan String @default("free")
|
|
236
|
+
stripeCustomerId String? @unique
|
|
237
|
+
credits Int @default(0)
|
|
238
|
+
messagesThisMonth Int @default(0)
|
|
239
|
+
|
|
240
|
+
members TeamMember[]
|
|
241
|
+
threads Thread[]
|
|
242
|
+
projects Project[]
|
|
243
|
+
invites TeamInvite[]
|
|
244
|
+
apiKeys ApiKey[]
|
|
245
|
+
documents Document[]
|
|
246
|
+
slackIntegration SlackIntegration?
|
|
247
|
+
scheduledPrompts ScheduledPrompt[]
|
|
248
|
+
createdAt DateTime @default(now())
|
|
249
|
+
updatedAt DateTime @updatedAt
|
|
250
|
+
|
|
251
|
+
@@index([stripeCustomerId])
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
model TeamMember {
|
|
255
|
+
id String @id @default(cuid())
|
|
256
|
+
teamId String
|
|
257
|
+
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
258
|
+
userId String
|
|
259
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
260
|
+
role String // 'owner' | 'admin' | 'member' | 'viewer'
|
|
261
|
+
|
|
262
|
+
createdAt DateTime @default(now())
|
|
263
|
+
|
|
264
|
+
@@unique([teamId, userId])
|
|
265
|
+
@@index([teamId])
|
|
266
|
+
@@index([userId])
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
model TeamInvite {
|
|
270
|
+
id String @id @default(cuid())
|
|
271
|
+
teamId String
|
|
272
|
+
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
273
|
+
email String
|
|
274
|
+
role String // 'admin' | 'member' | 'viewer'
|
|
275
|
+
token String @unique
|
|
276
|
+
invitedBy String
|
|
277
|
+
expiresAt DateTime
|
|
278
|
+
acceptedAt DateTime?
|
|
279
|
+
createdAt DateTime @default(now())
|
|
280
|
+
|
|
281
|
+
@@unique([teamId, email])
|
|
282
|
+
@@index([token])
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// MCP Server Credentials
|
|
286
|
+
model MCPCredential {
|
|
287
|
+
id String @id @default(cuid())
|
|
288
|
+
userId String
|
|
289
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
290
|
+
serverId String
|
|
291
|
+
credentialType String // 'api_key' | 'oauth'
|
|
292
|
+
encryptedData String // Encrypted JSON: {apiKey} or {accessToken, refreshToken, expiresAt}
|
|
293
|
+
oauthState String? // Temporary state during OAuth flow
|
|
294
|
+
codeVerifier String? // PKCE verifier (encrypted)
|
|
295
|
+
createdAt DateTime @default(now())
|
|
296
|
+
updatedAt DateTime @updatedAt
|
|
297
|
+
|
|
298
|
+
@@unique([userId, serverId])
|
|
299
|
+
@@index([userId])
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// API Keys for programmatic access
|
|
303
|
+
model ApiKey {
|
|
304
|
+
id String @id @default(cuid())
|
|
305
|
+
userId String
|
|
306
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
307
|
+
teamId String? // Optional: if set, key operates in team context
|
|
308
|
+
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
309
|
+
name String // User-provided label, e.g. "My CLI Tool"
|
|
310
|
+
keyPrefix String // First 10 chars for display: "sk-abc123..."
|
|
311
|
+
keyHash String // bcrypt hash of full key
|
|
312
|
+
lastUsedAt DateTime?
|
|
313
|
+
expiresAt DateTime? // Optional expiration
|
|
314
|
+
createdAt DateTime @default(now())
|
|
315
|
+
|
|
316
|
+
@@index([userId])
|
|
317
|
+
@@index([teamId])
|
|
318
|
+
@@index([keyPrefix]) // For lookup during auth
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// OAuth Client Registration for MCP Server (RFC 7591)
|
|
322
|
+
model OAuthClient {
|
|
323
|
+
id String @id @default(cuid())
|
|
324
|
+
clientId String @unique // Public client ID
|
|
325
|
+
clientSecretHash String? // bcrypt hash (for confidential clients)
|
|
326
|
+
clientName String
|
|
327
|
+
clientUri String?
|
|
328
|
+
redirectUris String // JSON array of allowed redirect URIs
|
|
329
|
+
grantTypes String @default("[\"authorization_code\",\"refresh_token\"]")
|
|
330
|
+
responseTypes String @default("[\"code\"]")
|
|
331
|
+
tokenEndpointAuth String @default("none") // "none", "client_secret_basic", "client_secret_post"
|
|
332
|
+
isActive Boolean @default(true)
|
|
333
|
+
|
|
334
|
+
// For user-registered clients (null = dynamic registration)
|
|
335
|
+
userId String?
|
|
336
|
+
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
337
|
+
|
|
338
|
+
createdAt DateTime @default(now())
|
|
339
|
+
updatedAt DateTime @updatedAt
|
|
340
|
+
|
|
341
|
+
// Relations
|
|
342
|
+
tokens OAuthToken[]
|
|
343
|
+
authCodes OAuthAuthorizationCode[]
|
|
344
|
+
|
|
345
|
+
@@index([clientId])
|
|
346
|
+
@@index([userId])
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// OAuth Authorization Codes (short-lived, for auth code flow)
|
|
350
|
+
model OAuthAuthorizationCode {
|
|
351
|
+
id String @id @default(cuid())
|
|
352
|
+
code String @unique
|
|
353
|
+
clientId String
|
|
354
|
+
client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
|
355
|
+
userId String
|
|
356
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
357
|
+
redirectUri String
|
|
358
|
+
scope String?
|
|
359
|
+
codeChallenge String // PKCE code challenge
|
|
360
|
+
codeChallengeMethod String @default("S256")
|
|
361
|
+
expiresAt DateTime
|
|
362
|
+
usedAt DateTime?
|
|
363
|
+
createdAt DateTime @default(now())
|
|
364
|
+
|
|
365
|
+
@@index([code])
|
|
366
|
+
@@index([clientId])
|
|
367
|
+
@@index([userId])
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// OAuth Access/Refresh Tokens
|
|
371
|
+
model OAuthToken {
|
|
372
|
+
id String @id @default(cuid())
|
|
373
|
+
tokenHash String @unique // Hash of access token
|
|
374
|
+
refreshTokenHash String? @unique // Hash of refresh token
|
|
375
|
+
clientId String
|
|
376
|
+
client OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
|
377
|
+
userId String
|
|
378
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
379
|
+
scope String?
|
|
380
|
+
expiresAt DateTime
|
|
381
|
+
refreshExpiresAt DateTime?
|
|
382
|
+
revokedAt DateTime?
|
|
383
|
+
createdAt DateTime @default(now())
|
|
384
|
+
|
|
385
|
+
@@index([tokenHash])
|
|
386
|
+
@@index([refreshTokenHash])
|
|
387
|
+
@@index([clientId])
|
|
388
|
+
@@index([userId])
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Document storage for @-mentionable resources
|
|
392
|
+
model Document {
|
|
393
|
+
id String @id @default(cuid())
|
|
394
|
+
name String // Unique within scope
|
|
395
|
+
content String? @db.Text // For small text docs (stored in DB)
|
|
396
|
+
storageKey String? // For file storage provider (filesystem/S3)
|
|
397
|
+
mimeType String @default("text/plain")
|
|
398
|
+
fileSize Int @default(0)
|
|
399
|
+
charCount Int @default(0) // For hybrid threshold
|
|
400
|
+
|
|
401
|
+
userId String
|
|
402
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
403
|
+
teamId String?
|
|
404
|
+
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
405
|
+
projectId String?
|
|
406
|
+
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
407
|
+
|
|
408
|
+
createdAt DateTime @default(now())
|
|
409
|
+
updatedAt DateTime @updatedAt
|
|
410
|
+
archivedAt DateTime?
|
|
411
|
+
|
|
412
|
+
@@unique([userId, name, teamId, projectId]) // Unique name per scope
|
|
413
|
+
@@index([userId])
|
|
414
|
+
@@index([teamId])
|
|
415
|
+
@@index([projectId])
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Slack Integration - connects a team to their Slack workspace
|
|
419
|
+
model SlackIntegration {
|
|
420
|
+
id String @id @default(cuid())
|
|
421
|
+
|
|
422
|
+
// Team relationship (one-to-one)
|
|
423
|
+
teamId String @unique
|
|
424
|
+
team Team @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
425
|
+
|
|
426
|
+
// Slack workspace info
|
|
427
|
+
slackWorkspaceId String @unique // Slack's team/workspace ID (T01234567)
|
|
428
|
+
slackWorkspaceName String // Human-readable workspace name
|
|
429
|
+
slackBotUserId String // Bot's user ID for @mention detection
|
|
430
|
+
|
|
431
|
+
// Encrypted credentials
|
|
432
|
+
encryptedTokens String // AES-encrypted JSON: {botToken, accessToken?}
|
|
433
|
+
|
|
434
|
+
// Per-team settings
|
|
435
|
+
notificationChannel String? // Default channel for notifications (#general)
|
|
436
|
+
aiChatEnabled Boolean @default(true)
|
|
437
|
+
|
|
438
|
+
// Status tracking
|
|
439
|
+
status String @default("active") // 'active' | 'disconnected' | 'error'
|
|
440
|
+
statusMessage String? // Error details if status='error'
|
|
441
|
+
|
|
442
|
+
// Audit
|
|
443
|
+
installedBy String // User ID who installed
|
|
444
|
+
installedAt DateTime @default(now())
|
|
445
|
+
updatedAt DateTime @updatedAt
|
|
446
|
+
|
|
447
|
+
// Relations
|
|
448
|
+
messageEvents SlackMessageEvent[]
|
|
449
|
+
|
|
450
|
+
@@index([teamId])
|
|
451
|
+
@@index([slackWorkspaceId])
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Slack Message Events - tracks incoming events for deduplication and retry
|
|
455
|
+
model SlackMessageEvent {
|
|
456
|
+
id String @id @default(cuid())
|
|
457
|
+
|
|
458
|
+
// Integration relationship
|
|
459
|
+
integrationId String
|
|
460
|
+
integration SlackIntegration @relation(fields: [integrationId], references: [id], onDelete: Cascade)
|
|
461
|
+
|
|
462
|
+
// Slack message identifiers
|
|
463
|
+
slackEventId String @unique // Slack's event_id for deduplication
|
|
464
|
+
slackChannelId String // Channel ID (C01234567)
|
|
465
|
+
slackThreadTs String? // Parent message timestamp (for threads)
|
|
466
|
+
slackMessageTs String // This message's timestamp
|
|
467
|
+
slackUserId String // User who sent the message
|
|
468
|
+
messageText String? // Original message text (for debugging)
|
|
469
|
+
|
|
470
|
+
// Processing state
|
|
471
|
+
status String @default("pending") // pending|processing|completed|failed
|
|
472
|
+
retryCount Int @default(0)
|
|
473
|
+
lastError String? // Error message if failed
|
|
474
|
+
|
|
475
|
+
// Internal thread linkage (for context continuity)
|
|
476
|
+
internalThreadId String?
|
|
477
|
+
internalThread Thread? @relation(fields: [internalThreadId], references: [id], onDelete: SetNull)
|
|
478
|
+
|
|
479
|
+
// Response tracking
|
|
480
|
+
responseTs String? // Timestamp of bot's response message
|
|
481
|
+
|
|
482
|
+
// Timing
|
|
483
|
+
createdAt DateTime @default(now())
|
|
484
|
+
updatedAt DateTime @updatedAt
|
|
485
|
+
processedAt DateTime?
|
|
486
|
+
|
|
487
|
+
@@index([integrationId])
|
|
488
|
+
@@index([slackEventId])
|
|
489
|
+
@@index([status, updatedAt]) // For retry queries
|
|
490
|
+
@@index([slackChannelId, slackThreadTs]) // For thread context lookup
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// One-time scheduled jobs (delayed execution)
|
|
494
|
+
// Used by the queue scheduler for jobs that need to run at a specific time
|
|
495
|
+
model ScheduledJob {
|
|
496
|
+
id String @id @default(cuid())
|
|
497
|
+
type String // Job type (e.g., 'email:send')
|
|
498
|
+
payload String @db.Text // JSON job payload
|
|
499
|
+
options String @db.Text // JSON EnqueueOptions
|
|
500
|
+
scheduledFor DateTime // When to enqueue to the queue
|
|
501
|
+
status String @default("scheduled") // scheduled | enqueued | cancelled
|
|
502
|
+
error String? // Error message if failed to enqueue
|
|
503
|
+
createdAt DateTime @default(now())
|
|
504
|
+
updatedAt DateTime @updatedAt
|
|
505
|
+
|
|
506
|
+
@@index([status, scheduledFor])
|
|
507
|
+
@@index([type])
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Recurring jobs (cron-style)
|
|
511
|
+
// Scheduler polls these and enqueues jobs according to schedule
|
|
512
|
+
model RecurringJob {
|
|
513
|
+
id String @id @default(cuid())
|
|
514
|
+
name String @unique // Unique job name: "daily-report", "hourly-cleanup"
|
|
515
|
+
type String // Job type to enqueue (e.g., 'report:generate')
|
|
516
|
+
payload String @db.Text // JSON payload for each job
|
|
517
|
+
options String @db.Text // JSON EnqueueOptions (minus scheduling)
|
|
518
|
+
schedule String // Cron: "0 9 * * *" or interval: "every 1 hour"
|
|
519
|
+
timezone String @default("UTC")
|
|
520
|
+
enabled Boolean @default(true)
|
|
521
|
+
nextRunAt DateTime? // Calculated next run time
|
|
522
|
+
lastRunAt DateTime? // Last successful run
|
|
523
|
+
lastError String? // Last error (if any)
|
|
524
|
+
createdAt DateTime @default(now())
|
|
525
|
+
updatedAt DateTime @updatedAt
|
|
526
|
+
|
|
527
|
+
@@index([enabled, nextRunAt])
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Scheduled Prompts (Automations)
|
|
531
|
+
// User or team-configurable prompts that run on a schedule
|
|
532
|
+
model ScheduledPrompt {
|
|
533
|
+
id String @id @default(cuid())
|
|
534
|
+
name String // "Daily Summary", "Weekly Report"
|
|
535
|
+
prompt String @db.Text // The prompt text to run
|
|
536
|
+
agentId String? // Agent to use (null = default)
|
|
537
|
+
|
|
538
|
+
// Schedule
|
|
539
|
+
schedule String // Cron: "0 9 * * 1-5" or interval: "every 1 day"
|
|
540
|
+
timezone String @default("UTC")
|
|
541
|
+
enabled Boolean @default(true)
|
|
542
|
+
|
|
543
|
+
// Notification settings
|
|
544
|
+
notifySlack Boolean @default(true)
|
|
545
|
+
notifyEmail Boolean @default(false)
|
|
546
|
+
emailRecipients String? @db.Text // JSON array of emails
|
|
547
|
+
|
|
548
|
+
// Results storage
|
|
549
|
+
threadId String? // Dedicated thread for results (created on first run)
|
|
550
|
+
thread Thread? @relation(fields: [threadId], references: [id], onDelete: SetNull)
|
|
551
|
+
|
|
552
|
+
// Ownership (one of these must be set)
|
|
553
|
+
userId String?
|
|
554
|
+
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
555
|
+
teamId String?
|
|
556
|
+
team Team? @relation(fields: [teamId], references: [id], onDelete: Cascade)
|
|
557
|
+
|
|
558
|
+
// Tracking
|
|
559
|
+
lastRunAt DateTime?
|
|
560
|
+
lastRunStatus String? // "success" | "failed"
|
|
561
|
+
lastError String?
|
|
562
|
+
runCount Int @default(0)
|
|
563
|
+
|
|
564
|
+
createdAt DateTime @default(now())
|
|
565
|
+
updatedAt DateTime @updatedAt
|
|
566
|
+
|
|
567
|
+
@@index([userId])
|
|
568
|
+
@@index([teamId])
|
|
569
|
+
@@index([enabled])
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Email Verification Codes
|
|
573
|
+
model EmailVerification {
|
|
574
|
+
id String @id @default(cuid())
|
|
575
|
+
code String // 6-digit code (hashed)
|
|
576
|
+
userId String
|
|
577
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
578
|
+
expiresAt DateTime
|
|
579
|
+
usedAt DateTime?
|
|
580
|
+
attempts Int @default(0) // Brute force protection
|
|
581
|
+
createdAt DateTime @default(now())
|
|
582
|
+
|
|
583
|
+
@@index([userId])
|
|
584
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Custom Schema - Your Application Models
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Add your custom models here. This file is preserved during `chat-saas-server db:sync`.
|
|
5
|
+
//
|
|
6
|
+
// You can:
|
|
7
|
+
// - Add new models
|
|
8
|
+
// - Add relations to core models (use the model name, Prisma will find it in base.prisma)
|
|
9
|
+
//
|
|
10
|
+
// Example:
|
|
11
|
+
//
|
|
12
|
+
// model BlogPost {
|
|
13
|
+
// id String @id @default(cuid())
|
|
14
|
+
// title String
|
|
15
|
+
// content String
|
|
16
|
+
// authorId String
|
|
17
|
+
// author User @relation(fields: [authorId], references: [id])
|
|
18
|
+
// createdAt DateTime @default(now())
|
|
19
|
+
// }
|
|
20
|
+
//
|
|
21
|
+
// Note: If you add a relation to a core model (like User above), you may need to
|
|
22
|
+
// add the opposite relation field to that model in base.prisma. After running
|
|
23
|
+
// db:sync, check for validation errors and add any missing relation fields.
|
|
24
|
+
// =============================================================================
|