@friggframework/core 2.0.0-next.12 → 2.0.0-next.121

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 (410) hide show
  1. package/.eslintrc.json +18 -1
  2. package/CLAUDE.md +830 -0
  3. package/README.md +996 -50
  4. package/admin-scripts/index.js +52 -0
  5. package/admin-scripts/repositories/admin-script-execution-repository-documentdb.js +21 -0
  6. package/admin-scripts/repositories/admin-script-execution-repository-factory.js +51 -0
  7. package/admin-scripts/repositories/admin-script-execution-repository-interface.js +171 -0
  8. package/admin-scripts/repositories/admin-script-execution-repository-mongo.js +238 -0
  9. package/admin-scripts/repositories/admin-script-execution-repository-postgres.js +278 -0
  10. package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
  11. package/admin-scripts/repositories/script-schedule-repository-factory.js +51 -0
  12. package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
  13. package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
  14. package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
  15. package/application/commands/README.md +451 -0
  16. package/application/commands/admin-script-commands.js +359 -0
  17. package/application/commands/credential-commands.js +262 -0
  18. package/application/commands/entity-commands.js +294 -0
  19. package/application/commands/integration-commands.js +419 -0
  20. package/application/commands/integration-mapping-commands.js +25 -0
  21. package/application/commands/process-commands.js +135 -0
  22. package/application/commands/report-commands.js +188 -0
  23. package/application/commands/scheduler-commands.js +263 -0
  24. package/application/commands/usage-commands.js +56 -0
  25. package/application/commands/user-commands.js +312 -0
  26. package/application/index.js +83 -0
  27. package/artifacts/repositories/artifact-repository-factory.js +19 -0
  28. package/artifacts/repositories/artifact-repository-interface.js +27 -0
  29. package/artifacts/repositories/artifact-repository-local.js +42 -0
  30. package/artifacts/repositories/artifact-repository-s3.js +61 -0
  31. package/assertions/index.js +0 -3
  32. package/core/CLAUDE.md +715 -0
  33. package/core/Worker.js +55 -24
  34. package/core/create-handler.js +121 -38
  35. package/core/index.js +8 -1
  36. package/core/invocation-scope.js +225 -0
  37. package/core/parameters-to-env.js +257 -0
  38. package/core/secrets-to-env.js +7 -6
  39. package/core/ssm-preload.mjs +34 -0
  40. package/credential/repositories/credential-active-type.js +32 -0
  41. package/credential/repositories/credential-repository-documentdb.js +355 -0
  42. package/credential/repositories/credential-repository-factory.js +54 -0
  43. package/credential/repositories/credential-repository-interface.js +113 -0
  44. package/credential/repositories/credential-repository-mongo.js +294 -0
  45. package/credential/repositories/credential-repository-postgres.js +312 -0
  46. package/credential/repositories/credential-repository.js +300 -0
  47. package/credential/use-cases/get-credential-for-user.js +25 -0
  48. package/credential/use-cases/update-authentication-status.js +15 -0
  49. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  50. package/database/adapters/lambda-invoker.js +97 -0
  51. package/database/config.js +147 -0
  52. package/database/documentdb-encryption-service.js +334 -0
  53. package/database/documentdb-utils.js +196 -0
  54. package/database/encryption/README.md +863 -0
  55. package/database/encryption/documentdb-encryption-service.md +3575 -0
  56. package/database/encryption/encryption-schema-registry.js +404 -0
  57. package/database/encryption/field-encryption-service.js +254 -0
  58. package/database/encryption/integration-mapping-encryption.js +97 -0
  59. package/database/encryption/logger.js +82 -0
  60. package/database/encryption/prisma-encryption-extension.js +241 -0
  61. package/database/index.js +21 -21
  62. package/database/prisma.js +182 -0
  63. package/database/repositories/health-check-repository-documentdb.js +138 -0
  64. package/database/repositories/health-check-repository-factory.js +48 -0
  65. package/database/repositories/health-check-repository-interface.js +82 -0
  66. package/database/repositories/health-check-repository-mongodb.js +89 -0
  67. package/database/repositories/health-check-repository-postgres.js +82 -0
  68. package/database/repositories/migration-status-repository-s3.js +137 -0
  69. package/database/use-cases/check-database-health-use-case.js +29 -0
  70. package/database/use-cases/check-database-state-use-case.js +81 -0
  71. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  72. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  73. package/database/use-cases/get-migration-status-use-case.js +93 -0
  74. package/database/use-cases/resolve-migration-via-worker-use-case.js +49 -0
  75. package/database/use-cases/run-database-migration-use-case.js +139 -0
  76. package/database/use-cases/test-encryption-use-case.js +253 -0
  77. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  78. package/database/utils/mongodb-collection-utils.js +94 -0
  79. package/database/utils/mongodb-schema-init.js +108 -0
  80. package/database/utils/prisma-runner.js +491 -0
  81. package/database/utils/prisma-schema-parser.js +182 -0
  82. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  83. package/encrypt/Cryptor.js +34 -168
  84. package/encrypt/index.js +1 -2
  85. package/errors/client-safe-error.js +26 -0
  86. package/errors/fetch-error.js +59 -57
  87. package/errors/index.js +6 -0
  88. package/errors/mapping-already-exists-error.js +14 -0
  89. package/generated/prisma-mongodb/client.d.ts +1 -0
  90. package/generated/prisma-mongodb/client.js +5 -0
  91. package/generated/prisma-mongodb/default.d.ts +1 -0
  92. package/generated/prisma-mongodb/default.js +5 -0
  93. package/generated/prisma-mongodb/edge.d.ts +1 -0
  94. package/generated/prisma-mongodb/edge.js +386 -0
  95. package/generated/prisma-mongodb/index-browser.js +368 -0
  96. package/generated/prisma-mongodb/index.d.ts +27065 -0
  97. package/generated/prisma-mongodb/index.js +411 -0
  98. package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  99. package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  100. package/generated/prisma-mongodb/package.json +183 -0
  101. package/generated/prisma-mongodb/runtime/edge-esm.js +35 -0
  102. package/generated/prisma-mongodb/runtime/edge.js +35 -0
  103. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  104. package/generated/prisma-mongodb/runtime/index-browser.js +17 -0
  105. package/generated/prisma-mongodb/runtime/library.d.ts +3982 -0
  106. package/generated/prisma-mongodb/runtime/library.js +147 -0
  107. package/generated/prisma-mongodb/runtime/react-native.js +84 -0
  108. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +85 -0
  109. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +38 -0
  110. package/generated/prisma-mongodb/schema.prisma +455 -0
  111. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +5 -0
  112. package/generated/prisma-mongodb/wasm-worker-loader.mjs +5 -0
  113. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  114. package/generated/prisma-mongodb/wasm.js +393 -0
  115. package/generated/prisma-postgresql/client.d.ts +1 -0
  116. package/generated/prisma-postgresql/client.js +5 -0
  117. package/generated/prisma-postgresql/default.d.ts +1 -0
  118. package/generated/prisma-postgresql/default.js +5 -0
  119. package/generated/prisma-postgresql/edge.d.ts +1 -0
  120. package/generated/prisma-postgresql/edge.js +407 -0
  121. package/generated/prisma-postgresql/index-browser.js +389 -0
  122. package/generated/prisma-postgresql/index.d.ts +29904 -0
  123. package/generated/prisma-postgresql/index.js +432 -0
  124. package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  125. package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  126. package/generated/prisma-postgresql/package.json +183 -0
  127. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  128. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  129. package/generated/prisma-postgresql/runtime/edge-esm.js +35 -0
  130. package/generated/prisma-postgresql/runtime/edge.js +35 -0
  131. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  132. package/generated/prisma-postgresql/runtime/index-browser.js +17 -0
  133. package/generated/prisma-postgresql/runtime/library.d.ts +3982 -0
  134. package/generated/prisma-postgresql/runtime/library.js +147 -0
  135. package/generated/prisma-postgresql/runtime/react-native.js +84 -0
  136. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +85 -0
  137. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +38 -0
  138. package/generated/prisma-postgresql/schema.prisma +436 -0
  139. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +5 -0
  140. package/generated/prisma-postgresql/wasm-worker-loader.mjs +5 -0
  141. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  142. package/generated/prisma-postgresql/wasm.js +414 -0
  143. package/handlers/WEBHOOKS.md +682 -0
  144. package/handlers/app-definition-loader.js +103 -0
  145. package/handlers/app-handler-helpers.js +20 -6
  146. package/handlers/backend-utils.js +272 -46
  147. package/handlers/database-migration-handler.js +236 -0
  148. package/handlers/integration-event-dispatcher.js +68 -0
  149. package/handlers/middleware/admin-auth.js +73 -0
  150. package/handlers/routers/HEALTHCHECK.md +342 -0
  151. package/handlers/routers/auth.js +4 -15
  152. package/handlers/routers/db-migration.handler.js +29 -0
  153. package/handlers/routers/db-migration.js +329 -0
  154. package/handlers/routers/health.js +518 -0
  155. package/handlers/routers/integration-defined-routers.js +85 -10
  156. package/handlers/routers/integration-webhook-routers.js +87 -0
  157. package/handlers/routers/user.js +27 -5
  158. package/handlers/routers/websocket.js +31 -9
  159. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  160. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  161. package/handlers/workers/db-migration.js +438 -0
  162. package/handlers/workers/dlq-processor.js +89 -0
  163. package/handlers/workers/integration-defined-workers.js +13 -7
  164. package/index.js +123 -47
  165. package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +238 -0
  166. package/infrastructure/scheduler/index.js +33 -0
  167. package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
  168. package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
  169. package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
  170. package/integrations/EXTENSIONS.md +240 -0
  171. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  172. package/integrations/extension.js +254 -0
  173. package/integrations/index.js +20 -10
  174. package/integrations/integration-base.js +777 -74
  175. package/integrations/integration-router.js +399 -180
  176. package/integrations/options.js +1 -1
  177. package/integrations/repositories/config-patch-shared.js +43 -0
  178. package/integrations/repositories/integration-mapping-query-pipeline.js +152 -0
  179. package/integrations/repositories/integration-mapping-query.js +193 -0
  180. package/integrations/repositories/integration-mapping-repository-documentdb.js +406 -0
  181. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  182. package/integrations/repositories/integration-mapping-repository-interface.js +183 -0
  183. package/integrations/repositories/integration-mapping-repository-mongo.js +284 -0
  184. package/integrations/repositories/integration-mapping-repository-postgres.js +403 -0
  185. package/integrations/repositories/integration-mapping-repository.js +185 -0
  186. package/integrations/repositories/integration-repository-documentdb.js +354 -0
  187. package/integrations/repositories/integration-repository-factory.js +51 -0
  188. package/integrations/repositories/integration-repository-interface.js +219 -0
  189. package/integrations/repositories/integration-repository-mongo.js +502 -0
  190. package/integrations/repositories/integration-repository-postgres.js +550 -0
  191. package/integrations/repositories/process-repository-documentdb.js +311 -0
  192. package/integrations/repositories/process-repository-factory.js +53 -0
  193. package/integrations/repositories/process-repository-interface.js +136 -0
  194. package/integrations/repositories/process-repository-mongo.js +262 -0
  195. package/integrations/repositories/process-repository-postgres.js +380 -0
  196. package/integrations/repositories/process-update-ops-shared.js +112 -0
  197. package/integrations/repositories/report-id.js +13 -0
  198. package/integrations/tests/doubles/config-capturing-integration.js +81 -0
  199. package/integrations/tests/doubles/dummy-integration-class.js +113 -0
  200. package/integrations/tests/doubles/test-integration-repository.js +146 -0
  201. package/integrations/use-cases/add-entities-to-integration.js +92 -0
  202. package/integrations/use-cases/create-integration.js +253 -0
  203. package/integrations/use-cases/create-process.js +130 -0
  204. package/integrations/use-cases/delete-integration-for-user.js +130 -0
  205. package/integrations/use-cases/find-integration-by-entity-external-id.js +74 -0
  206. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +76 -0
  207. package/integrations/use-cases/get-integration-for-user.js +78 -0
  208. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  209. package/integrations/use-cases/get-integration-instance.js +83 -0
  210. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  211. package/integrations/use-cases/get-possible-integrations.js +27 -0
  212. package/integrations/use-cases/get-process.js +89 -0
  213. package/integrations/use-cases/index.js +19 -0
  214. package/integrations/use-cases/list-integrations-by-entity-external-id.js +46 -0
  215. package/integrations/use-cases/load-integration-context.js +71 -0
  216. package/integrations/use-cases/patch-integration-config.js +39 -0
  217. package/integrations/use-cases/process-errors.js +28 -0
  218. package/integrations/use-cases/remove-entities-from-integration.js +70 -0
  219. package/integrations/use-cases/update-integration-config.js +32 -0
  220. package/integrations/use-cases/update-integration-messages.js +44 -0
  221. package/integrations/use-cases/update-integration-status.js +32 -0
  222. package/integrations/use-cases/update-integration.js +92 -0
  223. package/integrations/use-cases/update-process-metrics.js +222 -0
  224. package/integrations/use-cases/update-process-state.js +163 -0
  225. package/integrations/utils/assert-entity-ids-input.js +42 -0
  226. package/integrations/utils/map-integration-dto.js +37 -0
  227. package/jest-global-setup-noop.js +3 -0
  228. package/jest-global-teardown-noop.js +3 -0
  229. package/jest.config.js +2 -0
  230. package/logs/.eslintrc.json +26 -1
  231. package/logs/__fixtures__/events.js +82 -0
  232. package/logs/__fixtures__/matchers.js +45 -0
  233. package/logs/__fixtures__/secrets.js +59 -0
  234. package/logs/__fixtures__/vectors.js +329 -0
  235. package/logs/__fixtures__/with-env.js +45 -0
  236. package/logs/context.js +109 -0
  237. package/logs/contract-keys.js +67 -0
  238. package/logs/debug-shims.js +46 -0
  239. package/logs/denied-keys.js +21 -0
  240. package/logs/index.js +14 -3
  241. package/logs/jest-logger-setup.js +25 -0
  242. package/logs/levels.js +71 -0
  243. package/logs/logger-runtime.js +137 -0
  244. package/logs/logger.js +134 -46
  245. package/logs/record.js +276 -0
  246. package/logs/redact.js +328 -0
  247. package/logs/serialize.js +329 -0
  248. package/logs/sinks.js +93 -0
  249. package/logs/summarize-event.js +163 -0
  250. package/{module-plugin → modules}/index.js +0 -10
  251. package/modules/module-factory.js +56 -0
  252. package/modules/module.js +320 -0
  253. package/modules/repositories/module-repository-documentdb.js +350 -0
  254. package/modules/repositories/module-repository-factory.js +40 -0
  255. package/modules/repositories/module-repository-interface.js +145 -0
  256. package/modules/repositories/module-repository-mongo.js +436 -0
  257. package/modules/repositories/module-repository-postgres.js +481 -0
  258. package/modules/repositories/module-repository.js +369 -0
  259. package/modules/requester/api-key.js +52 -0
  260. package/modules/requester/oauth-2.js +561 -0
  261. package/modules/requester/requester.js +605 -0
  262. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  263. package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
  264. package/modules/tests/doubles/test-module-factory.js +16 -0
  265. package/modules/tests/doubles/test-module-repository.js +39 -0
  266. package/modules/use-cases/get-entities-for-user.js +32 -0
  267. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  268. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  269. package/modules/use-cases/get-module-instance-from-type.js +34 -0
  270. package/modules/use-cases/get-module.js +74 -0
  271. package/modules/use-cases/process-authorization-callback.js +294 -0
  272. package/modules/use-cases/refresh-entity-options.js +72 -0
  273. package/modules/use-cases/test-module-auth.js +72 -0
  274. package/modules/utils/map-module-dto.js +20 -0
  275. package/modules/utils/to-credential-id.js +14 -0
  276. package/package.json +92 -52
  277. package/prisma-mongodb/schema.prisma +455 -0
  278. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  279. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  280. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  281. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  282. package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
  283. package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
  284. package/prisma-postgresql/migrations/20260625000000_add_user_organization_id_index/migration.sql +2 -0
  285. package/prisma-postgresql/migrations/20260703000000_add_integration_status_in_creation_in_deletion/migration.sql +11 -0
  286. package/prisma-postgresql/migrations/20260703000001_integration_status_default_in_creation/migration.sql +8 -0
  287. package/prisma-postgresql/migrations/20260705000000_create_usage_counter/migration.sql +26 -0
  288. package/prisma-postgresql/migrations/20260706000000_add_admin_script_execution_and_schedule/migration.sql +61 -0
  289. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  290. package/prisma-postgresql/schema.prisma +436 -0
  291. package/queues/queue-delivery.js +41 -0
  292. package/queues/queuer-util.js +89 -21
  293. package/reporting/README.md +154 -0
  294. package/reporting/builtin-reports.js +6 -0
  295. package/reporting/index.js +13 -0
  296. package/reporting/report-base.js +49 -0
  297. package/reporting/reports/integrations-report.js +221 -0
  298. package/syncs/manager.js +468 -443
  299. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  300. package/syncs/repositories/sync-repository-factory.js +43 -0
  301. package/syncs/repositories/sync-repository-interface.js +109 -0
  302. package/syncs/repositories/sync-repository-mongo.js +239 -0
  303. package/syncs/repositories/sync-repository-postgres.js +319 -0
  304. package/syncs/sync.js +0 -1
  305. package/telemetry/README.md +331 -0
  306. package/telemetry/bind-telemetry-context.js +77 -0
  307. package/telemetry/canonical-counters.js +52 -0
  308. package/telemetry/exporters.js +85 -0
  309. package/telemetry/index.js +26 -0
  310. package/telemetry/instrument-handler.js +104 -0
  311. package/telemetry/no-op-telemetry.js +71 -0
  312. package/telemetry/north-star.js +103 -0
  313. package/telemetry/otel-telemetry.js +232 -0
  314. package/telemetry/plugin-subscribers.js +77 -0
  315. package/telemetry/telemetry-config.js +120 -0
  316. package/telemetry/telemetry-context.js +51 -0
  317. package/telemetry/telemetry-event-bus.js +58 -0
  318. package/telemetry/telemetry-runtime.js +164 -0
  319. package/telemetry/telemetry-service.js +52 -0
  320. package/telemetry/usage-rollup-subscriber.js +116 -0
  321. package/token/repositories/token-repository-documentdb.js +137 -0
  322. package/token/repositories/token-repository-factory.js +40 -0
  323. package/token/repositories/token-repository-interface.js +131 -0
  324. package/token/repositories/token-repository-mongo.js +219 -0
  325. package/token/repositories/token-repository-postgres.js +264 -0
  326. package/token/repositories/token-repository.js +219 -0
  327. package/types/associations/index.d.ts +0 -17
  328. package/types/core/index.d.ts +12 -4
  329. package/types/database/index.d.ts +10 -2
  330. package/types/encrypt/index.d.ts +5 -3
  331. package/types/errors/index.d.ts +24 -10
  332. package/types/integrations/index.d.ts +3 -8
  333. package/types/logs/index.d.ts +61 -2
  334. package/types/module-plugin/index.d.ts +20 -69
  335. package/types/syncs/index.d.ts +0 -17
  336. package/usage/README.md +54 -0
  337. package/usage/index.js +17 -0
  338. package/usage/repositories/usage-repository-documentdb.js +194 -0
  339. package/usage/repositories/usage-repository-factory.js +25 -0
  340. package/usage/repositories/usage-repository-interface.js +37 -0
  341. package/usage/repositories/usage-repository-prisma.js +146 -0
  342. package/usage/tracked-metrics.js +38 -0
  343. package/usage/usage-windows.js +24 -0
  344. package/user/repositories/user-repository-documentdb.js +426 -0
  345. package/user/repositories/user-repository-factory.js +52 -0
  346. package/user/repositories/user-repository-interface.js +214 -0
  347. package/user/repositories/user-repository-mongo.js +323 -0
  348. package/user/repositories/user-repository-postgres.js +377 -0
  349. package/user/tests/doubles/test-user-repository.js +72 -0
  350. package/user/use-cases/authenticate-user.js +143 -0
  351. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  352. package/user/use-cases/create-individual-user.js +61 -0
  353. package/user/use-cases/create-organization-user.js +47 -0
  354. package/user/use-cases/create-token-for-user-id.js +30 -0
  355. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  356. package/user/use-cases/get-user-from-bearer-token.js +82 -0
  357. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  358. package/user/use-cases/login-user.js +122 -0
  359. package/user/user.js +125 -0
  360. package/utils/backend-path.js +38 -0
  361. package/utils/index.js +6 -0
  362. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  363. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  364. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  365. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  366. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  367. package/websocket/repositories/websocket-connection-repository.js +161 -0
  368. package/assertions/is-equal.js +0 -17
  369. package/associations/model.js +0 -54
  370. package/database/models/IndividualUser.js +0 -76
  371. package/database/models/OrganizationUser.js +0 -29
  372. package/database/models/State.js +0 -9
  373. package/database/models/Token.js +0 -70
  374. package/database/models/UserModel.js +0 -7
  375. package/database/models/WebsocketConnection.js +0 -49
  376. package/database/mongo.js +0 -45
  377. package/database/mongoose.js +0 -5
  378. package/encrypt/Cryptor.test.js +0 -32
  379. package/encrypt/encrypt.js +0 -132
  380. package/encrypt/encrypt.test.js +0 -1069
  381. package/encrypt/test-encrypt.js +0 -107
  382. package/errors/base-error.test.js +0 -32
  383. package/errors/fetch-error.test.js +0 -79
  384. package/errors/halt-error.test.js +0 -11
  385. package/errors/validation-errors.test.js +0 -120
  386. package/handlers/routers/middleware/loadUser.js +0 -15
  387. package/handlers/routers/middleware/requireLoggedInUser.js +0 -12
  388. package/integrations/create-frigg-backend.js +0 -31
  389. package/integrations/integration-factory.js +0 -251
  390. package/integrations/integration-mapping.js +0 -43
  391. package/integrations/integration-model.js +0 -46
  392. package/integrations/integration-user.js +0 -144
  393. package/integrations/test/integration-base.test.js +0 -144
  394. package/lambda/TimeoutCatcher.test.js +0 -68
  395. package/logs/logger.test.js +0 -76
  396. package/module-plugin/auther.js +0 -393
  397. package/module-plugin/credential.js +0 -22
  398. package/module-plugin/entity-manager.js +0 -70
  399. package/module-plugin/entity.js +0 -46
  400. package/module-plugin/manager.js +0 -169
  401. package/module-plugin/module-factory.js +0 -61
  402. package/module-plugin/requester/api-key.js +0 -36
  403. package/module-plugin/requester/oauth-2.js +0 -219
  404. package/module-plugin/requester/requester.js +0 -165
  405. package/module-plugin/requester/requester.test.js +0 -28
  406. package/module-plugin/test/auther.test.js +0 -97
  407. package/syncs/model.js +0 -62
  408. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  409. /package/{module-plugin → modules}/requester/basic.js +0 -0
  410. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
@@ -1,36 +1,41 @@
1
+ /**
2
+ * Cryptor - Encryption Service Adapter
3
+ *
4
+ * Infrastructure Layer adapter for AWS KMS and local AES encryption.
5
+ * Provides envelope encryption pattern for field-level encryption.
6
+ *
7
+ * Envelope Encryption Pattern:
8
+ * 1. Generate Data Encryption Key (DEK) via KMS or locally
9
+ * 2. Encrypt field value with DEK using AES-256-CTR
10
+ * 3. Encrypt DEK with Master Key (KMS CMK or AES_KEY)
11
+ * 4. Return format: "keyId:encryptedText:encryptedKey"
12
+ *
13
+ * Benefits:
14
+ * - Reduces KMS API calls (unique DEK per operation)
15
+ * - Master key never leaves KMS
16
+ * - Enables key rotation without re-encrypting data
17
+ */
18
+
1
19
  const crypto = require('crypto');
2
- const AWS = require('aws-sdk');
3
- const { get, set } = require('lodash');
20
+ const { KMSClient, GenerateDataKeyCommand, DecryptCommand } = require('@aws-sdk/client-kms');
4
21
  const aes = require('./aes');
5
22
 
6
- const hasValue = (a) => a !== undefined && a !== null && a !== '';
7
-
8
23
  class Cryptor {
9
- constructor({ fields, shouldUseAws }) {
24
+ constructor({ shouldUseAws }) {
10
25
  this.shouldUseAws = shouldUseAws;
11
- this.fields = fields;
12
-
13
- this.permutationsByField = {};
14
-
15
- for (const field of fields) {
16
- this.permutationsByField[field] = this.calculatePermutations(
17
- field.split('.')
18
- );
19
- }
20
26
  }
21
27
 
22
28
  async generateDataKey() {
23
29
  if (this.shouldUseAws) {
24
- const kmsClient = new AWS.KMS();
25
- const dataKey = await kmsClient
26
- .generateDataKey({
27
- KeyId: process.env.KMS_KEY_ARN,
28
- KeySpec: 'AES_256',
29
- })
30
- .promise();
30
+ const kmsClient = new KMSClient({});
31
+ const command = new GenerateDataKeyCommand({
32
+ KeyId: process.env.KMS_KEY_ARN,
33
+ KeySpec: 'AES_256',
34
+ });
35
+ const dataKey = await kmsClient.send(command);
31
36
 
32
37
  const keyId = Buffer.from(dataKey.KeyId).toString('base64');
33
- const encryptedKey = dataKey.CiphertextBlob.toString('base64');
38
+ const encryptedKey = Buffer.from(dataKey.CiphertextBlob).toString('base64');
34
39
  const plaintext = dataKey.Plaintext;
35
40
  return { keyId, encryptedKey, plaintext };
36
41
  }
@@ -56,7 +61,7 @@ class Cryptor {
56
61
  const key = availableKeys[keyId];
57
62
 
58
63
  if (!key) {
59
- throw new Error(`No encryption key found with ID "${keyId}"`);
64
+ throw new Error('Encryption key not found');
60
65
  }
61
66
 
62
67
  return key;
@@ -64,13 +69,12 @@ class Cryptor {
64
69
 
65
70
  async decryptDataKey(keyId, encryptedKey) {
66
71
  if (this.shouldUseAws) {
67
- const kmsClient = new AWS.KMS();
68
- const dataKey = await kmsClient
69
- .decrypt({
70
- KeyId: keyId,
71
- CiphertextBlob: encryptedKey,
72
- })
73
- .promise();
72
+ const kmsClient = new KMSClient({});
73
+ const command = new DecryptCommand({
74
+ KeyId: keyId,
75
+ CiphertextBlob: encryptedKey,
76
+ });
77
+ const dataKey = await kmsClient.send(command);
74
78
 
75
79
  return dataKey.Plaintext;
76
80
  }
@@ -79,146 +83,9 @@ class Cryptor {
79
83
  return aes.decrypt(encryptedKey, key);
80
84
  }
81
85
 
82
- // If the field has a value in the document, apply async function f to that field.
83
- async setInDocument(doc, f) {
84
- // Use the Mongoose document get/set when available (not for insertMany)
85
- if (doc.get) {
86
- for (const field of this.fields) {
87
- const value = doc.get(field);
88
- if (hasValue(value)) {
89
- doc.set(field, await f(value));
90
- }
91
- }
92
- return;
93
- }
94
-
95
- // Otherwise use permutations.
96
- for (const field of this.fields) {
97
- const updatedDoc = await this.applyAll(doc, field, f);
98
- Object.assign(doc, updatedDoc);
99
- }
100
- }
101
-
102
- // Calculate all possible permutations for a nested field. For example a
103
- // field "deeply.nested.field" might be referred to in a Mongo query as
104
- // { deeply: { 'nested.field': {} } } or { 'deeply.nested.field': {} }
105
- // etc. For a given path, this gives all path parts to check in a format
106
- // that lodash understands when using get and set with an array of path
107
- // parts e.g. get(o, ['deeply', 'nested.parts'])
108
- calculatePermutations = (parts) => {
109
- if (!parts.length) return [];
110
- if (parts.length === 1) return [parts];
111
-
112
- const combos = [];
113
-
114
- for (let i = 0; i < parts.length; i += 1) {
115
- const frontPath = parts.slice(0, i + 1).join('.');
116
- const rest = parts.slice(i + 1);
117
-
118
- if (rest.length) {
119
- combos.push(
120
- ...this.calculatePermutations(rest).map((child) => [
121
- frontPath,
122
- ...child,
123
- ])
124
- );
125
- } else {
126
- combos.push([frontPath]);
127
- }
128
- }
129
-
130
- return combos;
131
- };
132
-
133
- // Encrypt all possible permutations of a field (possibly nested), if there
134
- // is a value at that path permutation.
135
- async applyAll(o, field, f) {
136
- const clone = { ...o };
137
- const permutations = this.permutationsByField[field];
138
-
139
- for (const path of permutations) {
140
- const value = get(o, path);
141
- if (hasValue(value)) {
142
- set(clone, path, await f(value));
143
- }
144
- }
145
-
146
- return clone;
147
- }
148
-
149
- async processFieldsInDocuments(docs, f) {
150
- const promises = docs
151
- .filter(Boolean)
152
- .flatMap((doc) => this.setInDocument(doc, f));
153
-
154
- return Promise.all(promises);
155
- }
156
-
157
- async encryptFieldsInDocuments(docs) {
158
- await this.processFieldsInDocuments(docs, this.encrypt.bind(this));
159
- }
160
-
161
- async decryptFieldsInDocuments(docs) {
162
- await this.processFieldsInDocuments(docs, this.decrypt.bind(this));
163
- }
164
-
165
- async encryptFieldsInQuery(query) {
166
- for (const field of this.fields) {
167
- const originalUpdate = query.getUpdate();
168
- const updatedUpdate = await this.applyAll(
169
- originalUpdate,
170
- field,
171
- this.encrypt.bind(this)
172
- );
173
-
174
- if (originalUpdate.$set) {
175
- const updatedSetUpdate = await this.applyAll(
176
- originalUpdate.$set,
177
- field,
178
- this.encrypt.bind(this)
179
- );
180
- updatedUpdate.$set = { ...updatedSetUpdate };
181
- }
182
-
183
- if (originalUpdate.$setOnInsert) {
184
- const updatedSetOnInsertUpdate = await this.applyAll(
185
- originalUpdate.$setOnInsert,
186
- field,
187
- this.encrypt.bind(this)
188
- );
189
- updatedUpdate.$setOnInsert = { ...updatedSetOnInsertUpdate };
190
- }
191
-
192
- query.setUpdate(updatedUpdate);
193
- }
194
- }
195
-
196
- expectNotToUpdateManyEncrypted(update) {
197
- for (const field of this.fields) {
198
- if (update.$set && hasValue(update.$set[field])) {
199
- throw new Error(
200
- 'Attempted to update encrypted field of multiple documents'
201
- );
202
- }
203
-
204
- if (update.$setOnInsert && hasValue(update.$setOnInsert[field])) {
205
- throw new Error(
206
- 'Attempted to update encrypted field of multiple documents'
207
- );
208
- }
209
-
210
- if (hasValue(update[field])) {
211
- throw new Error(
212
- 'Attempted to update encrypted field of multiple documents'
213
- );
214
- }
215
- }
216
- }
217
-
218
86
  async encrypt(text) {
219
87
  const { keyId, encryptedKey, plaintext } = await this.generateDataKey();
220
88
  const encryptedText = aes.encrypt(text, plaintext);
221
-
222
89
  return `${keyId}:${encryptedText}:${encryptedKey}`;
223
90
  }
224
91
 
@@ -228,7 +95,6 @@ class Cryptor {
228
95
  const encryptedText = `${split[1]}:${split[2]}`;
229
96
  const encryptedKey = Buffer.from(split[3], 'base64');
230
97
  const plaintext = await this.decryptDataKey(keyId, encryptedKey);
231
-
232
98
  return aes.decrypt(encryptedText, plaintext);
233
99
  }
234
100
  }
package/encrypt/index.js CHANGED
@@ -1,4 +1,3 @@
1
- const { Encrypt } = require('./encrypt');
2
1
  const { Cryptor } = require('./Cryptor');
3
2
 
4
- module.exports = { Encrypt, Cryptor };
3
+ module.exports = { Cryptor };
@@ -0,0 +1,26 @@
1
+ const { BaseError } = require('./base-error');
2
+
3
+ /**
4
+ * ClientSafeError - An error that is safe to expose to end users
5
+ *
6
+ * Use this error class when the error message does not contain sensitive
7
+ * implementation details and can be safely shown to users.
8
+ *
9
+ * Examples:
10
+ * - "Invalid Token: Token is expired"
11
+ * - "User not found"
12
+ * - "Invalid credentials"
13
+ *
14
+ * @param {string} message - The user-safe error message
15
+ * @param {number} statusCode - HTTP status code (default: 400)
16
+ * @param {object} options - Additional error options (cause, etc.)
17
+ */
18
+ class ClientSafeError extends BaseError {
19
+ constructor(message, statusCode = 400, options) {
20
+ super(message, options);
21
+ this.statusCode = statusCode;
22
+ this.isClientSafe = true;
23
+ }
24
+ }
25
+
26
+ module.exports = { ClientSafeError };
@@ -1,74 +1,76 @@
1
1
  const { BaseError } = require('./base-error');
2
- const { stripIndent } = require('common-tags');
3
-
4
- // TODO hide header values
2
+ const { redactUrl, scrubString } = require('../logs/redact');
5
3
 
6
4
  // Parameters names here are based on fetch. See:
7
5
  // https://developer.mozilla.org/en-US/docs/Web/API/fetch
8
6
 
9
- class FetchError extends BaseError {
10
- response = null;
11
-
12
- constructor(options = {}) {
13
- const { resource, init, response, responseBody } = options;
14
- const method = init?.method ?? 'GET';
15
- const initText = init
16
- ? init.body instanceof URLSearchParams
17
- ? (() => {
18
- init.body = init.body.toString();
19
- return JSON.stringify({ init }, null, 2);
20
- })()
21
- : JSON.stringify({ init }, null, 2)
22
- : '';
7
+ function resourceUrl(resource) {
8
+ if (resource === undefined || resource === null) return '';
9
+ if (typeof resource === 'object' && typeof resource.url === 'string') {
10
+ return redactUrl(resource.url);
11
+ }
12
+ return redactUrl(resource);
13
+ }
23
14
 
24
- let responseBodyText = '<response body is unavailable>';
25
- if (typeof responseBody === 'string') {
26
- responseBodyText = responseBody;
27
- } else if (responseBody) {
28
- responseBodyText = JSON.stringify(responseBody, null, 2);
29
- }
15
+ // node-fetch messages can contain part of the response body.
16
+ // Use a fixed phrase instead of the original message.
17
+ const NODE_FETCH_TYPE_PHRASES = {
18
+ 'invalid-json': 'invalid json response body',
19
+ };
30
20
 
31
- const responseHeaders = {};
32
- if (response?.headers) {
33
- for (const [key, value] of response.headers) {
34
- responseHeaders[key] = value;
35
- }
36
- }
21
+ function causeLabel(cause) {
22
+ if (!cause || typeof cause !== 'object') return '';
23
+ const label = cause.code ?? cause.name;
24
+ const scrubbedLabel =
25
+ label === undefined || label === null ? '' : scrubString(String(label));
26
+ const phrase = Object.hasOwn(NODE_FETCH_TYPE_PHRASES, cause.type)
27
+ ? NODE_FETCH_TYPE_PHRASES[cause.type]
28
+ : '';
29
+ return [scrubbedLabel, phrase].filter(Boolean).join(': ');
30
+ }
37
31
 
38
- const responseHeaderText = response
39
- ? JSON.stringify({ headers: responseHeaders }, null, 2)
40
- : '';
32
+ function buildMessage({ method, url, response, cause }) {
33
+ const outcome = response
34
+ ? response.status === undefined || response.status === null
35
+ ? ''
36
+ : String(response.status)
37
+ : causeLabel(cause);
38
+ return [method, url, outcome].filter(Boolean).join(' ');
39
+ }
41
40
 
42
- const messageParts = [
43
- stripIndent`
44
- -----------------------------------------------------
45
- An error ocurred while fetching an external resource.
46
- -----------------------------------------------------
47
- >>> Request Details >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
48
- ${method} ${resource}
49
- `,
50
- initText,
51
- stripIndent`
52
- <<< Response Details <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
53
- ${response?.status} ${response?.statusText}
54
- `,
55
- responseHeaderText,
56
- responseBodyText,
57
- stripIndent`
58
- -----------------------------------------------------
59
- Stack Trace:
60
- `,
61
- ];
41
+ class FetchError extends BaseError {
42
+ constructor({ resource, init, response, cause, responseBody, body } = {}) {
43
+ const method = String(init?.method ?? 'GET').toUpperCase();
44
+ const url = resourceUrl(resource);
45
+ super(
46
+ buildMessage({ method, url, response, cause }),
47
+ cause ? { cause } : undefined
48
+ );
62
49
 
63
- super(messageParts.filter(Boolean).join('\n'));
64
-
65
- this.response = response;
50
+ this.statusCode = response?.status;
51
+ this.method = method;
52
+ this.url = url;
53
+ Object.defineProperty(this, 'response', {
54
+ value: response ?? null,
55
+ enumerable: false,
56
+ writable: true,
57
+ configurable: true,
58
+ });
59
+ Object.defineProperty(this, 'body', {
60
+ value: responseBody ?? body,
61
+ enumerable: false,
62
+ writable: true,
63
+ configurable: true,
64
+ });
66
65
  }
67
66
 
68
67
  static async create(options = {}) {
69
68
  const { response } = options;
70
- let responseBody = response?.bodyUsed ? null : await response?.text();
71
- if (!responseBody && options.body) responseBody = options.body;
69
+ let responseBody =
70
+ response && !response.bodyUsed && typeof response.text === 'function'
71
+ ? await response.text()
72
+ : null;
73
+ if (!responseBody) responseBody = options.responseBody ?? options.body;
72
74
  return new FetchError({ ...options, responseBody });
73
75
  }
74
76
  }
package/errors/index.js CHANGED
@@ -5,6 +5,10 @@ const {
5
5
  RequiredPropertyError,
6
6
  ParameterTypeError,
7
7
  } = require('./validation-errors');
8
+ const { ClientSafeError } = require('./client-safe-error');
9
+ const {
10
+ MappingAlreadyExistsError,
11
+ } = require('./mapping-already-exists-error');
8
12
 
9
13
  module.exports = {
10
14
  BaseError,
@@ -12,4 +16,6 @@ module.exports = {
12
16
  HaltError,
13
17
  RequiredPropertyError,
14
18
  ParameterTypeError,
19
+ ClientSafeError,
20
+ MappingAlreadyExistsError,
15
21
  };
@@ -0,0 +1,14 @@
1
+ const { BaseError } = require('./base-error');
2
+
3
+ class MappingAlreadyExistsError extends BaseError {
4
+ constructor(integrationId, sourceId, ...errorOptions) {
5
+ super(
6
+ `Mapping already exists for integration ${integrationId} and sourceId ${sourceId}`,
7
+ ...errorOptions
8
+ );
9
+ this.integrationId = integrationId;
10
+ this.sourceId = sourceId;
11
+ }
12
+ }
13
+
14
+ module.exports = { MappingAlreadyExistsError };
@@ -0,0 +1 @@
1
+ export * from "./index"
@@ -0,0 +1,5 @@
1
+
2
+ /* !!! This is code generated by Prisma. Do not edit directly. !!!
3
+ /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
5
+ module.exports = { ...require('.') }
@@ -0,0 +1 @@
1
+ export * from "./index"
@@ -0,0 +1,5 @@
1
+
2
+ /* !!! This is code generated by Prisma. Do not edit directly. !!!
3
+ /* eslint-disable */
4
+ // biome-ignore-all lint: generated file
5
+ module.exports = { ...require('#main-entry-point') }
@@ -0,0 +1 @@
1
+ export * from "./default"