@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.
@@ -14,279 +14,287 @@ datasource db {
14
14
 
15
15
  // ===== attachments.prisma =====
16
16
  model Attachment {
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
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
- // Dates
25
- createdAt DateTime @default(now())
26
- updatedAt DateTime @updatedAt
24
+ // Dates
25
+ createdAt DateTime @default(now())
26
+ updatedAt DateTime @updatedAt
27
27
 
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?
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
- @@index([entityId, entityType])
34
+ @@index([entityId, entityType])
35
35
  }
36
36
 
37
37
  enum AttachmentEntityType {
38
- task
39
- vendor
40
- risk
41
- comment
38
+ task
39
+ vendor
40
+ risk
41
+ comment
42
+ trust_nda
42
43
  }
43
44
 
44
45
  enum AttachmentType {
45
- image
46
- video
47
- audio
48
- document
49
- other
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('usr'::text)"))
56
- name String
57
- email String
58
- emailVerified Boolean
59
- image String?
60
- createdAt DateTime @default(now())
61
- updatedAt DateTime @updatedAt
62
- lastLogin DateTime?
63
-
64
- accounts Account[]
65
- auditLog AuditLog[]
66
- integrationResults IntegrationResult[]
67
- invitations Invitation[]
68
- members Member[]
69
- sessions Session[]
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
- @@unique([email])
74
+ @@unique([email])
72
75
  }
73
76
 
74
77
  model EmployeeTrainingVideoCompletion {
75
- id String @id @default(dbgenerated("generate_prefixed_cuid('evc'::text)"))
76
- completedAt DateTime?
77
- videoId String
78
+ id String @id @default(dbgenerated("generate_prefixed_cuid('evc'::text)"))
79
+ completedAt DateTime?
80
+ videoId String
78
81
 
79
- memberId String
80
- member Member @relation(fields: [memberId], references: [id], onDelete: Cascade)
82
+ memberId String
83
+ member Member @relation(fields: [memberId], references: [id], onDelete: Cascade)
81
84
 
82
- @@unique([memberId, videoId])
83
- @@index([memberId])
85
+ @@unique([memberId, videoId])
86
+ @@index([memberId])
84
87
  }
85
88
 
86
89
  model Session {
87
- id String @id @default(dbgenerated("generate_prefixed_cuid('ses'::text)"))
88
- expiresAt DateTime
89
- token String
90
- createdAt DateTime @default(now())
91
- updatedAt DateTime @updatedAt
92
- ipAddress String?
93
- userAgent String?
94
- userId String
95
- activeOrganizationId String?
96
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
97
-
98
- @@unique([token])
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('acc'::text)"))
103
- accountId String
104
- providerId String
105
- userId String
106
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
107
- accessToken String?
108
- refreshToken String?
109
- idToken String?
110
- accessTokenExpiresAt DateTime?
111
- refreshTokenExpiresAt DateTime?
112
- scope String?
113
- password String?
114
- createdAt DateTime
115
- updatedAt DateTime
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('ver'::text)"))
120
- identifier String
121
- value String
122
- expiresAt DateTime
123
- createdAt DateTime @default(now())
124
- updatedAt DateTime @updatedAt
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('jwk'::text)"))
131
- publicKey String
132
- privateKey String
133
- createdAt DateTime @default(now())
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
- @@map("jwks")
138
+ @@map("jwks")
136
139
  }
137
140
 
138
141
  model Member {
139
- id String @id @default(dbgenerated("generate_prefixed_cuid('mem'::text)"))
140
- organizationId String
141
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
142
- userId String
143
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
144
- role String // Purposefully a string, since BetterAuth doesn't support enums this way
145
- createdAt DateTime @default(now())
146
-
147
- department Departments @default(none)
148
- isActive Boolean @default(true)
149
- deactivated Boolean @default(false)
150
- employeeTrainingVideoCompletion EmployeeTrainingVideoCompletion[]
151
- fleetDmLabelId Int?
152
-
153
- assignedPolicies Policy[] @relation("PolicyAssignee") // Policies where this member is an assignee
154
- approvedPolicies Policy[] @relation("PolicyApprover") // Policies where this member is an approver
155
- risks Risk[]
156
- tasks Task[]
157
- vendors Vendor[]
158
- comments Comment[]
159
- auditLogs AuditLog[]
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('inv'::text)"))
164
- organizationId String
165
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
166
- email String
167
- role String // Purposefully a string, since BetterAuth doesn't support enums this way
168
- status String
169
- expiresAt DateTime
170
- inviterId String
171
- user User @relation(fields: [inviterId], references: [id], onDelete: Cascade)
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
- owner
178
- admin
179
- auditor
180
- employee
181
- contractor
185
+ owner
186
+ admin
187
+ auditor
188
+ employee
189
+ contractor
182
190
  }
183
191
 
184
192
  enum PolicyStatus {
185
- draft
186
- published
187
- needs_review
193
+ draft
194
+ published
195
+ needs_review
188
196
  }
189
197
 
190
198
 
191
199
  // ===== automation-run.prisma =====
192
200
  model EvidenceAutomationRun {
193
- id String @id @default(dbgenerated("generate_prefixed_cuid('ear'::text)"))
194
- createdAt DateTime @default(now())
195
- updatedAt DateTime @updatedAt
196
-
197
- // Relations
198
- evidenceAutomationId String
199
- evidenceAutomation EvidenceAutomation @relation(fields: [evidenceAutomationId], references: [id], onDelete: Cascade)
200
-
201
- // Run details
202
- status EvidenceAutomationRunStatus @default(pending)
203
- startedAt DateTime?
204
- completedAt DateTime?
205
-
206
- // Results
207
- success Boolean?
208
- error String?
209
- logs Json?
210
- output Json?
211
-
212
- // Evaluation
213
- evaluationStatus EvidenceAutomationEvaluationStatus?
214
- evaluationReason String?
215
-
216
- // Metadata
217
- triggeredBy EvidenceAutomationTrigger @default(scheduled)
218
- runDuration Int? // in milliseconds
219
- version Int? // Version number that was executed (null = draft)
220
- Task Task? @relation(fields: [taskId], references: [id])
221
- taskId String?
222
-
223
- @@index([evidenceAutomationId])
224
- @@index([status])
225
- @@index([createdAt])
226
- @@index([version])
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
- pending
231
- running
232
- completed
233
- failed
234
- cancelled
238
+ pending
239
+ running
240
+ completed
241
+ failed
242
+ cancelled
235
243
  }
236
244
 
237
245
  enum EvidenceAutomationTrigger {
238
- manual
239
- scheduled
240
- api
246
+ manual
247
+ scheduled
248
+ api
241
249
  }
242
250
 
243
251
  enum EvidenceAutomationEvaluationStatus {
244
- pass
245
- fail
252
+ pass
253
+ fail
246
254
  }
247
255
 
248
256
 
249
257
  // ===== automation-version.prisma =====
250
258
  model EvidenceAutomationVersion {
251
- id String @id @default(dbgenerated("generate_prefixed_cuid('eav'::text)"))
252
- createdAt DateTime @default(now())
253
- updatedAt DateTime @updatedAt
259
+ id String @id @default(dbgenerated("generate_prefixed_cuid('eav'::text)"))
260
+ createdAt DateTime @default(now())
261
+ updatedAt DateTime @updatedAt
254
262
 
255
- // Relations
256
- evidenceAutomationId String
257
- evidenceAutomation EvidenceAutomation @relation(fields: [evidenceAutomationId], references: [id], onDelete: Cascade)
263
+ // Relations
264
+ evidenceAutomationId String
265
+ evidenceAutomation EvidenceAutomation @relation(fields: [evidenceAutomationId], references: [id], onDelete: Cascade)
258
266
 
259
- // Version details
260
- version Int // Sequential version number (1, 2, 3...)
261
- scriptKey String // S3 key for this version's script
262
- publishedBy String? // User ID who published
263
- changelog String? // Optional description of changes
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
- @@unique([evidenceAutomationId, version])
266
- @@index([evidenceAutomationId])
267
- @@index([createdAt])
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('aut'::text)"))
274
- name String
275
- description String?
276
- createdAt DateTime @default(now())
277
- isEnabled Boolean @default(false)
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
- chatHistory String?
280
- evaluationCriteria String?
287
+ chatHistory String?
288
+ evaluationCriteria String?
281
289
 
282
- taskId String
283
- task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
290
+ taskId String
291
+ task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
284
292
 
285
- // Relations
286
- runs EvidenceAutomationRun[]
287
- versions EvidenceAutomationVersion[]
293
+ // Relations
294
+ runs EvidenceAutomationRun[]
295
+ versions EvidenceAutomationVersion[]
288
296
 
289
- @@index([taskId])
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('ctx'::text)"))
326
- organizationId String
327
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
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
- question String
330
- answer String
337
+ question String
338
+ answer String
331
339
 
332
- tags String[]
340
+ tags String[]
333
341
 
334
- createdAt DateTime @default(now())
335
- updatedAt DateTime @updatedAt
342
+ createdAt DateTime @default(now())
343
+ updatedAt DateTime @updatedAt
336
344
 
337
- @@index([organizationId])
338
- @@index([question])
339
- @@index([answer])
340
- @@index([tags])
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('frk_vi'::text)"))
372
- title String
373
- description String
374
- youtubeId String
375
- url String
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
- // Dates
378
- createdAt DateTime @default(now())
379
- updatedAt DateTime @default(now()) @updatedAt
385
+ // Dates
386
+ createdAt DateTime @default(now())
387
+ updatedAt DateTime @default(now()) @updatedAt
380
388
  }
381
389
 
382
390
  model FrameworkEditorFramework {
383
- id String @id @default(dbgenerated("generate_prefixed_cuid('frk'::text)"))
384
- name String // e.g., "soc2", "iso27001"
385
- version String
386
- description String
387
- visible Boolean @default(false)
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
- requirements FrameworkEditorRequirement[]
390
- frameworkInstances FrameworkInstance[]
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
- // Dates
393
- createdAt DateTime @default(now())
394
- updatedAt DateTime @default(now()) @updatedAt
402
+ // Dates
403
+ createdAt DateTime @default(now())
404
+ updatedAt DateTime @default(now()) @updatedAt
395
405
  }
396
406
 
397
407
  model FrameworkEditorRequirement {
398
- id String @id @default(dbgenerated("generate_prefixed_cuid('frk_rq'::text)"))
399
- frameworkId String
400
- framework FrameworkEditorFramework @relation(fields: [frameworkId], references: [id])
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
- name String // Original requirement ID within that framework, e.g., "Privacy"
403
- identifier String @default("") // Unique identifier for the requirement, e.g., "cc1-1"
404
- description String
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
- controlTemplates FrameworkEditorControlTemplate[]
407
- requirementMaps RequirementMap[]
416
+ controlTemplates FrameworkEditorControlTemplate[]
417
+ requirementMaps RequirementMap[]
408
418
 
409
- // Dates
410
- createdAt DateTime @default(now())
411
- updatedAt DateTime @default(now()) @updatedAt
419
+ // Dates
420
+ createdAt DateTime @default(now())
421
+ updatedAt DateTime @default(now()) @updatedAt
412
422
  }
413
423
 
414
424
  model FrameworkEditorPolicyTemplate {
415
- id String @id @default(dbgenerated("generate_prefixed_cuid('frk_pt'::text)"))
416
- name String
417
- description String
418
- frequency Frequency // Using the enum from shared.prisma
419
- department Departments // Using the enum from shared.prisma
420
- content Json
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
- controlTemplates FrameworkEditorControlTemplate[]
432
+ controlTemplates FrameworkEditorControlTemplate[]
423
433
 
424
- // Dates
425
- createdAt DateTime @default(now())
426
- updatedAt DateTime @default(now()) @updatedAt
434
+ // Dates
435
+ createdAt DateTime @default(now())
436
+ updatedAt DateTime @default(now()) @updatedAt
427
437
 
428
- // Instances
429
- policies Policy[]
438
+ // Instances
439
+ policies Policy[]
430
440
  }
431
441
 
432
442
  model FrameworkEditorTaskTemplate {
433
- id String @id @default(dbgenerated("generate_prefixed_cuid('frk_tt'::text)"))
434
- name String
435
- description String
436
- frequency Frequency // Using the enum from shared.prisma
437
- department Departments // Using the enum from shared.prisma
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
- controlTemplates FrameworkEditorControlTemplate[]
449
+ controlTemplates FrameworkEditorControlTemplate[]
440
450
 
441
- // Dates
442
- createdAt DateTime @default(now())
443
- updatedAt DateTime @default(now()) @updatedAt
451
+ // Dates
452
+ createdAt DateTime @default(now())
453
+ updatedAt DateTime @default(now()) @updatedAt
444
454
 
445
- // Instances
446
- tasks Task[]
455
+ // Instances
456
+ tasks Task[]
447
457
  }
448
458
 
449
459
  model FrameworkEditorControlTemplate {
450
- id String @id @default(dbgenerated("generate_prefixed_cuid('frk_ct'::text)"))
451
- name String
452
- description String
460
+ id String @id @default(dbgenerated("generate_prefixed_cuid('frk_ct'::text)"))
461
+ name String
462
+ description String
453
463
 
454
- policyTemplates FrameworkEditorPolicyTemplate[]
455
- requirements FrameworkEditorRequirement[]
456
- taskTemplates FrameworkEditorTaskTemplate[]
464
+ policyTemplates FrameworkEditorPolicyTemplate[]
465
+ requirements FrameworkEditorRequirement[]
466
+ taskTemplates FrameworkEditorTaskTemplate[]
457
467
 
458
- // Dates
459
- createdAt DateTime @default(now())
460
- updatedAt DateTime @default(now()) @updatedAt
468
+ // Dates
469
+ createdAt DateTime @default(now())
470
+ updatedAt DateTime @default(now()) @updatedAt
461
471
 
462
- // Instances
463
- controls Control[]
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
- organizationId String @id
522
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
523
- policies Boolean @default(false)
524
- employees Boolean @default(false)
525
- vendors Boolean @default(false)
526
- integrations Boolean @default(false)
527
- risk Boolean @default(false)
528
- team Boolean @default(false)
529
- tasks Boolean @default(false)
530
- callBooked Boolean @default(false)
531
- companyBookingDetails Json?
532
- companyDetails Json?
533
- triggerJobId String?
534
- triggerJobCompleted Boolean @default(false)
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
- @@index([organizationId])
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 ApiKey[]
559
- auditLog AuditLog[]
560
- controls Control[]
561
- frameworkInstances FrameworkInstance[]
562
- integrations Integration[]
563
- invitations Invitation[]
564
- members Member[]
565
- policy Policy[]
566
- risk Risk[]
567
- vendors Vendor[]
568
- tasks Task[]
569
- comments Comment[]
570
- attachments Attachment[]
571
- trust Trust[]
572
- context Context[]
573
- secrets Secret[]
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('req'::text)"))
738
+ id String @id @default(dbgenerated("generate_prefixed_cuid('req'::text)"))
624
739
 
625
- requirementId String
626
- requirement FrameworkEditorRequirement @relation(fields: [requirementId], references: [id], onDelete: Cascade)
740
+ requirementId String
741
+ requirement FrameworkEditorRequirement @relation(fields: [requirementId], references: [id], onDelete: Cascade)
627
742
 
628
- controlId String
629
- control Control @relation(fields: [controlId], references: [id], onDelete: Cascade)
743
+ controlId String
744
+ control Control @relation(fields: [controlId], references: [id], onDelete: Cascade)
630
745
 
631
- frameworkInstanceId String
632
- frameworkInstance FrameworkInstance @relation(fields: [frameworkInstanceId], references: [id], onDelete: Cascade)
746
+ frameworkInstanceId String
747
+ frameworkInstance FrameworkInstance @relation(fields: [frameworkInstanceId], references: [id], onDelete: Cascade)
633
748
 
634
- @@unique([controlId, frameworkInstanceId, requirementId])
635
- @@index([requirementId, frameworkInstanceId])
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('sec'::text)"))
703
- organizationId String @map("organization_id")
704
- name String
705
- value String @db.Text // Encrypted value
706
- description String? @db.Text
707
- category String? // e.g., "api", "webhook", "database", etc.
708
- lastUsedAt DateTime? @map("last_used_at")
709
- createdAt DateTime @default(now()) @map("created_at")
710
- updatedAt DateTime @updatedAt @map("updated_at")
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
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
853
+ // Relationships
854
+ organizationId String
855
+ organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
713
856
 
714
- @@unique([organizationId, name])
715
- @@map("secrets")
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
- id String @id @default(dbgenerated("generate_prefixed_cuid('apk'::text)"))
722
- name String
723
- key String @unique
724
- salt String?
725
- createdAt DateTime @default(now())
726
- expiresAt DateTime?
727
- lastUsedAt DateTime?
728
- isActive Boolean @default(true)
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
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
731
- organizationId String
876
+ organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
877
+ organizationId String
732
878
 
733
- @@index([organizationId])
734
- @@index([key])
879
+ @@index([organizationId])
880
+ @@index([key])
735
881
  }
736
882
 
737
883
  model AuditLog {
738
- id String @id @default(dbgenerated("generate_prefixed_cuid('aud'::text)"))
739
- timestamp DateTime @default(now())
740
- organizationId String
741
- userId String
742
- memberId String?
743
- data Json
744
- description String?
745
- entityId String?
746
- entityType AuditLogEntityType?
747
-
748
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
749
- user User @relation(fields: [userId], references: [id], onDelete: Cascade)
750
- member Member? @relation(fields: [memberId], references: [id], onDelete: Cascade)
751
-
752
- @@index([userId])
753
- @@index([organizationId])
754
- @@index([memberId])
755
- @@index([entityType])
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
- organization
760
- framework
761
- requirement
762
- control
763
- policy
764
- task
765
- people
766
- risk
767
- vendor
768
- tests
769
- integration
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
- website String @id @unique
774
- company_name String?
775
- legal_name String?
776
- company_description String?
777
- company_hq_address String?
778
- privacy_policy_url String?
779
- terms_of_service_url String?
780
- service_level_agreement_url String?
781
- security_page_url String?
782
- trust_page_url String?
783
- security_certifications String[]
784
- subprocessors String[]
785
- type_of_company String?
786
-
787
- approved Boolean @default(false)
788
- createdAt DateTime @default(now())
789
-
790
- @@index([website])
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
- none
795
- admin
796
- gov
797
- hr
798
- it
799
- itsm
800
- qms
941
+ none
942
+ admin
943
+ gov
944
+ hr
945
+ it
946
+ itsm
947
+ qms
801
948
  }
802
949
 
803
950
  enum Frequency {
804
- monthly
805
- quarterly
806
- yearly
951
+ monthly
952
+ quarterly
953
+ yearly
807
954
  }
808
955
 
809
956
  enum Likelihood {
810
- very_unlikely
811
- unlikely
812
- possible
813
- likely
814
- very_likely
957
+ very_unlikely
958
+ unlikely
959
+ possible
960
+ likely
961
+ very_likely
815
962
  }
816
963
 
817
964
  enum Impact {
818
- insignificant
819
- minor
820
- moderate
821
- major
822
- severe
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
- // Metadata
829
- id String @id @default(dbgenerated("generate_prefixed_cuid('tsk'::text)"))
830
- title String
831
- description String
832
- status TaskStatus @default(todo)
833
- frequency TaskFrequency?
834
- department Departments? @default(none)
835
- order Int @default(0)
836
-
837
- // Dates
838
- createdAt DateTime @default(now())
839
- updatedAt DateTime @updatedAt
840
- lastCompletedAt DateTime?
841
- reviewDate DateTime?
842
-
843
- // Relationships
844
- assigneeId String?
845
- assignee Member? @relation(fields: [assigneeId], references: [id])
846
- organizationId String
847
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
848
- taskTemplateId String?
849
- taskTemplate FrameworkEditorTaskTemplate? @relation(fields: [taskTemplateId], references: [id])
850
- controls Control[]
851
- vendors Vendor[]
852
- risks Risk[]
853
- evidenceAutomations EvidenceAutomation[]
854
-
855
- EvidenceAutomationRun EvidenceAutomationRun[]
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
- todo
860
- in_progress
861
- done
862
- not_relevant
863
- failed
1143
+ todo
1144
+ in_progress
1145
+ done
1146
+ not_relevant
1147
+ failed
864
1148
  }
865
1149
 
866
1150
  enum TaskFrequency {
867
- daily
868
- weekly
869
- monthly
870
- quarterly
871
- yearly
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
- organizationId String
878
- organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
879
- friendlyUrl String? @unique
880
- domain String?
881
- domainVerified Boolean @default(false)
882
- isVercelDomain Boolean @default(false)
883
- vercelVerification String?
884
- status TrustStatus @default(draft)
885
- contactEmail String?
886
-
887
- email String?
888
- privacyPolicy String?
889
- soc2 Boolean @default(false)
890
- soc2type1 Boolean @default(false)
891
- soc2type2 Boolean @default(false)
892
- iso27001 Boolean @default(false)
893
- iso42001 Boolean @default(false)
894
- nen7510 Boolean @default(false)
895
- gdpr Boolean @default(false)
896
- hipaa Boolean @default(false)
897
- pci_dss Boolean @default(false)
898
-
899
- soc2_status FrameworkStatus @default(started)
900
- soc2type1_status FrameworkStatus @default(started)
901
- soc2type2_status FrameworkStatus @default(started)
902
- iso27001_status FrameworkStatus @default(started)
903
- iso42001_status FrameworkStatus @default(started)
904
- nen7510_status FrameworkStatus @default(started)
905
- gdpr_status FrameworkStatus @default(started)
906
- hipaa_status FrameworkStatus @default(started)
907
- pci_dss_status FrameworkStatus @default(started)
908
-
909
- @@id([status, organizationId])
910
- @@unique([organizationId])
911
- @@index([organizationId])
912
- @@index([friendlyUrl])
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
- draft
917
- published
1202
+ draft
1203
+ published
918
1204
  }
919
1205
 
920
1206
  enum FrameworkStatus {
921
- started
922
- in_progress
923
- compliant
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