@friggframework/core 2.0.0--canary.461.61382d8.0 → 2.0.0--canary.461.3d6d8ad.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/database/use-cases/check-migration-status-use-case.js +81 -0
  2. package/generated/prisma-mongodb/client.d.ts +1 -0
  3. package/generated/prisma-mongodb/client.js +4 -0
  4. package/generated/prisma-mongodb/default.d.ts +1 -0
  5. package/generated/prisma-mongodb/default.js +4 -0
  6. package/generated/prisma-mongodb/edge.d.ts +1 -0
  7. package/generated/prisma-mongodb/edge.js +336 -0
  8. package/generated/prisma-mongodb/index-browser.js +318 -0
  9. package/generated/prisma-mongodb/index.d.ts +22993 -0
  10. package/generated/prisma-mongodb/index.js +361 -0
  11. package/generated/prisma-mongodb/package.json +183 -0
  12. package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
  13. package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
  14. package/generated/prisma-mongodb/runtime/binary.d.ts +1 -0
  15. package/generated/prisma-mongodb/runtime/binary.js +289 -0
  16. package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
  17. package/generated/prisma-mongodb/runtime/edge.js +34 -0
  18. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  19. package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
  20. package/generated/prisma-mongodb/runtime/library.d.ts +3977 -0
  21. package/generated/prisma-mongodb/runtime/react-native.js +83 -0
  22. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
  23. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
  24. package/generated/prisma-mongodb/schema.prisma +364 -0
  25. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
  26. package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
  27. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  28. package/generated/prisma-mongodb/wasm.js +343 -0
  29. package/generated/prisma-postgresql/client.d.ts +1 -0
  30. package/generated/prisma-postgresql/client.js +4 -0
  31. package/generated/prisma-postgresql/default.d.ts +1 -0
  32. package/generated/prisma-postgresql/default.js +4 -0
  33. package/generated/prisma-postgresql/edge.d.ts +1 -0
  34. package/generated/prisma-postgresql/edge.js +358 -0
  35. package/generated/prisma-postgresql/index-browser.js +340 -0
  36. package/generated/prisma-postgresql/index.d.ts +25171 -0
  37. package/generated/prisma-postgresql/index.js +383 -0
  38. package/generated/prisma-postgresql/package.json +183 -0
  39. package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
  40. package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
  41. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  42. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  43. package/generated/prisma-postgresql/runtime/binary.d.ts +1 -0
  44. package/generated/prisma-postgresql/runtime/binary.js +289 -0
  45. package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
  46. package/generated/prisma-postgresql/runtime/edge.js +34 -0
  47. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  48. package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
  49. package/generated/prisma-postgresql/runtime/library.d.ts +3977 -0
  50. package/generated/prisma-postgresql/runtime/react-native.js +83 -0
  51. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
  52. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
  53. package/generated/prisma-postgresql/schema.prisma +347 -0
  54. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
  55. package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
  56. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  57. package/generated/prisma-postgresql/wasm.js +365 -0
  58. package/handlers/routers/db-migration.js +52 -0
  59. package/package.json +5 -5
  60. package/application/commands/integration-commands.test.js +0 -123
  61. package/core/Worker.test.js +0 -159
  62. package/database/encryption/encryption-integration.test.js +0 -553
  63. package/database/encryption/encryption-schema-registry.test.js +0 -392
  64. package/database/encryption/field-encryption-service.test.js +0 -525
  65. package/database/encryption/mongo-decryption-fix-verification.test.js +0 -348
  66. package/database/encryption/postgres-decryption-fix-verification.test.js +0 -371
  67. package/database/encryption/postgres-relation-decryption.test.js +0 -245
  68. package/database/encryption/prisma-encryption-extension.test.js +0 -439
  69. package/database/repositories/migration-status-repository-s3.test.js +0 -158
  70. package/database/use-cases/check-encryption-health-use-case.test.js +0 -192
  71. package/database/use-cases/get-migration-status-use-case.test.js +0 -171
  72. package/database/use-cases/run-database-migration-use-case.test.js +0 -310
  73. package/database/use-cases/trigger-database-migration-use-case.test.js +0 -250
  74. package/database/utils/prisma-runner.test.js +0 -486
  75. package/encrypt/Cryptor.test.js +0 -144
  76. package/errors/base-error.test.js +0 -32
  77. package/errors/fetch-error.test.js +0 -79
  78. package/errors/halt-error.test.js +0 -11
  79. package/errors/validation-errors.test.js +0 -120
  80. package/handlers/auth-flow.integration.test.js +0 -147
  81. package/handlers/integration-event-dispatcher.test.js +0 -209
  82. package/handlers/routers/db-migration.test.js +0 -51
  83. package/handlers/routers/health.test.js +0 -210
  84. package/handlers/routers/integration-webhook-routers.test.js +0 -126
  85. package/handlers/use-cases/check-integrations-health-use-case.test.js +0 -125
  86. package/handlers/webhook-flow.integration.test.js +0 -356
  87. package/handlers/workers/db-migration.test.js +0 -50
  88. package/handlers/workers/integration-defined-workers.test.js +0 -184
  89. package/integrations/tests/integration-router-multi-auth.test.js +0 -369
  90. package/integrations/tests/use-cases/create-integration.test.js +0 -131
  91. package/integrations/tests/use-cases/delete-integration-for-user.test.js +0 -150
  92. package/integrations/tests/use-cases/find-integration-context-by-external-entity-id.test.js +0 -92
  93. package/integrations/tests/use-cases/get-integration-for-user.test.js +0 -150
  94. package/integrations/tests/use-cases/get-integration-instance.test.js +0 -176
  95. package/integrations/tests/use-cases/get-integrations-for-user.test.js +0 -176
  96. package/integrations/tests/use-cases/get-possible-integrations.test.js +0 -188
  97. package/integrations/tests/use-cases/update-integration-messages.test.js +0 -142
  98. package/integrations/tests/use-cases/update-integration-status.test.js +0 -103
  99. package/integrations/tests/use-cases/update-integration.test.js +0 -141
  100. package/integrations/use-cases/create-process.test.js +0 -178
  101. package/integrations/use-cases/get-process.test.js +0 -190
  102. package/integrations/use-cases/load-integration-context-full.test.js +0 -329
  103. package/integrations/use-cases/load-integration-context.test.js +0 -114
  104. package/integrations/use-cases/update-process-metrics.test.js +0 -308
  105. package/integrations/use-cases/update-process-state.test.js +0 -256
  106. package/lambda/TimeoutCatcher.test.js +0 -68
  107. package/logs/logger.test.js +0 -76
  108. package/modules/module-hydration.test.js +0 -205
  109. package/modules/requester/requester.test.js +0 -28
  110. package/queues/queuer-util.test.js +0 -132
  111. package/user/tests/use-cases/create-individual-user.test.js +0 -24
  112. package/user/tests/use-cases/create-organization-user.test.js +0 -28
  113. package/user/tests/use-cases/create-token-for-user-id.test.js +0 -19
  114. package/user/tests/use-cases/get-user-from-adopter-jwt.test.js +0 -113
  115. package/user/tests/use-cases/get-user-from-bearer-token.test.js +0 -64
  116. package/user/tests/use-cases/get-user-from-x-frigg-headers.test.js +0 -346
  117. package/user/tests/use-cases/login-user.test.js +0 -220
  118. package/user/tests/user-password-encryption-isolation.test.js +0 -237
  119. package/user/tests/user-password-hashing.test.js +0 -235
  120. package/websocket/repositories/websocket-connection-repository.test.js +0 -227
@@ -1,553 +0,0 @@
1
- /**
2
- * Integration tests for field-level encryption
3
- * Tests transparent encryption/decryption with Prisma for MongoDB and PostgreSQL
4
- *
5
- * These tests verify:
6
- * - Create operations encrypt fields
7
- * - Read operations decrypt fields
8
- * - Update operations handle encryption
9
- * - Upsert operations work correctly
10
- * - FindMany operations decrypt arrays
11
- * - Null/undefined/empty values are handled
12
- * - Database stores encrypted data
13
- *
14
- * Database-Agnostic Design:
15
- * - Uses repository pattern for raw database access (getRawCredentialById)
16
- * - MongoDB: Uses Mongoose for raw collection access
17
- * - PostgreSQL: Uses Prisma $queryRaw for raw SQL queries
18
- * - Field names match Prisma schema (userId, externalId, not user_id/entity_id)
19
- * - Uses externalId (string) for test data instead of userId (ObjectId reference)
20
- *
21
- * Prerequisites:
22
- * - Database must be running and accessible
23
- * - For MongoDB: Replica set recommended (for transactions)
24
- * - For PostgreSQL: Database must exist
25
- * - Database type configured in backend/index.js app definition
26
- *
27
- * Note: Test explicitly passes 'mongodb' to repository factory for testing purposes
28
- */
29
-
30
- // Set default DATABASE_URL for testing if not already set
31
- if (!process.env.DATABASE_URL) {
32
- process.env.DATABASE_URL = 'mongodb://localhost:27017/frigg?replicaSet=rs0';
33
- }
34
-
35
- // Enable encryption for testing (bypass test stage check)
36
- process.env.STAGE = 'integration-test';
37
- process.env.AES_KEY_ID = 'test-key-id';
38
- process.env.AES_KEY = 'test-aes-key-32-characters-long!';
39
-
40
- jest.mock('../config', () => ({
41
- DB_TYPE: 'mongodb',
42
- getDatabaseType: jest.fn(() => 'mongodb'),
43
- PRISMA_LOG_LEVEL: 'error,warn',
44
- PRISMA_QUERY_LOGGING: false,
45
- }));
46
-
47
- const { prisma, connectPrisma, disconnectPrisma } = require('../prisma');
48
- const { createHealthCheckRepository } = require('../repositories/health-check-repository-factory');
49
- const { mongoose } = require('../mongoose');
50
-
51
- describe('Field-Level Encryption Integration Tests', () => {
52
- // Use externalId for test identification (works with both MongoDB and PostgreSQL)
53
- const testExternalId = 'test-encryption-integration-id';
54
- let repository;
55
-
56
- beforeAll(async () => {
57
- await connectPrisma();
58
- // Connect mongoose for raw database queries
59
- if (mongoose.connection.readyState === 0) {
60
- await mongoose.connect(process.env.DATABASE_URL);
61
- }
62
- // Create database-specific repository for raw access
63
- // Pass explicit database type for testing
64
- repository = createHealthCheckRepository('mongodb');
65
- });
66
-
67
- afterAll(async () => {
68
- // Clean up test data - delete all test credentials by externalId
69
- await prisma.credential.deleteMany({
70
- where: { externalId: { startsWith: 'test-encryption-' } },
71
- });
72
- await mongoose.disconnect();
73
- await disconnectPrisma();
74
- });
75
-
76
- afterEach(async () => {
77
- // Clean up after each test
78
- await prisma.credential.deleteMany({
79
- where: { externalId: { startsWith: 'test-encryption-' } },
80
- });
81
- });
82
-
83
- describe('Create Operations', () => {
84
- it('should encrypt sensitive fields on create', async () => {
85
- const credential = await prisma.credential.create({
86
- data: {
87
- externalId: testExternalId,
88
- data: {
89
- access_token: 'secret-token-123',
90
- refresh_token: 'refresh-token-456',
91
- domain: 'example.com',
92
- },
93
- },
94
- });
95
-
96
- // Verify decrypted values returned to application
97
- expect(credential.data.access_token).toBe('secret-token-123');
98
- expect(credential.data.refresh_token).toBe('refresh-token-456');
99
- expect(credential.data.domain).toBe('example.com');
100
-
101
- // Verify raw database has encrypted values
102
- const rawDoc = await repository.getRawCredentialById(credential.id);
103
-
104
- expect(rawDoc.data.access_token).not.toBe('secret-token-123');
105
- expect(rawDoc.data.access_token).toContain(':');
106
- expect(rawDoc.data.refresh_token).not.toBe('refresh-token-456');
107
- expect(rawDoc.data.refresh_token).toContain(':');
108
- // domain should NOT be encrypted (not in schema registry)
109
- expect(rawDoc.data.domain).toBe('example.com');
110
- });
111
-
112
- it('should handle null and undefined values', async () => {
113
- const credential = await prisma.credential.create({
114
- data: {
115
- externalId: testExternalId,
116
- data: {
117
- access_token: null,
118
- domain: 'example.com',
119
- },
120
- },
121
- });
122
-
123
- expect(credential.data.access_token).toBeNull();
124
- expect(credential.data.domain).toBe('example.com');
125
- });
126
-
127
- it('should handle empty strings', async () => {
128
- const credential = await prisma.credential.create({
129
- data: {
130
- externalId: testExternalId,
131
- data: {
132
- access_token: '',
133
- domain: 'example.com',
134
- },
135
- },
136
- });
137
-
138
- // Empty strings should not be encrypted
139
- expect(credential.data.access_token).toBe('');
140
- expect(credential.data.domain).toBe('example.com');
141
- });
142
- });
143
-
144
- describe('Read Operations', () => {
145
- it('should decrypt fields on findUnique', async () => {
146
- // Create with encrypted data
147
- const created = await prisma.credential.create({
148
- data: {
149
- externalId: testExternalId,
150
- data: {
151
- access_token: 'secret-find-unique',
152
- domain: 'findunique.com',
153
- },
154
- },
155
- });
156
-
157
- // Read back
158
- const found = await prisma.credential.findUnique({
159
- where: { id: created.id },
160
- });
161
-
162
- expect(found.data.access_token).toBe('secret-find-unique');
163
- expect(found.data.domain).toBe('findunique.com');
164
- });
165
-
166
- it('should decrypt fields on findFirst', async () => {
167
- await prisma.credential.create({
168
- data: {
169
- externalId: testExternalId,
170
- data: {
171
- access_token: 'secret-find-first',
172
- domain: 'findfirst.com',
173
- },
174
- },
175
- });
176
-
177
- const found = await prisma.credential.findFirst({
178
- where: { externalId: { startsWith: 'test-encryption-' } },
179
- });
180
-
181
- expect(found.data.access_token).toBe('secret-find-first');
182
- expect(found.data.domain).toBe('findfirst.com');
183
- });
184
-
185
- it('should decrypt array of results on findMany', async () => {
186
- // Create multiple credentials
187
- await prisma.credential.createMany({
188
- data: [
189
- {
190
- externalId: 'test-encryption-entity-1',
191
- data: {
192
- access_token: 'secret-1',
193
- domain: 'domain1.com',
194
- },
195
- },
196
- {
197
- externalId: 'test-encryption-entity-2',
198
- data: {
199
- access_token: 'secret-2',
200
- domain: 'domain2.com',
201
- },
202
- },
203
- {
204
- externalId: 'test-encryption-entity-3',
205
- data: {
206
- access_token: 'secret-3',
207
- domain: 'domain3.com',
208
- },
209
- },
210
- ],
211
- });
212
-
213
- const credentials = await prisma.credential.findMany({
214
- where: { externalId: { startsWith: 'test-encryption-' } },
215
- });
216
-
217
- expect(credentials).toHaveLength(3);
218
- expect(credentials[0].data.access_token).toBe('secret-1');
219
- expect(credentials[1].data.access_token).toBe('secret-2');
220
- expect(credentials[2].data.access_token).toBe('secret-3');
221
- });
222
-
223
- it('should return null for non-existent records', async () => {
224
- // Use a valid ObjectId format that doesn't exist in database
225
- const { ObjectId } = require('mongodb');
226
- const nonExistentId = new ObjectId().toString();
227
-
228
- const found = await prisma.credential.findUnique({
229
- where: { id: nonExistentId },
230
- });
231
-
232
- expect(found).toBeNull();
233
- });
234
-
235
- it('should return empty array for no matches', async () => {
236
- const credentials = await prisma.credential.findMany({
237
- where: { externalId: 'non-existent-external-id' },
238
- });
239
-
240
- expect(credentials).toEqual([]);
241
- });
242
- });
243
-
244
- describe('Update Operations', () => {
245
- it('should encrypt new values on update', async () => {
246
- // Create
247
- const created = await prisma.credential.create({
248
- data: {
249
- externalId: testExternalId,
250
- data: {
251
- access_token: 'old-token',
252
- domain: 'old.com',
253
- },
254
- },
255
- });
256
-
257
- // Update
258
- const updated = await prisma.credential.update({
259
- where: { id: created.id },
260
- data: {
261
- data: {
262
- access_token: 'new-token',
263
- domain: 'new.com',
264
- },
265
- },
266
- });
267
-
268
- // Verify decrypted values
269
- expect(updated.data.access_token).toBe('new-token');
270
- expect(updated.data.domain).toBe('new.com');
271
-
272
- // Verify raw database has new encrypted value
273
- const rawDoc = await repository.getRawCredentialById(created.id);
274
-
275
- expect(rawDoc.data.access_token).not.toBe('new-token');
276
- expect(rawDoc.data.access_token).toContain(':');
277
- });
278
-
279
- it('should handle partial updates', async () => {
280
- const created = await prisma.credential.create({
281
- data: {
282
- externalId: testExternalId,
283
- data: {
284
- access_token: 'original-token',
285
- refresh_token: 'original-refresh',
286
- domain: 'original.com',
287
- },
288
- },
289
- });
290
-
291
- // Update only access_token
292
- const updated = await prisma.credential.update({
293
- where: { id: created.id },
294
- data: {
295
- data: {
296
- ...created.data,
297
- access_token: 'updated-token',
298
- },
299
- },
300
- });
301
-
302
- expect(updated.data.access_token).toBe('updated-token');
303
- expect(updated.data.refresh_token).toBe('original-refresh');
304
- expect(updated.data.domain).toBe('original.com');
305
- });
306
- });
307
-
308
- describe('Upsert Operations', () => {
309
- it('should encrypt on insert path', async () => {
310
- // Use a valid ObjectId format that doesn't exist in database
311
- const { ObjectId } = require('mongodb');
312
- const nonExistentId = new ObjectId().toString();
313
-
314
- const upserted = await prisma.credential.upsert({
315
- where: {
316
- id: nonExistentId,
317
- },
318
- create: {
319
- id: nonExistentId,
320
- externalId: 'test-encryption-upsert-entity',
321
- data: {
322
- access_token: 'upsert-create-token',
323
- domain: 'upsert-create.com',
324
- },
325
- },
326
- update: {
327
- data: {
328
- access_token: 'upsert-update-token',
329
- domain: 'upsert-update.com',
330
- },
331
- },
332
- });
333
-
334
- expect(upserted.data.access_token).toBe('upsert-create-token');
335
-
336
- // Verify encryption in database
337
- const rawDoc = await repository.getRawCredentialById(upserted.id);
338
-
339
- expect(rawDoc.data.access_token).not.toBe('upsert-create-token');
340
- expect(rawDoc.data.access_token).toContain(':');
341
- });
342
-
343
- it('should encrypt on update path', async () => {
344
- // Create first
345
- const created = await prisma.credential.create({
346
- data: {
347
- externalId: 'test-encryption-upsert-update-entity',
348
- data: {
349
- access_token: 'original-token',
350
- domain: 'original.com',
351
- },
352
- },
353
- });
354
-
355
- // Upsert (should hit update path)
356
- const upserted = await prisma.credential.upsert({
357
- where: {
358
- id: created.id,
359
- },
360
- create: {
361
- externalId: 'test-encryption-upsert-update-entity',
362
- data: {
363
- access_token: 'create-path-token',
364
- domain: 'create.com',
365
- },
366
- },
367
- update: {
368
- data: {
369
- access_token: 'update-path-token',
370
- domain: 'update.com',
371
- },
372
- },
373
- });
374
-
375
- expect(upserted.data.access_token).toBe('update-path-token');
376
-
377
- // Verify encryption in database
378
- const rawDoc = await repository.getRawCredentialById(upserted.id);
379
-
380
- expect(rawDoc.data.access_token).not.toBe('update-path-token');
381
- expect(rawDoc.data.access_token).toContain(':');
382
- });
383
- });
384
-
385
- describe('Delete Operations', () => {
386
- it('should decrypt deleted record', async () => {
387
- const created = await prisma.credential.create({
388
- data: {
389
- externalId: testExternalId,
390
- data: {
391
- access_token: 'to-be-deleted',
392
- domain: 'delete.com',
393
- },
394
- },
395
- });
396
-
397
- const deleted = await prisma.credential.delete({
398
- where: { id: created.id },
399
- });
400
-
401
- expect(deleted.data.access_token).toBe('to-be-deleted');
402
- expect(deleted.data.domain).toBe('delete.com');
403
- });
404
- });
405
-
406
- describe('CreateMany Operations', () => {
407
- it('should encrypt fields in bulk create', async () => {
408
- const result = await prisma.credential.createMany({
409
- data: [
410
- {
411
- externalId: 'test-encryption-bulk-1',
412
- data: {
413
- access_token: 'bulk-secret-1',
414
- domain: 'bulk1.com',
415
- },
416
- },
417
- {
418
- externalId: 'test-encryption-bulk-2',
419
- data: {
420
- access_token: 'bulk-secret-2',
421
- domain: 'bulk2.com',
422
- },
423
- },
424
- ],
425
- });
426
-
427
- expect(result.count).toBe(2);
428
-
429
- // Verify encryption in database by reading back with Prisma and checking one record's raw form
430
- const credentials = await prisma.credential.findMany({
431
- where: { externalId: { startsWith: 'test-encryption-' } },
432
- });
433
-
434
- // Check raw database for first credential
435
- const rawDoc = await repository.getRawCredentialById(credentials[0].id);
436
- expect(rawDoc.data.access_token).toContain(':');
437
- expect(rawDoc.data.access_token).not.toMatch(/bulk-secret-/);
438
-
439
- // Verify decryption when reading
440
- const tokens = credentials.map((c) => c.data.access_token);
441
- expect(tokens).toContain('bulk-secret-1');
442
- expect(tokens).toContain('bulk-secret-2');
443
- });
444
- });
445
-
446
- describe('Non-Encrypted Fields', () => {
447
- it('should not encrypt fields not in schema registry', async () => {
448
- const credential = await prisma.credential.create({
449
- data: {
450
- externalId: testExternalId,
451
- data: {
452
- access_token: 'secret-token',
453
- domain: 'example.com',
454
- custom_field: 'should-not-encrypt',
455
- },
456
- },
457
- });
458
-
459
- // Verify domain is not encrypted (not in schema)
460
- const rawDoc = await repository.getRawCredentialById(credential.id);
461
-
462
- expect(rawDoc.data.domain).toBe('example.com');
463
- expect(rawDoc.data.custom_field).toBe('should-not-encrypt');
464
-
465
- // access_token should be encrypted (in schema)
466
- expect(rawDoc.data.access_token).not.toBe('secret-token');
467
- });
468
- });
469
-
470
- describe('Error Handling', () => {
471
- it('should handle malformed encrypted data gracefully', async () => {
472
- let created;
473
- try {
474
- // Create a credential first to get a valid ID
475
- created = await prisma.credential.create({
476
- data: {
477
- externalId: 'test-encryption-malformed-entity',
478
- data: {
479
- access_token: 'valid-token',
480
- domain: 'malformed.com',
481
- },
482
- },
483
- });
484
-
485
- // Manually corrupt the encrypted data in the database
486
- // Use realistic corrupted format: 4 colon-separated parts (passes _isEncrypted check)
487
- // but contains invalid base64 that will fail during decryption
488
- const { ObjectId } = require('mongodb');
489
- const dbType = 'mongodb';
490
- if (dbType === 'mongodb') {
491
- const { mongoose } = require('../mongoose');
492
- // Ensure mongoose is connected
493
- if (mongoose.connection.readyState !== 1) {
494
- await mongoose.connect(process.env.DATABASE_URL);
495
- }
496
- await mongoose.connection.db.collection('Credential').updateOne(
497
- { _id: new ObjectId(created.id) },
498
- { $set: { 'data.access_token': 'CORRUPT:INVALID:DATA:FAKE=' } }
499
- );
500
- } else {
501
- // PostgreSQL - use raw query to corrupt data
502
- await prisma.$executeRaw`
503
- UPDATE "Credential"
504
- SET data = jsonb_set(data, '{access_token}', '"CORRUPT:INVALID:DATA:FAKE="')
505
- WHERE id = ${created.id}
506
- `;
507
- }
508
-
509
- // Attempt to read should fail with decryption error
510
- // Fix: Remove async wrapper - expect needs the promise directly for .rejects to work
511
- await expect(
512
- prisma.credential.findUnique({
513
- where: { id: created.id },
514
- })
515
- ).rejects.toThrow();
516
- } finally {
517
- // Cleanup - ensure it runs even if test throws
518
- // Use raw database delete to bypass Prisma encryption extension
519
- // (the encrypted data is corrupted so Prisma delete would fail)
520
- if (created) {
521
- const { ObjectId } = require('mongodb');
522
- const { mongoose } = require('../mongoose');
523
- await mongoose.connection.db.collection('Credential').deleteOne(
524
- { _id: new ObjectId(created.id) }
525
- );
526
- }
527
- }
528
- });
529
- });
530
-
531
- describe('Count and Aggregate Operations', () => {
532
- it('should not interfere with count operations', async () => {
533
- await prisma.credential.createMany({
534
- data: [
535
- {
536
- externalId: 'test-encryption-count-1',
537
- data: { access_token: 'token1', domain: 'count1.com' },
538
- },
539
- {
540
- externalId: 'test-encryption-count-2',
541
- data: { access_token: 'token2', domain: 'count2.com' },
542
- },
543
- ],
544
- });
545
-
546
- const count = await prisma.credential.count({
547
- where: { externalId: { startsWith: 'test-encryption-' } },
548
- });
549
-
550
- expect(count).toBe(2);
551
- });
552
- });
553
- });