@trycompai/db 1.3.17 → 1.3.19-canary.3
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/postinstall.d.ts +11 -0
- package/dist/postinstall.d.ts.map +1 -0
- package/dist/postinstall.js +138 -0
- package/dist/schema.prisma +935 -479
- package/package.json +8 -3
package/dist/schema.prisma
CHANGED
|
@@ -14,279 +14,287 @@ datasource db {
|
|
|
14
14
|
|
|
15
15
|
// ===== attachments.prisma =====
|
|
16
16
|
model Attachment {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('att'::text)"))
|
|
18
|
+
name String
|
|
19
|
+
url String
|
|
20
|
+
type AttachmentType
|
|
21
|
+
entityId String
|
|
22
|
+
entityType AttachmentEntityType
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// Dates
|
|
25
|
+
createdAt DateTime @default(now())
|
|
26
|
+
updatedAt DateTime @updatedAt
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
// Relationships
|
|
29
|
+
organizationId String
|
|
30
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
31
|
+
comment Comment? @relation(fields: [commentId], references: [id])
|
|
32
|
+
commentId String?
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
@@index([entityId, entityType])
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
enum AttachmentEntityType {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
task
|
|
39
|
+
vendor
|
|
40
|
+
risk
|
|
41
|
+
comment
|
|
42
|
+
trust_nda
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
enum AttachmentType {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
image
|
|
47
|
+
video
|
|
48
|
+
audio
|
|
49
|
+
document
|
|
50
|
+
other
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
// ===== auth.prisma =====
|
|
54
55
|
model User {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('usr'::text)"))
|
|
57
|
+
name String
|
|
58
|
+
email String
|
|
59
|
+
emailVerified Boolean
|
|
60
|
+
image String?
|
|
61
|
+
createdAt DateTime @default(now())
|
|
62
|
+
updatedAt DateTime @updatedAt
|
|
63
|
+
lastLogin DateTime?
|
|
64
|
+
emailNotificationsUnsubscribed Boolean @default(false)
|
|
65
|
+
emailPreferences Json? @default("{\"policyNotifications\":true,\"taskReminders\":true,\"weeklyTaskDigest\":true,\"unassignedItemsNotifications\":true}")
|
|
66
|
+
|
|
67
|
+
accounts Account[]
|
|
68
|
+
auditLog AuditLog[]
|
|
69
|
+
integrationResults IntegrationResult[]
|
|
70
|
+
invitations Invitation[]
|
|
71
|
+
members Member[]
|
|
72
|
+
sessions Session[]
|
|
70
73
|
|
|
71
|
-
|
|
74
|
+
@@unique([email])
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
model EmployeeTrainingVideoCompletion {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('evc'::text)"))
|
|
79
|
+
completedAt DateTime?
|
|
80
|
+
videoId String
|
|
78
81
|
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
memberId String
|
|
83
|
+
member Member @relation(fields: [memberId], references: [id], onDelete: Cascade)
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
@@unique([memberId, videoId])
|
|
86
|
+
@@index([memberId])
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
model Session {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('ses'::text)"))
|
|
91
|
+
expiresAt DateTime
|
|
92
|
+
token String
|
|
93
|
+
createdAt DateTime @default(now())
|
|
94
|
+
updatedAt DateTime @updatedAt
|
|
95
|
+
ipAddress String?
|
|
96
|
+
userAgent String?
|
|
97
|
+
userId String
|
|
98
|
+
activeOrganizationId String?
|
|
99
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
100
|
+
|
|
101
|
+
@@unique([token])
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
model Account {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
105
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('acc'::text)"))
|
|
106
|
+
accountId String
|
|
107
|
+
providerId String
|
|
108
|
+
userId String
|
|
109
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
110
|
+
accessToken String?
|
|
111
|
+
refreshToken String?
|
|
112
|
+
idToken String?
|
|
113
|
+
accessTokenExpiresAt DateTime?
|
|
114
|
+
refreshTokenExpiresAt DateTime?
|
|
115
|
+
scope String?
|
|
116
|
+
password String?
|
|
117
|
+
createdAt DateTime
|
|
118
|
+
updatedAt DateTime
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
model Verification {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('ver'::text)"))
|
|
123
|
+
identifier String
|
|
124
|
+
value String
|
|
125
|
+
expiresAt DateTime
|
|
126
|
+
createdAt DateTime @default(now())
|
|
127
|
+
updatedAt DateTime @updatedAt
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
// JWT Plugin - Required by Better Auth JWT plugin
|
|
128
131
|
// https://www.better-auth.com/docs/plugins/jwt
|
|
129
132
|
model Jwks {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('jwk'::text)"))
|
|
134
|
+
publicKey String
|
|
135
|
+
privateKey String
|
|
136
|
+
createdAt DateTime @default(now())
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
@@map("jwks")
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
model Member {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
142
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('mem'::text)"))
|
|
143
|
+
organizationId String
|
|
144
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
145
|
+
userId String
|
|
146
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
147
|
+
role String // Purposefully a string, since BetterAuth doesn't support enums this way
|
|
148
|
+
createdAt DateTime @default(now())
|
|
149
|
+
|
|
150
|
+
department Departments @default(none)
|
|
151
|
+
isActive Boolean @default(true)
|
|
152
|
+
deactivated Boolean @default(false)
|
|
153
|
+
employeeTrainingVideoCompletion EmployeeTrainingVideoCompletion[]
|
|
154
|
+
fleetDmLabelId Int?
|
|
155
|
+
|
|
156
|
+
assignedPolicies Policy[] @relation("PolicyAssignee") // Policies where this member is an assignee
|
|
157
|
+
approvedPolicies Policy[] @relation("PolicyApprover") // Policies where this member is an approver
|
|
158
|
+
approvedSOADocuments SOADocument[] @relation("SOADocumentApprover") // SOA documents where this member is an approver
|
|
159
|
+
risks Risk[]
|
|
160
|
+
tasks Task[]
|
|
161
|
+
vendors Vendor[]
|
|
162
|
+
comments Comment[]
|
|
163
|
+
auditLogs AuditLog[]
|
|
164
|
+
reviewedAccessRequests TrustAccessRequest[] @relation("TrustAccessRequestReviewer")
|
|
165
|
+
issuedGrants TrustAccessGrant[] @relation("IssuedGrants")
|
|
166
|
+
revokedGrants TrustAccessGrant[] @relation("RevokedGrants")
|
|
160
167
|
}
|
|
161
168
|
|
|
162
169
|
model Invitation {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('inv'::text)"))
|
|
171
|
+
organizationId String
|
|
172
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
173
|
+
email String
|
|
174
|
+
role String // Purposefully a string, since BetterAuth doesn't support enums this way
|
|
175
|
+
status String
|
|
176
|
+
expiresAt DateTime
|
|
177
|
+
inviterId String
|
|
178
|
+
user User @relation(fields: [inviterId], references: [id], onDelete: Cascade)
|
|
179
|
+
createdAt DateTime @default(now())
|
|
172
180
|
}
|
|
173
181
|
|
|
174
182
|
// This is only for the app to consume, shouldn't be enforced by DB
|
|
175
183
|
// Otherwise it won't work with Better Auth, as per https://www.better-auth.com/docs/plugins/organization#access-control
|
|
176
184
|
enum Role {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
185
|
+
owner
|
|
186
|
+
admin
|
|
187
|
+
auditor
|
|
188
|
+
employee
|
|
189
|
+
contractor
|
|
182
190
|
}
|
|
183
191
|
|
|
184
192
|
enum PolicyStatus {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
193
|
+
draft
|
|
194
|
+
published
|
|
195
|
+
needs_review
|
|
188
196
|
}
|
|
189
197
|
|
|
190
198
|
|
|
191
199
|
// ===== automation-run.prisma =====
|
|
192
200
|
model EvidenceAutomationRun {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
201
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('ear'::text)"))
|
|
202
|
+
createdAt DateTime @default(now())
|
|
203
|
+
updatedAt DateTime @updatedAt
|
|
204
|
+
|
|
205
|
+
// Relations
|
|
206
|
+
evidenceAutomationId String
|
|
207
|
+
evidenceAutomation EvidenceAutomation @relation(fields: [evidenceAutomationId], references: [id], onDelete: Cascade)
|
|
208
|
+
|
|
209
|
+
// Run details
|
|
210
|
+
status EvidenceAutomationRunStatus @default(pending)
|
|
211
|
+
startedAt DateTime?
|
|
212
|
+
completedAt DateTime?
|
|
213
|
+
|
|
214
|
+
// Results
|
|
215
|
+
success Boolean?
|
|
216
|
+
error String?
|
|
217
|
+
logs Json?
|
|
218
|
+
output Json?
|
|
219
|
+
|
|
220
|
+
// Evaluation
|
|
221
|
+
evaluationStatus EvidenceAutomationEvaluationStatus?
|
|
222
|
+
evaluationReason String?
|
|
223
|
+
|
|
224
|
+
// Metadata
|
|
225
|
+
triggeredBy EvidenceAutomationTrigger @default(scheduled)
|
|
226
|
+
runDuration Int? // in milliseconds
|
|
227
|
+
version Int? // Version number that was executed (null = draft)
|
|
228
|
+
Task Task? @relation(fields: [taskId], references: [id])
|
|
229
|
+
taskId String?
|
|
230
|
+
|
|
231
|
+
@@index([evidenceAutomationId])
|
|
232
|
+
@@index([status])
|
|
233
|
+
@@index([createdAt])
|
|
234
|
+
@@index([version])
|
|
227
235
|
}
|
|
228
236
|
|
|
229
237
|
enum EvidenceAutomationRunStatus {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
238
|
+
pending
|
|
239
|
+
running
|
|
240
|
+
completed
|
|
241
|
+
failed
|
|
242
|
+
cancelled
|
|
235
243
|
}
|
|
236
244
|
|
|
237
245
|
enum EvidenceAutomationTrigger {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
246
|
+
manual
|
|
247
|
+
scheduled
|
|
248
|
+
api
|
|
241
249
|
}
|
|
242
250
|
|
|
243
251
|
enum EvidenceAutomationEvaluationStatus {
|
|
244
|
-
|
|
245
|
-
|
|
252
|
+
pass
|
|
253
|
+
fail
|
|
246
254
|
}
|
|
247
255
|
|
|
248
256
|
|
|
249
257
|
// ===== automation-version.prisma =====
|
|
250
258
|
model EvidenceAutomationVersion {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
259
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('eav'::text)"))
|
|
260
|
+
createdAt DateTime @default(now())
|
|
261
|
+
updatedAt DateTime @updatedAt
|
|
254
262
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
263
|
+
// Relations
|
|
264
|
+
evidenceAutomationId String
|
|
265
|
+
evidenceAutomation EvidenceAutomation @relation(fields: [evidenceAutomationId], references: [id], onDelete: Cascade)
|
|
258
266
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
267
|
+
// Version details
|
|
268
|
+
version Int // Sequential version number (1, 2, 3...)
|
|
269
|
+
scriptKey String // S3 key for this version's script
|
|
270
|
+
publishedBy String? // User ID who published
|
|
271
|
+
changelog String? // Optional description of changes
|
|
264
272
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
273
|
+
@@unique([evidenceAutomationId, version])
|
|
274
|
+
@@index([evidenceAutomationId])
|
|
275
|
+
@@index([createdAt])
|
|
268
276
|
}
|
|
269
277
|
|
|
270
278
|
|
|
271
279
|
// ===== automation.prisma =====
|
|
272
280
|
model EvidenceAutomation {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
281
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('aut'::text)"))
|
|
282
|
+
name String
|
|
283
|
+
description String?
|
|
284
|
+
createdAt DateTime @default(now())
|
|
285
|
+
isEnabled Boolean @default(false)
|
|
278
286
|
|
|
279
|
-
|
|
280
|
-
|
|
287
|
+
chatHistory String?
|
|
288
|
+
evaluationCriteria String?
|
|
281
289
|
|
|
282
|
-
|
|
283
|
-
|
|
290
|
+
taskId String
|
|
291
|
+
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
|
|
284
292
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
293
|
+
// Relations
|
|
294
|
+
runs EvidenceAutomationRun[]
|
|
295
|
+
versions EvidenceAutomationVersion[]
|
|
288
296
|
|
|
289
|
-
|
|
297
|
+
@@index([taskId])
|
|
290
298
|
}
|
|
291
299
|
|
|
292
300
|
|
|
@@ -322,22 +330,22 @@ enum CommentEntityType {
|
|
|
322
330
|
|
|
323
331
|
// ===== context.prisma =====
|
|
324
332
|
model Context {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
333
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('ctx'::text)"))
|
|
334
|
+
organizationId String
|
|
335
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
328
336
|
|
|
329
|
-
|
|
330
|
-
|
|
337
|
+
question String
|
|
338
|
+
answer String
|
|
331
339
|
|
|
332
|
-
|
|
340
|
+
tags String[]
|
|
333
341
|
|
|
334
|
-
|
|
335
|
-
|
|
342
|
+
createdAt DateTime @default(now())
|
|
343
|
+
updatedAt DateTime @updatedAt
|
|
336
344
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
345
|
+
@@index([organizationId])
|
|
346
|
+
@@index([question])
|
|
347
|
+
@@index([answer])
|
|
348
|
+
@@index([tags])
|
|
341
349
|
}
|
|
342
350
|
|
|
343
351
|
|
|
@@ -368,99 +376,101 @@ model Control {
|
|
|
368
376
|
// ===== framework-editor.prisma =====
|
|
369
377
|
// --- Data for Framework Editor ---
|
|
370
378
|
model FrameworkEditorVideo {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
379
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('frk_vi'::text)"))
|
|
380
|
+
title String
|
|
381
|
+
description String
|
|
382
|
+
youtubeId String
|
|
383
|
+
url String
|
|
376
384
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
385
|
+
// Dates
|
|
386
|
+
createdAt DateTime @default(now())
|
|
387
|
+
updatedAt DateTime @default(now()) @updatedAt
|
|
380
388
|
}
|
|
381
389
|
|
|
382
390
|
model FrameworkEditorFramework {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
391
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('frk'::text)"))
|
|
392
|
+
name String // e.g., "soc2", "iso27001"
|
|
393
|
+
version String
|
|
394
|
+
description String
|
|
395
|
+
visible Boolean @default(false)
|
|
388
396
|
|
|
389
|
-
|
|
390
|
-
|
|
397
|
+
requirements FrameworkEditorRequirement[]
|
|
398
|
+
frameworkInstances FrameworkInstance[]
|
|
399
|
+
soaConfigurations SOAFrameworkConfiguration[] // Multiple SOA config versions per framework
|
|
400
|
+
soaDocuments SOADocument[] // SOA documents from organizations
|
|
391
401
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
402
|
+
// Dates
|
|
403
|
+
createdAt DateTime @default(now())
|
|
404
|
+
updatedAt DateTime @default(now()) @updatedAt
|
|
395
405
|
}
|
|
396
406
|
|
|
397
407
|
model FrameworkEditorRequirement {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
408
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('frk_rq'::text)"))
|
|
409
|
+
frameworkId String
|
|
410
|
+
framework FrameworkEditorFramework @relation(fields: [frameworkId], references: [id])
|
|
401
411
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
412
|
+
name String // Original requirement ID within that framework, e.g., "Privacy"
|
|
413
|
+
identifier String @default("") // Unique identifier for the requirement, e.g., "cc1-1"
|
|
414
|
+
description String
|
|
405
415
|
|
|
406
|
-
|
|
407
|
-
|
|
416
|
+
controlTemplates FrameworkEditorControlTemplate[]
|
|
417
|
+
requirementMaps RequirementMap[]
|
|
408
418
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
419
|
+
// Dates
|
|
420
|
+
createdAt DateTime @default(now())
|
|
421
|
+
updatedAt DateTime @default(now()) @updatedAt
|
|
412
422
|
}
|
|
413
423
|
|
|
414
424
|
model FrameworkEditorPolicyTemplate {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
425
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('frk_pt'::text)"))
|
|
426
|
+
name String
|
|
427
|
+
description String
|
|
428
|
+
frequency Frequency // Using the enum from shared.prisma
|
|
429
|
+
department Departments // Using the enum from shared.prisma
|
|
430
|
+
content Json
|
|
421
431
|
|
|
422
|
-
|
|
432
|
+
controlTemplates FrameworkEditorControlTemplate[]
|
|
423
433
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
434
|
+
// Dates
|
|
435
|
+
createdAt DateTime @default(now())
|
|
436
|
+
updatedAt DateTime @default(now()) @updatedAt
|
|
427
437
|
|
|
428
|
-
|
|
429
|
-
|
|
438
|
+
// Instances
|
|
439
|
+
policies Policy[]
|
|
430
440
|
}
|
|
431
441
|
|
|
432
442
|
model FrameworkEditorTaskTemplate {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
443
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('frk_tt'::text)"))
|
|
444
|
+
name String
|
|
445
|
+
description String
|
|
446
|
+
frequency Frequency // Using the enum from shared.prisma
|
|
447
|
+
department Departments // Using the enum from shared.prisma
|
|
438
448
|
|
|
439
|
-
|
|
449
|
+
controlTemplates FrameworkEditorControlTemplate[]
|
|
440
450
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
451
|
+
// Dates
|
|
452
|
+
createdAt DateTime @default(now())
|
|
453
|
+
updatedAt DateTime @default(now()) @updatedAt
|
|
444
454
|
|
|
445
|
-
|
|
446
|
-
|
|
455
|
+
// Instances
|
|
456
|
+
tasks Task[]
|
|
447
457
|
}
|
|
448
458
|
|
|
449
459
|
model FrameworkEditorControlTemplate {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
460
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('frk_ct'::text)"))
|
|
461
|
+
name String
|
|
462
|
+
description String
|
|
453
463
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
464
|
+
policyTemplates FrameworkEditorPolicyTemplate[]
|
|
465
|
+
requirements FrameworkEditorRequirement[]
|
|
466
|
+
taskTemplates FrameworkEditorTaskTemplate[]
|
|
457
467
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
468
|
+
// Dates
|
|
469
|
+
createdAt DateTime @default(now())
|
|
470
|
+
updatedAt DateTime @default(now()) @updatedAt
|
|
461
471
|
|
|
462
|
-
|
|
463
|
-
|
|
472
|
+
// Instances
|
|
473
|
+
controls Control[]
|
|
464
474
|
}
|
|
465
475
|
|
|
466
476
|
|
|
@@ -516,24 +526,58 @@ model IntegrationResult {
|
|
|
516
526
|
}
|
|
517
527
|
|
|
518
528
|
|
|
529
|
+
// ===== knowledge-base-document.prisma =====
|
|
530
|
+
model KnowledgeBaseDocument {
|
|
531
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('kbd'::text)"))
|
|
532
|
+
name String // Original filename
|
|
533
|
+
description String? // Optional user description/notes
|
|
534
|
+
s3Key String // S3 storage key (e.g., "org123/knowledge-base-documents/timestamp-file.pdf")
|
|
535
|
+
fileType String // MIME type (e.g., "application/pdf")
|
|
536
|
+
fileSize Int // File size in bytes
|
|
537
|
+
processingStatus KnowledgeBaseDocumentProcessingStatus @default(pending) // Track indexing status
|
|
538
|
+
processedAt DateTime? // When indexing completed
|
|
539
|
+
triggerRunId String? // Trigger.dev run ID for tracking processing progress
|
|
540
|
+
|
|
541
|
+
// Dates
|
|
542
|
+
createdAt DateTime @default(now())
|
|
543
|
+
updatedAt DateTime @updatedAt
|
|
544
|
+
|
|
545
|
+
// Relationships
|
|
546
|
+
organizationId String
|
|
547
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
548
|
+
|
|
549
|
+
@@index([organizationId])
|
|
550
|
+
@@index([organizationId, processingStatus])
|
|
551
|
+
@@index([s3Key])
|
|
552
|
+
@@index([triggerRunId])
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
enum KnowledgeBaseDocumentProcessingStatus {
|
|
556
|
+
pending // Uploaded but not yet processed/indexed
|
|
557
|
+
processing // Currently being processed/indexed
|
|
558
|
+
completed // Successfully indexed in vector database
|
|
559
|
+
failed // Processing failed
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
|
|
519
563
|
// ===== onboarding.prisma =====
|
|
520
564
|
model Onboarding {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
565
|
+
organizationId String @id
|
|
566
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
567
|
+
policies Boolean @default(false)
|
|
568
|
+
employees Boolean @default(false)
|
|
569
|
+
vendors Boolean @default(false)
|
|
570
|
+
integrations Boolean @default(false)
|
|
571
|
+
risk Boolean @default(false)
|
|
572
|
+
team Boolean @default(false)
|
|
573
|
+
tasks Boolean @default(false)
|
|
574
|
+
callBooked Boolean @default(false)
|
|
575
|
+
companyBookingDetails Json?
|
|
576
|
+
companyDetails Json?
|
|
577
|
+
triggerJobId String?
|
|
578
|
+
triggerJobCompleted Boolean @default(false)
|
|
535
579
|
|
|
536
|
-
|
|
580
|
+
@@index([organizationId])
|
|
537
581
|
}
|
|
538
582
|
|
|
539
583
|
|
|
@@ -555,23 +599,31 @@ model Organization {
|
|
|
555
599
|
fleetDmLabelId Int?
|
|
556
600
|
isFleetSetupCompleted Boolean @default(false)
|
|
557
601
|
|
|
558
|
-
apiKeys
|
|
559
|
-
auditLog
|
|
560
|
-
controls
|
|
561
|
-
frameworkInstances
|
|
562
|
-
integrations
|
|
563
|
-
invitations
|
|
564
|
-
members
|
|
565
|
-
policy
|
|
566
|
-
risk
|
|
567
|
-
vendors
|
|
568
|
-
tasks
|
|
569
|
-
comments
|
|
570
|
-
attachments
|
|
571
|
-
trust
|
|
572
|
-
context
|
|
573
|
-
secrets
|
|
574
|
-
|
|
602
|
+
apiKeys ApiKey[]
|
|
603
|
+
auditLog AuditLog[]
|
|
604
|
+
controls Control[]
|
|
605
|
+
frameworkInstances FrameworkInstance[]
|
|
606
|
+
integrations Integration[]
|
|
607
|
+
invitations Invitation[]
|
|
608
|
+
members Member[]
|
|
609
|
+
policy Policy[]
|
|
610
|
+
risk Risk[]
|
|
611
|
+
vendors Vendor[]
|
|
612
|
+
tasks Task[]
|
|
613
|
+
comments Comment[]
|
|
614
|
+
attachments Attachment[]
|
|
615
|
+
trust Trust[]
|
|
616
|
+
context Context[]
|
|
617
|
+
secrets Secret[]
|
|
618
|
+
trustAccessRequests TrustAccessRequest[]
|
|
619
|
+
trustNdaAgreements TrustNDAAgreement[]
|
|
620
|
+
trustDocuments TrustDocument[]
|
|
621
|
+
trustResources TrustResource[] @relation("OrganizationTrustResources")
|
|
622
|
+
knowledgeBaseDocuments KnowledgeBaseDocument[]
|
|
623
|
+
questionnaires Questionnaire[]
|
|
624
|
+
securityQuestionnaireManualAnswers SecurityQuestionnaireManualAnswer[]
|
|
625
|
+
soaDocuments SOADocument[]
|
|
626
|
+
primaryColor String?
|
|
575
627
|
@@index([slug])
|
|
576
628
|
}
|
|
577
629
|
|
|
@@ -618,21 +670,84 @@ model Policy {
|
|
|
618
670
|
}
|
|
619
671
|
|
|
620
672
|
|
|
673
|
+
// ===== questionnaire.prisma =====
|
|
674
|
+
model Questionnaire {
|
|
675
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('qst'::text)"))
|
|
676
|
+
filename String // Original filename
|
|
677
|
+
s3Key String // S3 storage key for the uploaded file
|
|
678
|
+
fileType String // MIME type (e.g., "application/pdf")
|
|
679
|
+
fileSize Int // File size in bytes
|
|
680
|
+
status QuestionnaireStatus @default(parsing) // Parsing status
|
|
681
|
+
parsedAt DateTime? // When parsing completed
|
|
682
|
+
totalQuestions Int @default(0) // Total number of questions parsed
|
|
683
|
+
answeredQuestions Int @default(0) // Number of questions with answers
|
|
684
|
+
|
|
685
|
+
// Dates
|
|
686
|
+
createdAt DateTime @default(now())
|
|
687
|
+
updatedAt DateTime @updatedAt
|
|
688
|
+
|
|
689
|
+
// Relationships
|
|
690
|
+
organizationId String
|
|
691
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
692
|
+
questions QuestionnaireQuestionAnswer[]
|
|
693
|
+
manualAnswers SecurityQuestionnaireManualAnswer[] // Manual answers saved from this questionnaire
|
|
694
|
+
|
|
695
|
+
@@index([organizationId])
|
|
696
|
+
@@index([organizationId, createdAt])
|
|
697
|
+
@@index([status])
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
model QuestionnaireQuestionAnswer {
|
|
701
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('qqa'::text)"))
|
|
702
|
+
question String // The question text
|
|
703
|
+
answer String? // The answer (nullable if not provided in file or not generated yet)
|
|
704
|
+
status QuestionnaireAnswerStatus @default(untouched) // Answer status
|
|
705
|
+
questionIndex Int // Order/index of the question in the questionnaire
|
|
706
|
+
sources Json? // Sources used for generated answers (array of source objects)
|
|
707
|
+
generatedAt DateTime? // When answer was generated (if status is generated)
|
|
708
|
+
updatedBy String? // User ID who last updated the answer (if manual)
|
|
709
|
+
|
|
710
|
+
// Dates
|
|
711
|
+
createdAt DateTime @default(now())
|
|
712
|
+
updatedAt DateTime @updatedAt
|
|
713
|
+
|
|
714
|
+
// Relationships
|
|
715
|
+
questionnaireId String
|
|
716
|
+
questionnaire Questionnaire @relation(fields: [questionnaireId], references: [id], onDelete: Cascade)
|
|
717
|
+
|
|
718
|
+
@@index([questionnaireId])
|
|
719
|
+
@@index([questionnaireId, questionIndex])
|
|
720
|
+
@@index([status])
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
enum QuestionnaireStatus {
|
|
724
|
+
parsing // Currently being parsed
|
|
725
|
+
completed // Successfully parsed
|
|
726
|
+
failed // Parsing failed
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
enum QuestionnaireAnswerStatus {
|
|
730
|
+
untouched // No answer yet (empty or not generated)
|
|
731
|
+
generated // AI generated answer
|
|
732
|
+
manual // Manually written/edited by user
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
|
|
621
736
|
// ===== requirement.prisma =====
|
|
622
737
|
model RequirementMap {
|
|
623
|
-
|
|
738
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('req'::text)"))
|
|
624
739
|
|
|
625
|
-
|
|
626
|
-
|
|
740
|
+
requirementId String
|
|
741
|
+
requirement FrameworkEditorRequirement @relation(fields: [requirementId], references: [id], onDelete: Cascade)
|
|
627
742
|
|
|
628
|
-
|
|
629
|
-
|
|
743
|
+
controlId String
|
|
744
|
+
control Control @relation(fields: [controlId], references: [id], onDelete: Cascade)
|
|
630
745
|
|
|
631
|
-
|
|
632
|
-
|
|
746
|
+
frameworkInstanceId String
|
|
747
|
+
frameworkInstance FrameworkInstance @relation(fields: [frameworkInstanceId], references: [id], onDelete: Cascade)
|
|
633
748
|
|
|
634
|
-
|
|
635
|
-
|
|
749
|
+
@@unique([controlId, frameworkInstanceId, requirementId])
|
|
750
|
+
@@index([requirementId, frameworkInstanceId])
|
|
636
751
|
}
|
|
637
752
|
|
|
638
753
|
|
|
@@ -699,228 +814,569 @@ enum RiskStatus {
|
|
|
699
814
|
|
|
700
815
|
// ===== secret.prisma =====
|
|
701
816
|
model Secret {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
817
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('sec'::text)"))
|
|
818
|
+
organizationId String @map("organization_id")
|
|
819
|
+
name String
|
|
820
|
+
value String @db.Text // Encrypted value
|
|
821
|
+
description String? @db.Text
|
|
822
|
+
category String? // e.g., "api", "webhook", "database", etc.
|
|
823
|
+
lastUsedAt DateTime? @map("last_used_at")
|
|
824
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
825
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
826
|
+
|
|
827
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
828
|
+
|
|
829
|
+
@@unique([organizationId, name])
|
|
830
|
+
@@map("secrets")
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
// ===== security-questionnaire-manual-answer.prisma =====
|
|
835
|
+
model SecurityQuestionnaireManualAnswer {
|
|
836
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('sqma'::text)"))
|
|
837
|
+
question String // The question text
|
|
838
|
+
answer String // The answer text (required for saved answers)
|
|
839
|
+
tags String[] @default([]) // Optional tags for categorization
|
|
840
|
+
|
|
841
|
+
// Optional reference to original questionnaire (for tracking)
|
|
842
|
+
sourceQuestionnaireId String?
|
|
843
|
+
sourceQuestionnaire Questionnaire? @relation(fields: [sourceQuestionnaireId], references: [id], onDelete: SetNull)
|
|
844
|
+
|
|
845
|
+
// User who created/updated this answer
|
|
846
|
+
createdBy String? // User ID
|
|
847
|
+
updatedBy String? // User ID
|
|
848
|
+
|
|
849
|
+
// Dates
|
|
850
|
+
createdAt DateTime @default(now())
|
|
851
|
+
updatedAt DateTime @updatedAt
|
|
711
852
|
|
|
712
|
-
|
|
853
|
+
// Relationships
|
|
854
|
+
organizationId String
|
|
855
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
713
856
|
|
|
714
|
-
|
|
715
|
-
|
|
857
|
+
@@unique([organizationId, question]) // Prevent duplicate questions per organization
|
|
858
|
+
@@index([organizationId])
|
|
859
|
+
@@index([organizationId, question])
|
|
860
|
+
@@index([tags])
|
|
861
|
+
@@index([createdAt])
|
|
716
862
|
}
|
|
717
863
|
|
|
718
864
|
|
|
719
865
|
// ===== shared.prisma =====
|
|
720
866
|
model ApiKey {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
867
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('apk'::text)"))
|
|
868
|
+
name String
|
|
869
|
+
key String @unique
|
|
870
|
+
salt String?
|
|
871
|
+
createdAt DateTime @default(now())
|
|
872
|
+
expiresAt DateTime?
|
|
873
|
+
lastUsedAt DateTime?
|
|
874
|
+
isActive Boolean @default(true)
|
|
729
875
|
|
|
730
|
-
|
|
731
|
-
|
|
876
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
877
|
+
organizationId String
|
|
732
878
|
|
|
733
|
-
|
|
734
|
-
|
|
879
|
+
@@index([organizationId])
|
|
880
|
+
@@index([key])
|
|
735
881
|
}
|
|
736
882
|
|
|
737
883
|
model AuditLog {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
884
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('aud'::text)"))
|
|
885
|
+
timestamp DateTime @default(now())
|
|
886
|
+
organizationId String
|
|
887
|
+
userId String
|
|
888
|
+
memberId String?
|
|
889
|
+
data Json
|
|
890
|
+
description String?
|
|
891
|
+
entityId String?
|
|
892
|
+
entityType AuditLogEntityType?
|
|
893
|
+
|
|
894
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
895
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
896
|
+
member Member? @relation(fields: [memberId], references: [id], onDelete: Cascade)
|
|
897
|
+
|
|
898
|
+
@@index([userId])
|
|
899
|
+
@@index([organizationId])
|
|
900
|
+
@@index([memberId])
|
|
901
|
+
@@index([entityType])
|
|
756
902
|
}
|
|
757
903
|
|
|
758
904
|
enum AuditLogEntityType {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
905
|
+
organization
|
|
906
|
+
framework
|
|
907
|
+
requirement
|
|
908
|
+
control
|
|
909
|
+
policy
|
|
910
|
+
task
|
|
911
|
+
people
|
|
912
|
+
risk
|
|
913
|
+
vendor
|
|
914
|
+
tests
|
|
915
|
+
integration
|
|
916
|
+
trust
|
|
770
917
|
}
|
|
771
918
|
|
|
772
919
|
model GlobalVendors {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
920
|
+
website String @id @unique
|
|
921
|
+
company_name String?
|
|
922
|
+
legal_name String?
|
|
923
|
+
company_description String?
|
|
924
|
+
company_hq_address String?
|
|
925
|
+
privacy_policy_url String?
|
|
926
|
+
terms_of_service_url String?
|
|
927
|
+
service_level_agreement_url String?
|
|
928
|
+
security_page_url String?
|
|
929
|
+
trust_page_url String?
|
|
930
|
+
security_certifications String[]
|
|
931
|
+
subprocessors String[]
|
|
932
|
+
type_of_company String?
|
|
933
|
+
|
|
934
|
+
approved Boolean @default(false)
|
|
935
|
+
createdAt DateTime @default(now())
|
|
936
|
+
|
|
937
|
+
@@index([website])
|
|
791
938
|
}
|
|
792
939
|
|
|
793
940
|
enum Departments {
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
941
|
+
none
|
|
942
|
+
admin
|
|
943
|
+
gov
|
|
944
|
+
hr
|
|
945
|
+
it
|
|
946
|
+
itsm
|
|
947
|
+
qms
|
|
801
948
|
}
|
|
802
949
|
|
|
803
950
|
enum Frequency {
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
951
|
+
monthly
|
|
952
|
+
quarterly
|
|
953
|
+
yearly
|
|
807
954
|
}
|
|
808
955
|
|
|
809
956
|
enum Likelihood {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
957
|
+
very_unlikely
|
|
958
|
+
unlikely
|
|
959
|
+
possible
|
|
960
|
+
likely
|
|
961
|
+
very_likely
|
|
815
962
|
}
|
|
816
963
|
|
|
817
964
|
enum Impact {
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
965
|
+
insignificant
|
|
966
|
+
minor
|
|
967
|
+
moderate
|
|
968
|
+
major
|
|
969
|
+
severe
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
// ===== soa.prisma =====
|
|
974
|
+
// Statement of Applicability (SOA) Auto-complete Configuration and Answers
|
|
975
|
+
|
|
976
|
+
model SOAFrameworkConfiguration {
|
|
977
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('soa_cfg'::text)"))
|
|
978
|
+
frameworkId String
|
|
979
|
+
framework FrameworkEditorFramework @relation(fields: [frameworkId], references: [id], onDelete: Cascade)
|
|
980
|
+
|
|
981
|
+
// Configuration versioning - allows multiple configurations per framework
|
|
982
|
+
version Int @default(1) // Version number for this configuration (increments when config changes)
|
|
983
|
+
isLatest Boolean @default(true) // Whether this is the latest configuration version
|
|
984
|
+
|
|
985
|
+
// Column definitions for SOA structure (template used when creating new documents)
|
|
986
|
+
columns Json // Array of { name: string, type: string } objects
|
|
987
|
+
// Example: [{ name: "Control ID", type: "string" }, { name: "Control Name", type: "string" }, { name: "Applicable", type: "boolean" }, { name: "Justification", type: "text" }]
|
|
988
|
+
|
|
989
|
+
// Predefined questions for this framework
|
|
990
|
+
// Documents reference a specific configuration version via SOADocument.configurationId
|
|
991
|
+
// Old documents keep their old config version, new documents use new config version
|
|
992
|
+
questions Json // Array of question objects with unique IDs
|
|
993
|
+
// Example: [{ id: "A.5.1.1", text: "Is this control applicable?", columnMapping: "Applicable", controlId: "A.5.1.1" }, ...]
|
|
994
|
+
// IMPORTANT: question.id must be unique and stable - this is what SOAAnswer.questionId references
|
|
995
|
+
|
|
996
|
+
// Dates
|
|
997
|
+
createdAt DateTime @default(now())
|
|
998
|
+
updatedAt DateTime @updatedAt
|
|
999
|
+
|
|
1000
|
+
// Relationships
|
|
1001
|
+
documents SOADocument[]
|
|
1002
|
+
|
|
1003
|
+
@@unique([frameworkId, version]) // Prevent duplicate configuration versions
|
|
1004
|
+
@@index([frameworkId])
|
|
1005
|
+
@@index([frameworkId, version])
|
|
1006
|
+
@@index([frameworkId, isLatest])
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
model SOADocument {
|
|
1010
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('soa_doc'::text)"))
|
|
1011
|
+
|
|
1012
|
+
// Framework and organization context
|
|
1013
|
+
frameworkId String
|
|
1014
|
+
framework FrameworkEditorFramework @relation(fields: [frameworkId], references: [id], onDelete: Cascade)
|
|
1015
|
+
organizationId String
|
|
1016
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
1017
|
+
|
|
1018
|
+
// Configuration reference - references a specific SOAFrameworkConfiguration version
|
|
1019
|
+
// Each document version can use a different configuration version
|
|
1020
|
+
// Old documents keep their old config, new documents use new config
|
|
1021
|
+
configurationId String
|
|
1022
|
+
configuration SOAFrameworkConfiguration @relation(fields: [configurationId], references: [id], onDelete: Cascade)
|
|
1023
|
+
|
|
1024
|
+
// Document versioning
|
|
1025
|
+
version Int @default(1) // Version number for this document (increments yearly)
|
|
1026
|
+
isLatest Boolean @default(true) // Whether this is the latest version
|
|
1027
|
+
|
|
1028
|
+
// Document status
|
|
1029
|
+
status SOADocumentStatus @default(draft) // draft, in_progress, completed
|
|
1030
|
+
|
|
1031
|
+
// Document metadata
|
|
1032
|
+
totalQuestions Int @default(0) // Total number of questions in this document
|
|
1033
|
+
answeredQuestions Int @default(0) // Number of questions with answers
|
|
1034
|
+
|
|
1035
|
+
// Approval tracking
|
|
1036
|
+
preparedBy String @default("Comp AI") // Always "Comp AI"
|
|
1037
|
+
approverId String? // Member ID who will approve this document (set when submitted for approval)
|
|
1038
|
+
approver Member? @relation("SOADocumentApprover", fields: [approverId], references: [id], onDelete: SetNull, onUpdate: Cascade)
|
|
1039
|
+
approvedAt DateTime? // When document was approved
|
|
1040
|
+
|
|
1041
|
+
// Dates
|
|
1042
|
+
completedAt DateTime? // When document was completed
|
|
1043
|
+
createdAt DateTime @default(now())
|
|
1044
|
+
updatedAt DateTime @updatedAt
|
|
1045
|
+
|
|
1046
|
+
// Relationships
|
|
1047
|
+
answers SOAAnswer[]
|
|
1048
|
+
|
|
1049
|
+
@@unique([frameworkId, organizationId, version]) // Prevent duplicate versions
|
|
1050
|
+
@@index([frameworkId, organizationId])
|
|
1051
|
+
@@index([frameworkId, organizationId, version])
|
|
1052
|
+
@@index([frameworkId, organizationId, isLatest])
|
|
1053
|
+
@@index([configurationId])
|
|
1054
|
+
@@index([status])
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
model SOAAnswer {
|
|
1058
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('soa_ans'::text)"))
|
|
1059
|
+
|
|
1060
|
+
// Document context (replaces direct framework/organization link)
|
|
1061
|
+
documentId String
|
|
1062
|
+
document SOADocument @relation(fields: [documentId], references: [id], onDelete: Cascade)
|
|
1063
|
+
|
|
1064
|
+
// Question reference - references question.id from SOADocument.configuration.questions
|
|
1065
|
+
// References the specific configuration version that the document uses
|
|
1066
|
+
// If config changes, old documents still reference their old config version
|
|
1067
|
+
questionId String // Must match a question.id from SOADocument.configuration.questions
|
|
1068
|
+
|
|
1069
|
+
// Answer data - simple text answer
|
|
1070
|
+
answer String? // Text answer (nullable if not generated yet)
|
|
1071
|
+
|
|
1072
|
+
// Answer metadata
|
|
1073
|
+
status SOAAnswerStatus @default(untouched) // untouched, generated, manual
|
|
1074
|
+
sources Json? // Sources used for generated answers (similar to questionnaire)
|
|
1075
|
+
generatedAt DateTime? // When answer was generated
|
|
1076
|
+
|
|
1077
|
+
// Answer versioning (within the document)
|
|
1078
|
+
answerVersion Int @default(1) // Version number for this specific answer
|
|
1079
|
+
isLatestAnswer Boolean @default(true) // Whether this is the latest version of this answer
|
|
1080
|
+
|
|
1081
|
+
// User tracking
|
|
1082
|
+
createdBy String? // User ID who created this answer
|
|
1083
|
+
updatedBy String? // User ID who last updated this answer
|
|
1084
|
+
|
|
1085
|
+
// Dates
|
|
1086
|
+
createdAt DateTime @default(now())
|
|
1087
|
+
updatedAt DateTime @updatedAt
|
|
1088
|
+
|
|
1089
|
+
@@unique([documentId, questionId, answerVersion]) // Prevent duplicate answer versions
|
|
1090
|
+
@@index([documentId])
|
|
1091
|
+
@@index([documentId, questionId])
|
|
1092
|
+
@@index([documentId, questionId, isLatestAnswer])
|
|
1093
|
+
@@index([status])
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
enum SOADocumentStatus {
|
|
1097
|
+
draft // Document is being created/edited
|
|
1098
|
+
in_progress // Document is being generated
|
|
1099
|
+
needs_review // Document is submitted for approval
|
|
1100
|
+
completed // Document is complete and approved
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
enum SOAAnswerStatus {
|
|
1104
|
+
untouched // No answer yet (not generated)
|
|
1105
|
+
generated // AI generated answer
|
|
1106
|
+
manual // Manually written/edited by user
|
|
823
1107
|
}
|
|
824
1108
|
|
|
825
1109
|
|
|
826
1110
|
// ===== task.prisma =====
|
|
827
1111
|
model Task {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1112
|
+
// Metadata
|
|
1113
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('tsk'::text)"))
|
|
1114
|
+
title String
|
|
1115
|
+
description String
|
|
1116
|
+
status TaskStatus @default(todo)
|
|
1117
|
+
frequency TaskFrequency?
|
|
1118
|
+
department Departments? @default(none)
|
|
1119
|
+
order Int @default(0)
|
|
1120
|
+
|
|
1121
|
+
// Dates
|
|
1122
|
+
createdAt DateTime @default(now())
|
|
1123
|
+
updatedAt DateTime @updatedAt
|
|
1124
|
+
lastCompletedAt DateTime?
|
|
1125
|
+
reviewDate DateTime?
|
|
1126
|
+
|
|
1127
|
+
// Relationships
|
|
1128
|
+
assigneeId String?
|
|
1129
|
+
assignee Member? @relation(fields: [assigneeId], references: [id])
|
|
1130
|
+
organizationId String
|
|
1131
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
1132
|
+
taskTemplateId String?
|
|
1133
|
+
taskTemplate FrameworkEditorTaskTemplate? @relation(fields: [taskTemplateId], references: [id])
|
|
1134
|
+
controls Control[]
|
|
1135
|
+
vendors Vendor[]
|
|
1136
|
+
risks Risk[]
|
|
1137
|
+
evidenceAutomations EvidenceAutomation[]
|
|
1138
|
+
|
|
1139
|
+
EvidenceAutomationRun EvidenceAutomationRun[]
|
|
856
1140
|
}
|
|
857
1141
|
|
|
858
1142
|
enum TaskStatus {
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
1143
|
+
todo
|
|
1144
|
+
in_progress
|
|
1145
|
+
done
|
|
1146
|
+
not_relevant
|
|
1147
|
+
failed
|
|
864
1148
|
}
|
|
865
1149
|
|
|
866
1150
|
enum TaskFrequency {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1151
|
+
daily
|
|
1152
|
+
weekly
|
|
1153
|
+
monthly
|
|
1154
|
+
quarterly
|
|
1155
|
+
yearly
|
|
872
1156
|
}
|
|
873
1157
|
|
|
874
1158
|
|
|
875
1159
|
// ===== trust.prisma =====
|
|
876
1160
|
model Trust {
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1161
|
+
organizationId String
|
|
1162
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
1163
|
+
friendlyUrl String? @unique
|
|
1164
|
+
domain String?
|
|
1165
|
+
domainVerified Boolean @default(false)
|
|
1166
|
+
isVercelDomain Boolean @default(false)
|
|
1167
|
+
vercelVerification String?
|
|
1168
|
+
status TrustStatus @default(draft)
|
|
1169
|
+
contactEmail String?
|
|
1170
|
+
|
|
1171
|
+
email String?
|
|
1172
|
+
privacyPolicy String?
|
|
1173
|
+
soc2 Boolean @default(false)
|
|
1174
|
+
soc2type1 Boolean @default(false)
|
|
1175
|
+
soc2type2 Boolean @default(false)
|
|
1176
|
+
iso27001 Boolean @default(false)
|
|
1177
|
+
iso42001 Boolean @default(false)
|
|
1178
|
+
nen7510 Boolean @default(false)
|
|
1179
|
+
gdpr Boolean @default(false)
|
|
1180
|
+
hipaa Boolean @default(false)
|
|
1181
|
+
pci_dss Boolean @default(false)
|
|
1182
|
+
iso9001 Boolean @default(false)
|
|
1183
|
+
|
|
1184
|
+
soc2_status FrameworkStatus @default(started)
|
|
1185
|
+
soc2type1_status FrameworkStatus @default(started)
|
|
1186
|
+
soc2type2_status FrameworkStatus @default(started)
|
|
1187
|
+
iso27001_status FrameworkStatus @default(started)
|
|
1188
|
+
iso42001_status FrameworkStatus @default(started)
|
|
1189
|
+
nen7510_status FrameworkStatus @default(started)
|
|
1190
|
+
gdpr_status FrameworkStatus @default(started)
|
|
1191
|
+
hipaa_status FrameworkStatus @default(started)
|
|
1192
|
+
pci_dss_status FrameworkStatus @default(started)
|
|
1193
|
+
iso9001_status FrameworkStatus @default(started)
|
|
1194
|
+
|
|
1195
|
+
@@id([status, organizationId])
|
|
1196
|
+
@@unique([organizationId])
|
|
1197
|
+
@@index([organizationId])
|
|
1198
|
+
@@index([friendlyUrl])
|
|
913
1199
|
}
|
|
914
1200
|
|
|
915
1201
|
enum TrustStatus {
|
|
916
|
-
|
|
917
|
-
|
|
1202
|
+
draft
|
|
1203
|
+
published
|
|
918
1204
|
}
|
|
919
1205
|
|
|
920
1206
|
enum FrameworkStatus {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1207
|
+
started
|
|
1208
|
+
in_progress
|
|
1209
|
+
compliant
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
enum TrustFramework {
|
|
1213
|
+
iso_27001
|
|
1214
|
+
iso_42001
|
|
1215
|
+
gdpr
|
|
1216
|
+
hipaa
|
|
1217
|
+
soc2_type1
|
|
1218
|
+
soc2_type2
|
|
1219
|
+
pci_dss
|
|
1220
|
+
nen_7510
|
|
1221
|
+
iso_9001
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
model TrustResource {
|
|
1225
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('tcr'::text)"))
|
|
1226
|
+
organizationId String
|
|
1227
|
+
organization Organization @relation("OrganizationTrustResources", fields: [organizationId], references: [id], onDelete: Cascade)
|
|
1228
|
+
framework TrustFramework
|
|
1229
|
+
s3Key String
|
|
1230
|
+
fileName String
|
|
1231
|
+
fileSize Int
|
|
1232
|
+
createdAt DateTime @default(now())
|
|
1233
|
+
updatedAt DateTime @updatedAt
|
|
1234
|
+
|
|
1235
|
+
@@unique([organizationId, framework])
|
|
1236
|
+
@@index([organizationId])
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
model TrustAccessRequest {
|
|
1240
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('tar'::text)"))
|
|
1241
|
+
organizationId String
|
|
1242
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
1243
|
+
|
|
1244
|
+
name String
|
|
1245
|
+
email String
|
|
1246
|
+
company String?
|
|
1247
|
+
jobTitle String?
|
|
1248
|
+
purpose String?
|
|
1249
|
+
requestedDurationDays Int?
|
|
1250
|
+
|
|
1251
|
+
status TrustAccessRequestStatus @default(under_review)
|
|
1252
|
+
reviewerMemberId String?
|
|
1253
|
+
reviewer Member? @relation("TrustAccessRequestReviewer", fields: [reviewerMemberId], references: [id], onDelete: SetNull)
|
|
1254
|
+
reviewedAt DateTime?
|
|
1255
|
+
decisionReason String?
|
|
1256
|
+
|
|
1257
|
+
ipAddress String?
|
|
1258
|
+
userAgent String?
|
|
1259
|
+
|
|
1260
|
+
createdAt DateTime @default(now())
|
|
1261
|
+
updatedAt DateTime @updatedAt
|
|
1262
|
+
|
|
1263
|
+
grant TrustAccessGrant? @relation("RequestGrant")
|
|
1264
|
+
ndaAgreements TrustNDAAgreement[] @relation("RequestNDA")
|
|
1265
|
+
|
|
1266
|
+
@@index([organizationId])
|
|
1267
|
+
@@index([email])
|
|
1268
|
+
@@index([status])
|
|
1269
|
+
@@index([organizationId, status])
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
model TrustAccessGrant {
|
|
1273
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('tag'::text)"))
|
|
1274
|
+
|
|
1275
|
+
accessRequestId String @unique
|
|
1276
|
+
accessRequest TrustAccessRequest @relation("RequestGrant", fields: [accessRequestId], references: [id], onDelete: Cascade)
|
|
1277
|
+
|
|
1278
|
+
subjectEmail String
|
|
1279
|
+
|
|
1280
|
+
status TrustAccessGrantStatus @default(active)
|
|
1281
|
+
expiresAt DateTime
|
|
1282
|
+
|
|
1283
|
+
accessToken String? @unique
|
|
1284
|
+
accessTokenExpiresAt DateTime?
|
|
1285
|
+
|
|
1286
|
+
issuedByMemberId String?
|
|
1287
|
+
issuedBy Member? @relation("IssuedGrants", fields: [issuedByMemberId], references: [id], onDelete: SetNull)
|
|
1288
|
+
|
|
1289
|
+
revokedAt DateTime?
|
|
1290
|
+
revokedByMemberId String?
|
|
1291
|
+
revokedBy Member? @relation("RevokedGrants", fields: [revokedByMemberId], references: [id], onDelete: SetNull)
|
|
1292
|
+
revokeReason String?
|
|
1293
|
+
|
|
1294
|
+
createdAt DateTime @default(now())
|
|
1295
|
+
updatedAt DateTime @updatedAt
|
|
1296
|
+
|
|
1297
|
+
ndaAgreement TrustNDAAgreement? @relation("GrantNDA")
|
|
1298
|
+
|
|
1299
|
+
@@index([accessRequestId])
|
|
1300
|
+
@@index([subjectEmail])
|
|
1301
|
+
@@index([status])
|
|
1302
|
+
@@index([expiresAt])
|
|
1303
|
+
@@index([status, expiresAt])
|
|
1304
|
+
@@index([accessToken])
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
enum TrustAccessRequestStatus {
|
|
1308
|
+
under_review
|
|
1309
|
+
approved
|
|
1310
|
+
denied
|
|
1311
|
+
canceled
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
enum TrustAccessGrantStatus {
|
|
1315
|
+
active
|
|
1316
|
+
expired
|
|
1317
|
+
revoked
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
model TrustNDAAgreement {
|
|
1321
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('tna'::text)"))
|
|
1322
|
+
|
|
1323
|
+
organizationId String
|
|
1324
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
1325
|
+
|
|
1326
|
+
accessRequestId String
|
|
1327
|
+
accessRequest TrustAccessRequest @relation("RequestNDA", fields: [accessRequestId], references: [id], onDelete: Cascade)
|
|
1328
|
+
|
|
1329
|
+
grantId String? @unique
|
|
1330
|
+
grant TrustAccessGrant? @relation("GrantNDA", fields: [grantId], references: [id], onDelete: SetNull)
|
|
1331
|
+
|
|
1332
|
+
signerName String?
|
|
1333
|
+
signerEmail String?
|
|
1334
|
+
|
|
1335
|
+
status TrustNDAStatus @default(pending)
|
|
1336
|
+
|
|
1337
|
+
signToken String @unique
|
|
1338
|
+
signTokenExpiresAt DateTime
|
|
1339
|
+
|
|
1340
|
+
pdfTemplateKey String?
|
|
1341
|
+
pdfSignedKey String?
|
|
1342
|
+
|
|
1343
|
+
signedAt DateTime?
|
|
1344
|
+
|
|
1345
|
+
ipAddress String?
|
|
1346
|
+
userAgent String?
|
|
1347
|
+
|
|
1348
|
+
createdAt DateTime @default(now())
|
|
1349
|
+
updatedAt DateTime @updatedAt
|
|
1350
|
+
|
|
1351
|
+
@@index([organizationId])
|
|
1352
|
+
@@index([accessRequestId])
|
|
1353
|
+
@@index([signToken])
|
|
1354
|
+
@@index([status])
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
enum TrustNDAStatus {
|
|
1358
|
+
pending
|
|
1359
|
+
signed
|
|
1360
|
+
void
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
model TrustDocument {
|
|
1364
|
+
id String @id @default(dbgenerated("generate_prefixed_cuid('tdoc'::text)"))
|
|
1365
|
+
|
|
1366
|
+
organizationId String
|
|
1367
|
+
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
|
1368
|
+
|
|
1369
|
+
name String
|
|
1370
|
+
description String?
|
|
1371
|
+
s3Key String
|
|
1372
|
+
|
|
1373
|
+
isActive Boolean @default(true)
|
|
1374
|
+
|
|
1375
|
+
createdAt DateTime @default(now())
|
|
1376
|
+
updatedAt DateTime @updatedAt
|
|
1377
|
+
|
|
1378
|
+
@@index([organizationId])
|
|
1379
|
+
@@index([organizationId, isActive])
|
|
924
1380
|
}
|
|
925
1381
|
|
|
926
1382
|
|