@friggframework/core 2.0.0-next.8 → 2.0.0-next.81

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 (305) hide show
  1. package/CLAUDE.md +702 -0
  2. package/README.md +959 -50
  3. package/application/commands/README.md +451 -0
  4. package/application/commands/credential-commands.js +245 -0
  5. package/application/commands/entity-commands.js +336 -0
  6. package/application/commands/integration-commands.js +210 -0
  7. package/application/commands/scheduler-commands.js +263 -0
  8. package/application/commands/user-commands.js +283 -0
  9. package/application/index.js +73 -0
  10. package/assertions/index.js +0 -3
  11. package/core/CLAUDE.md +690 -0
  12. package/core/Worker.js +60 -24
  13. package/core/create-handler.js +79 -8
  14. package/credential/repositories/credential-repository-documentdb.js +304 -0
  15. package/credential/repositories/credential-repository-factory.js +54 -0
  16. package/credential/repositories/credential-repository-interface.js +98 -0
  17. package/credential/repositories/credential-repository-mongo.js +269 -0
  18. package/credential/repositories/credential-repository-postgres.js +287 -0
  19. package/credential/repositories/credential-repository.js +300 -0
  20. package/credential/use-cases/get-credential-for-user.js +25 -0
  21. package/credential/use-cases/update-authentication-status.js +15 -0
  22. package/database/MONGODB_TRANSACTION_FIX.md +198 -0
  23. package/database/adapters/lambda-invoker.js +97 -0
  24. package/database/config.js +154 -0
  25. package/database/documentdb-encryption-service.js +330 -0
  26. package/database/documentdb-utils.js +136 -0
  27. package/database/encryption/README.md +839 -0
  28. package/database/encryption/documentdb-encryption-service.md +3575 -0
  29. package/database/encryption/encryption-schema-registry.js +268 -0
  30. package/database/encryption/field-encryption-service.js +226 -0
  31. package/database/encryption/logger.js +79 -0
  32. package/database/encryption/prisma-encryption-extension.js +222 -0
  33. package/database/index.js +21 -21
  34. package/database/prisma.js +182 -0
  35. package/database/repositories/health-check-repository-documentdb.js +138 -0
  36. package/database/repositories/health-check-repository-factory.js +48 -0
  37. package/database/repositories/health-check-repository-interface.js +82 -0
  38. package/database/repositories/health-check-repository-mongodb.js +89 -0
  39. package/database/repositories/health-check-repository-postgres.js +82 -0
  40. package/database/repositories/migration-status-repository-s3.js +137 -0
  41. package/database/use-cases/check-database-health-use-case.js +29 -0
  42. package/database/use-cases/check-database-state-use-case.js +81 -0
  43. package/database/use-cases/check-encryption-health-use-case.js +83 -0
  44. package/database/use-cases/get-database-state-via-worker-use-case.js +61 -0
  45. package/database/use-cases/get-migration-status-use-case.js +93 -0
  46. package/database/use-cases/run-database-migration-use-case.js +139 -0
  47. package/database/use-cases/test-encryption-use-case.js +253 -0
  48. package/database/use-cases/trigger-database-migration-use-case.js +157 -0
  49. package/database/utils/mongodb-collection-utils.js +94 -0
  50. package/database/utils/mongodb-schema-init.js +108 -0
  51. package/database/utils/prisma-runner.js +477 -0
  52. package/database/utils/prisma-schema-parser.js +182 -0
  53. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +517 -0
  54. package/encrypt/Cryptor.js +34 -168
  55. package/encrypt/index.js +1 -2
  56. package/errors/client-safe-error.js +26 -0
  57. package/errors/fetch-error.js +15 -7
  58. package/errors/index.js +2 -0
  59. package/generated/prisma-mongodb/client.d.ts +1 -0
  60. package/generated/prisma-mongodb/client.js +4 -0
  61. package/generated/prisma-mongodb/default.d.ts +1 -0
  62. package/generated/prisma-mongodb/default.js +4 -0
  63. package/generated/prisma-mongodb/edge.d.ts +1 -0
  64. package/generated/prisma-mongodb/edge.js +335 -0
  65. package/generated/prisma-mongodb/index-browser.js +317 -0
  66. package/generated/prisma-mongodb/index.d.ts +22955 -0
  67. package/generated/prisma-mongodb/index.js +360 -0
  68. package/generated/prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  69. package/generated/prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  70. package/generated/prisma-mongodb/package.json +183 -0
  71. package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
  72. package/generated/prisma-mongodb/runtime/edge.js +34 -0
  73. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  74. package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
  75. package/generated/prisma-mongodb/runtime/library.d.ts +3977 -0
  76. package/generated/prisma-mongodb/runtime/library.js +146 -0
  77. package/generated/prisma-mongodb/runtime/react-native.js +83 -0
  78. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
  79. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
  80. package/generated/prisma-mongodb/schema.prisma +368 -0
  81. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
  82. package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
  83. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  84. package/generated/prisma-mongodb/wasm.js +342 -0
  85. package/generated/prisma-postgresql/client.d.ts +1 -0
  86. package/generated/prisma-postgresql/client.js +4 -0
  87. package/generated/prisma-postgresql/default.d.ts +1 -0
  88. package/generated/prisma-postgresql/default.js +4 -0
  89. package/generated/prisma-postgresql/edge.d.ts +1 -0
  90. package/generated/prisma-postgresql/edge.js +357 -0
  91. package/generated/prisma-postgresql/index-browser.js +339 -0
  92. package/generated/prisma-postgresql/index.d.ts +25135 -0
  93. package/generated/prisma-postgresql/index.js +382 -0
  94. package/generated/prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node +0 -0
  95. package/generated/prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node +0 -0
  96. package/generated/prisma-postgresql/package.json +183 -0
  97. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  98. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  99. package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
  100. package/generated/prisma-postgresql/runtime/edge.js +34 -0
  101. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  102. package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
  103. package/generated/prisma-postgresql/runtime/library.d.ts +3977 -0
  104. package/generated/prisma-postgresql/runtime/library.js +146 -0
  105. package/generated/prisma-postgresql/runtime/react-native.js +83 -0
  106. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
  107. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
  108. package/generated/prisma-postgresql/schema.prisma +351 -0
  109. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
  110. package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
  111. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  112. package/generated/prisma-postgresql/wasm.js +364 -0
  113. package/handlers/WEBHOOKS.md +653 -0
  114. package/handlers/app-definition-loader.js +38 -0
  115. package/handlers/app-handler-helpers.js +57 -0
  116. package/handlers/backend-utils.js +262 -0
  117. package/handlers/database-migration-handler.js +227 -0
  118. package/handlers/integration-event-dispatcher.js +54 -0
  119. package/handlers/routers/HEALTHCHECK.md +342 -0
  120. package/handlers/routers/auth.js +15 -0
  121. package/handlers/routers/db-migration.handler.js +29 -0
  122. package/handlers/routers/db-migration.js +326 -0
  123. package/handlers/routers/health.js +516 -0
  124. package/handlers/routers/integration-defined-routers.js +45 -0
  125. package/handlers/routers/integration-webhook-routers.js +67 -0
  126. package/handlers/routers/user.js +63 -0
  127. package/handlers/routers/websocket.js +57 -0
  128. package/handlers/use-cases/check-external-apis-health-use-case.js +81 -0
  129. package/handlers/use-cases/check-integrations-health-use-case.js +44 -0
  130. package/handlers/workers/db-migration.js +352 -0
  131. package/handlers/workers/dlq-processor.js +63 -0
  132. package/handlers/workers/integration-defined-workers.js +23 -0
  133. package/index.js +82 -46
  134. package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +184 -0
  135. package/infrastructure/scheduler/index.js +33 -0
  136. package/infrastructure/scheduler/mock-scheduler-adapter.js +143 -0
  137. package/infrastructure/scheduler/scheduler-service-factory.js +73 -0
  138. package/infrastructure/scheduler/scheduler-service-interface.js +47 -0
  139. package/integrations/WEBHOOK-QUICKSTART.md +151 -0
  140. package/integrations/index.js +12 -10
  141. package/integrations/integration-base.js +364 -55
  142. package/integrations/integration-router.js +376 -179
  143. package/integrations/options.js +1 -1
  144. package/integrations/repositories/integration-mapping-repository-documentdb.js +280 -0
  145. package/integrations/repositories/integration-mapping-repository-factory.js +57 -0
  146. package/integrations/repositories/integration-mapping-repository-interface.js +106 -0
  147. package/integrations/repositories/integration-mapping-repository-mongo.js +161 -0
  148. package/integrations/repositories/integration-mapping-repository-postgres.js +227 -0
  149. package/integrations/repositories/integration-mapping-repository.js +156 -0
  150. package/integrations/repositories/integration-repository-documentdb.js +219 -0
  151. package/integrations/repositories/integration-repository-factory.js +51 -0
  152. package/integrations/repositories/integration-repository-interface.js +144 -0
  153. package/integrations/repositories/integration-repository-mongo.js +330 -0
  154. package/integrations/repositories/integration-repository-postgres.js +385 -0
  155. package/integrations/repositories/process-repository-documentdb.js +311 -0
  156. package/integrations/repositories/process-repository-factory.js +53 -0
  157. package/integrations/repositories/process-repository-interface.js +136 -0
  158. package/integrations/repositories/process-repository-mongo.js +262 -0
  159. package/integrations/repositories/process-repository-postgres.js +380 -0
  160. package/integrations/repositories/process-update-ops-shared.js +112 -0
  161. package/integrations/tests/doubles/config-capturing-integration.js +81 -0
  162. package/integrations/tests/doubles/dummy-integration-class.js +105 -0
  163. package/integrations/tests/doubles/test-integration-repository.js +112 -0
  164. package/integrations/use-cases/create-integration.js +83 -0
  165. package/integrations/use-cases/create-process.js +128 -0
  166. package/integrations/use-cases/delete-integration-for-user.js +101 -0
  167. package/integrations/use-cases/find-integration-context-by-external-entity-id.js +72 -0
  168. package/integrations/use-cases/get-integration-for-user.js +78 -0
  169. package/integrations/use-cases/get-integration-instance-by-definition.js +67 -0
  170. package/integrations/use-cases/get-integration-instance.js +83 -0
  171. package/integrations/use-cases/get-integrations-for-user.js +88 -0
  172. package/integrations/use-cases/get-possible-integrations.js +27 -0
  173. package/integrations/use-cases/get-process.js +87 -0
  174. package/integrations/use-cases/index.js +19 -0
  175. package/integrations/use-cases/load-integration-context.js +71 -0
  176. package/integrations/use-cases/update-integration-messages.js +44 -0
  177. package/integrations/use-cases/update-integration-status.js +32 -0
  178. package/integrations/use-cases/update-integration.js +92 -0
  179. package/integrations/use-cases/update-process-metrics.js +205 -0
  180. package/integrations/use-cases/update-process-state.js +158 -0
  181. package/integrations/utils/map-integration-dto.js +37 -0
  182. package/jest-global-setup-noop.js +3 -0
  183. package/jest-global-teardown-noop.js +3 -0
  184. package/logs/logger.js +0 -4
  185. package/{module-plugin → modules}/index.js +0 -10
  186. package/modules/module-factory.js +56 -0
  187. package/modules/module.js +258 -0
  188. package/modules/repositories/module-repository-documentdb.js +335 -0
  189. package/modules/repositories/module-repository-factory.js +40 -0
  190. package/modules/repositories/module-repository-interface.js +129 -0
  191. package/modules/repositories/module-repository-mongo.js +408 -0
  192. package/modules/repositories/module-repository-postgres.js +453 -0
  193. package/modules/repositories/module-repository.js +345 -0
  194. package/modules/requester/api-key.js +52 -0
  195. package/modules/requester/oauth-2.js +396 -0
  196. package/modules/requester/requester.js +275 -0
  197. package/{module-plugin → modules}/test/mock-api/api.js +8 -3
  198. package/{module-plugin → modules}/test/mock-api/definition.js +14 -10
  199. package/modules/tests/doubles/test-module-factory.js +16 -0
  200. package/modules/tests/doubles/test-module-repository.js +39 -0
  201. package/modules/use-cases/get-entities-for-user.js +32 -0
  202. package/modules/use-cases/get-entity-options-by-id.js +71 -0
  203. package/modules/use-cases/get-entity-options-by-type.js +34 -0
  204. package/modules/use-cases/get-module-instance-from-type.js +34 -0
  205. package/modules/use-cases/get-module.js +74 -0
  206. package/modules/use-cases/process-authorization-callback.js +177 -0
  207. package/modules/use-cases/refresh-entity-options.js +72 -0
  208. package/modules/use-cases/test-module-auth.js +72 -0
  209. package/modules/utils/map-module-dto.js +18 -0
  210. package/package.json +82 -50
  211. package/prisma-mongodb/schema.prisma +368 -0
  212. package/prisma-postgresql/migrations/20250930193005_init/migration.sql +315 -0
  213. package/prisma-postgresql/migrations/20251006135218_init/migration.sql +9 -0
  214. package/prisma-postgresql/migrations/20251010000000_remove_unused_entity_reference_map/migration.sql +3 -0
  215. package/prisma-postgresql/migrations/20251112195422_update_user_unique_constraints/migration.sql +25 -0
  216. package/prisma-postgresql/migrations/20260422120000_add_entity_data_column/migration.sql +10 -0
  217. package/prisma-postgresql/migrations/20260422120001_create_process_table/migration.sql +48 -0
  218. package/prisma-postgresql/migrations/migration_lock.toml +3 -0
  219. package/prisma-postgresql/schema.prisma +351 -0
  220. package/queues/queuer-util.js +103 -21
  221. package/syncs/manager.js +468 -443
  222. package/syncs/repositories/sync-repository-documentdb.js +240 -0
  223. package/syncs/repositories/sync-repository-factory.js +43 -0
  224. package/syncs/repositories/sync-repository-interface.js +109 -0
  225. package/syncs/repositories/sync-repository-mongo.js +239 -0
  226. package/syncs/repositories/sync-repository-postgres.js +319 -0
  227. package/syncs/sync.js +0 -1
  228. package/token/repositories/token-repository-documentdb.js +137 -0
  229. package/token/repositories/token-repository-factory.js +40 -0
  230. package/token/repositories/token-repository-interface.js +131 -0
  231. package/token/repositories/token-repository-mongo.js +219 -0
  232. package/token/repositories/token-repository-postgres.js +264 -0
  233. package/token/repositories/token-repository.js +219 -0
  234. package/types/associations/index.d.ts +0 -17
  235. package/types/core/index.d.ts +12 -4
  236. package/types/database/index.d.ts +10 -2
  237. package/types/encrypt/index.d.ts +5 -3
  238. package/types/integrations/index.d.ts +3 -8
  239. package/types/module-plugin/index.d.ts +17 -69
  240. package/types/syncs/index.d.ts +0 -17
  241. package/user/repositories/user-repository-documentdb.js +441 -0
  242. package/user/repositories/user-repository-factory.js +52 -0
  243. package/user/repositories/user-repository-interface.js +201 -0
  244. package/user/repositories/user-repository-mongo.js +308 -0
  245. package/user/repositories/user-repository-postgres.js +360 -0
  246. package/user/tests/doubles/test-user-repository.js +72 -0
  247. package/user/use-cases/authenticate-user.js +127 -0
  248. package/user/use-cases/authenticate-with-shared-secret.js +48 -0
  249. package/user/use-cases/create-individual-user.js +61 -0
  250. package/user/use-cases/create-organization-user.js +47 -0
  251. package/user/use-cases/create-token-for-user-id.js +30 -0
  252. package/user/use-cases/get-user-from-adopter-jwt.js +149 -0
  253. package/user/use-cases/get-user-from-bearer-token.js +77 -0
  254. package/user/use-cases/get-user-from-x-frigg-headers.js +132 -0
  255. package/user/use-cases/login-user.js +122 -0
  256. package/user/user.js +125 -0
  257. package/utils/backend-path.js +38 -0
  258. package/utils/index.js +6 -0
  259. package/websocket/repositories/websocket-connection-repository-documentdb.js +119 -0
  260. package/websocket/repositories/websocket-connection-repository-factory.js +44 -0
  261. package/websocket/repositories/websocket-connection-repository-interface.js +106 -0
  262. package/websocket/repositories/websocket-connection-repository-mongo.js +156 -0
  263. package/websocket/repositories/websocket-connection-repository-postgres.js +196 -0
  264. package/websocket/repositories/websocket-connection-repository.js +161 -0
  265. package/assertions/is-equal.js +0 -17
  266. package/associations/model.js +0 -54
  267. package/database/models/IndividualUser.js +0 -76
  268. package/database/models/OrganizationUser.js +0 -29
  269. package/database/models/State.js +0 -9
  270. package/database/models/Token.js +0 -70
  271. package/database/models/UserModel.js +0 -7
  272. package/database/models/WebsocketConnection.js +0 -49
  273. package/database/mongo.js +0 -45
  274. package/database/mongoose.js +0 -5
  275. package/encrypt/Cryptor.test.js +0 -32
  276. package/encrypt/encrypt.js +0 -132
  277. package/encrypt/encrypt.test.js +0 -1069
  278. package/encrypt/test-encrypt.js +0 -107
  279. package/errors/base-error.test.js +0 -32
  280. package/errors/fetch-error.test.js +0 -79
  281. package/errors/halt-error.test.js +0 -11
  282. package/errors/validation-errors.test.js +0 -120
  283. package/integrations/create-frigg-backend.js +0 -31
  284. package/integrations/integration-factory.js +0 -251
  285. package/integrations/integration-mapping.js +0 -43
  286. package/integrations/integration-model.js +0 -46
  287. package/integrations/integration-user.js +0 -144
  288. package/integrations/test/integration-base.test.js +0 -144
  289. package/lambda/TimeoutCatcher.test.js +0 -68
  290. package/logs/logger.test.js +0 -76
  291. package/module-plugin/auther.js +0 -393
  292. package/module-plugin/credential.js +0 -22
  293. package/module-plugin/entity-manager.js +0 -70
  294. package/module-plugin/entity.js +0 -46
  295. package/module-plugin/manager.js +0 -169
  296. package/module-plugin/module-factory.js +0 -61
  297. package/module-plugin/requester/api-key.js +0 -36
  298. package/module-plugin/requester/oauth-2.js +0 -219
  299. package/module-plugin/requester/requester.js +0 -165
  300. package/module-plugin/requester/requester.test.js +0 -28
  301. package/module-plugin/test/auther.test.js +0 -97
  302. package/syncs/model.js +0 -62
  303. /package/{module-plugin → modules}/ModuleConstants.js +0 -0
  304. /package/{module-plugin → modules}/requester/basic.js +0 -0
  305. /package/{module-plugin → modules}/test/mock-api/mocks/hubspot.js +0 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,702 @@
1
+ # CLAUDE.md - Frigg Framework Core Package
2
+
3
+ This file provides guidance to Claude Code when working with the Frigg Framework's core package (`@friggframework/core`).
4
+
5
+ ## Critical Context (Read First)
6
+
7
+ - **Package Purpose**: Core framework functionality for building enterprise serverless integrations
8
+ - **Main Architecture**: Hexagonal/DDD architecture with clear separation of adapters, use cases, and repositories
9
+ - **Key Technologies**: Node.js, Express, AWS Lambda, MongoDB/PostgreSQL (Prisma), AWS KMS encryption
10
+ - **Core Value**: Provides building blocks for integration developers - they extend IntegrationBase and use framework services
11
+ - **Security Model**: Field-level encryption, OAuth2 flows, signature validation, VPC deployment
12
+ - **DO NOT**: Bypass architectural layers, skip encryption for sensitive data, expose internal errors to users
13
+
14
+ ## Table of Contents
15
+
16
+ 1. [Package Overview](#package-overview)
17
+ 2. [Architecture Principles](#architecture-principles)
18
+ 3. [Essential Commands](#essential-commands)
19
+ 4. [Directory Structure](#directory-structure)
20
+ 5. [Core Components](#core-components)
21
+ 6. [Development Workflow](#development-workflow)
22
+ 7. [Testing Strategy](#testing-strategy)
23
+ 8. [Anti-Patterns](#anti-patterns)
24
+
25
+ ## Package Overview
26
+
27
+ `@friggframework/core` is the foundational package of the Frigg Framework, providing:
28
+
29
+ - **IntegrationBase**: Base class all integrations extend
30
+ - **Database Layer**: Multi-database support (MongoDB, DocumentDB, PostgreSQL) with Prisma ORM
31
+ - **Encryption**: Transparent field-level encryption with AWS KMS or AES
32
+ - **User Management**: Individual and organizational user support
33
+ - **Module System**: API module loading and credential management
34
+ - **Lambda Runtime**: Handler factory, worker base class, timeout management
35
+ - **Error Handling**: Standardized error types with proper HTTP status codes
36
+ - **Event System**: Integration lifecycle events and user actions
37
+
38
+ ## Architecture Principles
39
+
40
+ ### Hexagonal Architecture (Ports and Adapters)
41
+
42
+ The core package strictly follows hexagonal architecture:
43
+
44
+ ```
45
+ ┌─────────────────────────────────────────────────────────┐
46
+ │ Adapters (Inbound) │
47
+ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
48
+ │ │ HTTP/REST │ │ Lambda │ │ SQS Workers │ │
49
+ │ │ (handlers/) │ │ (core/) │ │ (queues/) │ │
50
+ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
51
+ └─────────┼─────────────────┼─────────────────┼───────────┘
52
+ │ │ │
53
+ ┌─────────▼─────────────────▼─────────────────▼───────────┐
54
+ │ Application Layer (Use Cases) │
55
+ │ ┌────────────────────────────────────────────────┐ │
56
+ │ │ CreateIntegration, UpdateIntegration, │ │
57
+ │ │ LoginUser, ProcessAttachmentJob, etc. │ │
58
+ │ └────────────────────┬───────────────────────────┘ │
59
+ └───────────────────────┼─────────────────────────────────┘
60
+ │ calls
61
+ ┌───────────────────────▼─────────────────────────────────┐
62
+ │ Domain Layer (Entities) │
63
+ │ ┌────────────────────────────────────────────────┐ │
64
+ │ │ IntegrationBase, User, Credential, Entity │ │
65
+ │ └────────────────────┬───────────────────────────┘ │
66
+ └───────────────────────┼─────────────────────────────────┘
67
+ │ persisted by
68
+ ┌───────────────────────▼─────────────────────────────────┐
69
+ │ Infrastructure Layer (Repositories) │
70
+ │ ┌────────────────────────────────────────────────┐ │
71
+ │ │ IntegrationRepository, UserRepository, │ │
72
+ │ │ CredentialRepository, ModuleRepository │ │
73
+ │ └────────────────────┬───────────────────────────┘ │
74
+ └───────────────────────┼─────────────────────────────────┘
75
+ │ accesses
76
+ ┌───────────────────────▼─────────────────────────────────┐
77
+ │ External Systems │
78
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
79
+ │ │ MongoDB │ │ Postgres │ │ AWS KMS │ │
80
+ │ └──────────┘ └──────────┘ └──────────┘ │
81
+ └─────────────────────────────────────────────────────────┘
82
+ ```
83
+
84
+ ### Golden Rules
85
+
86
+ 1. **Handlers NEVER call repositories directly** - Always go through use cases
87
+ 2. **Use cases contain business logic** - Not repositories or handlers
88
+ 3. **Repositories are pure data access** - No business logic or orchestration
89
+ 4. **Domain entities have behavior** - Not just data bags
90
+ 5. **Encryption is transparent** - Application code works with plain data
91
+
92
+ ## Essential Commands
93
+
94
+ ### Development
95
+
96
+ ```bash
97
+ # Install dependencies
98
+ npm install
99
+
100
+ # Generate Prisma clients (both MongoDB and PostgreSQL)
101
+ npm run prisma:generate
102
+
103
+ # Format and lint code
104
+ npm run lint:fix
105
+
106
+ # Run tests
107
+ npm test
108
+
109
+ # Run specific test file
110
+ npm test -- path/to/test.test.js
111
+
112
+ # Run tests for specific pattern
113
+ npm test -- --testPathPattern="encryption"
114
+ ```
115
+
116
+ ### Prisma Database Operations
117
+
118
+ ```bash
119
+ # Generate clients
120
+ npm run prisma:generate:mongo # MongoDB only
121
+ npm run prisma:generate:postgres # PostgreSQL only
122
+ npm run prisma:generate # Both databases
123
+
124
+ # Database migrations
125
+ npm run prisma:push:mongo # Push MongoDB schema
126
+ npm run prisma:migrate:postgres # Run PostgreSQL migrations
127
+ ```
128
+
129
+ ### Testing
130
+
131
+ ```bash
132
+ # All tests
133
+ npm test
134
+
135
+ # Specific test categories
136
+ npm test -- database/encryption/ # Encryption tests
137
+ npm test -- integrations/ # Integration tests
138
+ npm test -- handlers/ # Handler tests
139
+ ```
140
+
141
+ ## Directory Structure
142
+
143
+ ```
144
+ packages/core/
145
+ ├── application/ # Application-level commands and initialization
146
+ │ └── commands/ # Command pattern implementations
147
+ ├── assertions/ # Validation and assertion utilities
148
+ ├── associations/ # Entity association management
149
+ ├── core/ # Runtime system (Lambda, Workers, Delegates)
150
+ │ └── CLAUDE.md # Detailed core runtime documentation
151
+ ├── credential/ # Credential management
152
+ │ ├── repositories/ # Credential data access
153
+ │ └── use-cases/ # Credential business logic
154
+ ├── database/ # Database layer and encryption
155
+ │ ├── encryption/ # Field-level encryption system
156
+ │ │ └── README.md # Comprehensive encryption documentation
157
+ │ ├── models/ # Mongoose models
158
+ │ ├── repositories/ # Database repositories
159
+ │ └── use-cases/ # Database health and management
160
+ ├── encrypt/ # Cryptor adapter for AWS KMS and AES
161
+ ├── errors/ # Error type definitions
162
+ ├── handlers/ # HTTP/Lambda request handlers
163
+ │ └── routers/ # Express routers
164
+ ├── integrations/ # Integration domain and lifecycle
165
+ │ ├── integration-base.js # Base class for all integrations
166
+ │ ├── repositories/ # Integration data access
167
+ │ ├── tests/ # Integration tests
168
+ │ └── use-cases/ # Integration business logic
169
+ ├── lambda/ # AWS Lambda utilities
170
+ ├── logs/ # Logging system
171
+ ├── modules/ # API module system
172
+ │ ├── requester/ # HTTP client implementations
173
+ │ └── repositories/ # Module data access
174
+ ├── prisma-mongodb/ # MongoDB Prisma schema
175
+ ├── prisma-postgresql/ # PostgreSQL Prisma schema
176
+ ├── queues/ # SQS job queue management
177
+ ├── syncs/ # Data synchronization
178
+ ├── token/ # Token management
179
+ │ └── repositories/ # Token data access
180
+ ├── types/ # TypeScript type definitions
181
+ ├── user/ # User management
182
+ │ ├── repositories/ # User data access
183
+ │ └── use-cases/ # User business logic
184
+ ├── utils/ # Utility functions
185
+ ├── websocket/ # WebSocket connection management
186
+ │ └── repositories/ # WebSocket data access
187
+ ├── index.js # Main export file
188
+ ├── package.json # Package configuration
189
+ └── README.md # Package documentation
190
+ ```
191
+
192
+ ## Core Components
193
+
194
+ ### 1. Integration System (`/integrations`)
195
+
196
+ **Purpose**: Foundation for building integrations between external systems.
197
+
198
+ **Key Files**:
199
+ - `integration-base.js` - Base class all integrations extend
200
+ - `integration.js` - Integration domain aggregate using Proxy pattern
201
+ - `options.js` - Integration configuration and options
202
+
203
+ **Use Cases**:
204
+ - `create-integration.js` - Create new integration instance
205
+ - `update-integration.js` - Update integration configuration
206
+ - `delete-integration-for-user.js` - Remove integration
207
+ - `get-integration-instance.js` - Load integration with modules
208
+ - `load-integration-context.js` - Full integration context loading
209
+
210
+ **Repositories**:
211
+ - `integration-repository-factory.js` - Creates database-specific repositories
212
+ - `integration-repository-mongo.js` - MongoDB implementation
213
+ - `integration-repository-postgres.js` - PostgreSQL implementation
214
+ - `integration-mapping-repository-*.js` - Mapping data persistence
215
+ - `process-repository-*.js` - Process (long-running job) persistence.
216
+ Implements `applyProcessUpdate(processId, ops)` — a race-safe alternative
217
+ to `update(id, patch)` that routes increments, sets, and bounded-array
218
+ pushes through each backend's native atomic primitive (PostgreSQL
219
+ `jsonb_set` / MongoDB `$inc`/`$set`/`$push`). Use this method any time
220
+ multiple queue workers may concurrently mutate the same Process row
221
+ (counters, flags, error history). The legacy `update(id, patch)`
222
+ remains available but is clobber-prone under concurrency.
223
+
224
+ **Integration developers extend IntegrationBase**:
225
+
226
+ ```javascript
227
+ const { IntegrationBase } = require('@friggframework/core');
228
+
229
+ class MyIntegration extends IntegrationBase {
230
+ static Definition = {
231
+ name: 'my-integration',
232
+ version: '1.0.0',
233
+ modules: {
234
+ serviceA: 'service-a',
235
+ serviceB: 'service-b'
236
+ }
237
+ };
238
+
239
+ async onCreate({ integrationId }) {
240
+ // Setup logic
241
+ await super.onCreate({ integrationId });
242
+ }
243
+ }
244
+ ```
245
+
246
+ ### 2. Database Layer (`/database`)
247
+
248
+ **Purpose**: Multi-database support with transparent encryption.
249
+
250
+ **Key Components**:
251
+ - `prisma.js` - Prisma client initialization with encryption extension
252
+ - `mongo.js` - Mongoose connection management (legacy)
253
+ - `models/` - Mongoose model definitions
254
+
255
+ **Encryption System** (`/database/encryption`):
256
+ - **Transparent encryption**: Application code never sees encrypted data
257
+ - **Database-agnostic**: Works with MongoDB and PostgreSQL
258
+ - **AWS KMS or AES**: Production KMS, development AES
259
+ - **Configurable**: Via environment variables and app definition
260
+
261
+ **See**: `database/encryption/README.md` for comprehensive documentation
262
+
263
+ **Repositories**:
264
+ - `health-check-repository.js` - Database health monitoring
265
+ - `token-repository.js` - Authentication tokens
266
+ - `websocket-connection-repository.js` - WebSocket connections
267
+ - DocumentDB-enabled adapters mirror the MongoDB APIs but execute raw commands (`$runCommandRaw`, `$aggregateRaw`) for compatibility; encrypted models (e.g., credentials) still delegate reads to Prisma so the encryption extension can decrypt secrets transparently.
268
+
269
+ **Use Cases**:
270
+ - `check-database-health-use-case.js` - Database health checks
271
+ - `test-encryption-use-case.js` - Encryption verification
272
+
273
+ ### 3. User Management (`/user`)
274
+
275
+ **Purpose**: Individual and organizational user authentication.
276
+
277
+ **User Types**:
278
+ - **Individual Users**: Personal accounts with email/password
279
+ - **Organization Users**: Business accounts with organization-level access
280
+ - **Hybrid**: Support both simultaneously
281
+
282
+ **Authentication Methods**:
283
+ - Password-based (bcrypt hashed)
284
+ - Token-based (Bearer tokens)
285
+ - App-based (external app user IDs)
286
+
287
+ **Use Cases**:
288
+ - `login-user.js` - User authentication
289
+ - `create-individual-user.js` - Create personal account
290
+ - `create-organization-user.js` - Create business account
291
+ - `get-user-from-bearer-token.js` - Token authentication
292
+
293
+ **Repositories**:
294
+ - `user-repository-factory.js` - Creates database-specific repositories
295
+ - `user-repository-mongo.js` - MongoDB implementation
296
+ - `user-repository-postgres.js` - PostgreSQL implementation
297
+
298
+ **Configuration** (in app definition):
299
+
300
+ ```javascript
301
+ {
302
+ user: {
303
+ usePassword: true, // Enable password auth
304
+ primary: 'individual', // Primary user type
305
+ individualUserRequired: true, // Require individual user
306
+ organizationUserRequired: false // Optional org user
307
+ }
308
+ }
309
+ ```
310
+
311
+ ### 4. Module System (`/modules`)
312
+
313
+ **Purpose**: API module loading, credential management, and HTTP clients.
314
+
315
+ **Key Classes**:
316
+ - `Credential` - API credentials domain entity
317
+ - `Entity` - External service entity (account, workspace, etc.)
318
+ - `Requester` - Base HTTP client class
319
+ - `OAuth2Requester` - OAuth 2.0 flow implementation
320
+ - `ApiKeyRequester` - API key authentication
321
+ - `BasicAuthRequester` - Basic authentication
322
+
323
+ **Module Factory**:
324
+ - `ModuleFactory` - Creates and configures API module instances
325
+ - Handles credential injection
326
+ - Manages module lifecycle
327
+
328
+ **Repositories**:
329
+ - `module-repository.js` - Module data access
330
+ - `credential-repository.js` - Credential persistence (encrypted)
331
+
332
+ ### 5. Core Runtime System (`/core`)
333
+
334
+ **Purpose**: Lambda-optimized runtime with handlers, workers, and delegates.
335
+
336
+ **See**: `core/CLAUDE.md` for comprehensive documentation
337
+
338
+ **Key Components**:
339
+ - `create-handler.js` - Lambda handler factory
340
+ - `Worker.js` - SQS job processing base class
341
+ - `Delegate.js` - Observer/delegation pattern
342
+ - `load-installed-modules.js` - Dynamic module loading
343
+
344
+ **Handler Pattern**:
345
+
346
+ ```javascript
347
+ const { createHandler } = require('@friggframework/core');
348
+
349
+ const handler = createHandler({
350
+ eventName: 'MyIntegration',
351
+ isUserFacingResponse: true, // Sanitize errors
352
+ shouldUseDatabase: true, // Connect to DB
353
+ method: async (event, context) => {
354
+ // Your logic here
355
+ return { statusCode: 200, body: 'Success' };
356
+ }
357
+ });
358
+ ```
359
+
360
+ **Worker Pattern**:
361
+
362
+ ```javascript
363
+ const { Worker } = require('@friggframework/core');
364
+
365
+ class MyWorker extends Worker {
366
+ _validateParams(params) {
367
+ this._verifyParamExists(params, 'requiredField');
368
+ }
369
+
370
+ async _run(params, context) {
371
+ // Process SQS message
372
+ }
373
+ }
374
+ ```
375
+
376
+ ### 6. Encryption System (`/encrypt`)
377
+
378
+ **Purpose**: Cryptor adapter for AWS KMS and AES encryption.
379
+
380
+ **Key Class**: `Cryptor.js`
381
+ - Envelope encryption pattern
382
+ - AWS KMS integration
383
+ - AES-256-GCM fallback
384
+ - Key rotation support
385
+
386
+ **Usage**:
387
+
388
+ ```javascript
389
+ const { Cryptor } = require('@friggframework/core');
390
+
391
+ const cryptor = new Cryptor({
392
+ shouldUseAws: process.env.KMS_KEY_ARN ? true : false
393
+ });
394
+
395
+ const encrypted = await cryptor.encrypt('sensitive-data');
396
+ const decrypted = await cryptor.decrypt(encrypted);
397
+ ```
398
+
399
+ ### 7. Handlers & Routers (`/handlers`)
400
+
401
+ **Purpose**: HTTP/Lambda request handling and routing.
402
+
403
+ **Key Routers**:
404
+ - `integration-router.js` - Integration CRUD operations
405
+ - `auth.js` - Authentication endpoints
406
+ - `health.js` - Health check endpoints with encryption verification
407
+
408
+ **Handler Types**:
409
+ - **User-facing**: Sanitize errors, friendly responses
410
+ - **Server-to-server**: Full error details for debugging
411
+ - **Background workers**: SQS message processing
412
+
413
+ **Event Dispatcher**:
414
+ - `integration-event-dispatcher.js` - Routes events to integration handlers
415
+ - Supports lifecycle events and user actions
416
+
417
+ ### 8. Error Handling (`/errors`)
418
+
419
+ **Purpose**: Standardized error types with proper HTTP semantics.
420
+
421
+ **Error Types**:
422
+ - `BaseError` - Base error class
423
+ - `FetchError` - HTTP request failures
424
+ - `HaltError` - Stop processing without retry
425
+ - `RequiredPropertyError` - Missing required parameters
426
+ - `ParameterTypeError` - Invalid parameter type
427
+
428
+ **Usage**:
429
+
430
+ ```javascript
431
+ const { RequiredPropertyError } = require('@friggframework/core');
432
+
433
+ if (!userId) {
434
+ throw new RequiredPropertyError('userId is required');
435
+ }
436
+ ```
437
+
438
+ ### 9. Logging System (`/logs`)
439
+
440
+ **Purpose**: Structured logging with debug capabilities.
441
+
442
+ **Functions**:
443
+ - `debug(message, data)` - Debug logging
444
+ - `initDebugLog(eventName, event)` - Initialize debug context
445
+ - `flushDebugLog(error)` - Flush logs on error
446
+
447
+ **Usage**:
448
+
449
+ ```javascript
450
+ const { debug, initDebugLog, flushDebugLog } = require('@friggframework/core');
451
+
452
+ initDebugLog('MyIntegration', event);
453
+ debug('Processing request', { userId, action });
454
+ // ... your code ...
455
+ flushDebugLog(); // On error
456
+ ```
457
+
458
+ ### 10. Lambda Utilities (`/lambda`)
459
+
460
+ **Purpose**: AWS Lambda-specific utilities.
461
+
462
+ **Key Classes**:
463
+ - `TimeoutCatcher` - Detect approaching Lambda timeout
464
+ - Graceful shutdown handling
465
+
466
+ **Usage**:
467
+
468
+ ```javascript
469
+ const { TimeoutCatcher } = require('@friggframework/core');
470
+
471
+ exports.handler = async (event, context) => {
472
+ const timeoutCatcher = new TimeoutCatcher(context);
473
+
474
+ if (timeoutCatcher.isNearTimeout()) {
475
+ // Save state and exit gracefully
476
+ }
477
+ };
478
+ ```
479
+
480
+ ## Development Workflow
481
+
482
+ ### Adding a New Use Case
483
+
484
+ 1. **Create use case file** in appropriate `use-cases/` directory:
485
+
486
+ ```javascript
487
+ // integrations/use-cases/my-new-use-case.js
488
+ class MyNewUseCase {
489
+ constructor({ integrationRepository, userRepository }) {
490
+ this.integrationRepo = integrationRepository;
491
+ this.userRepo = userRepository;
492
+ }
493
+
494
+ async execute(userId, integrationId) {
495
+ // Business logic here
496
+ const user = await this.userRepo.findById(userId);
497
+ const integration = await this.integrationRepo.findById(integrationId);
498
+
499
+ // Validate, orchestrate, coordinate
500
+ // Return result
501
+ }
502
+ }
503
+
504
+ module.exports = { MyNewUseCase };
505
+ ```
506
+
507
+ 2. **Add tests** in corresponding `tests/` directory
508
+ 3. **Export** from parent index.js if needed
509
+ 4. **Use in handler** - handlers call use cases, not repositories
510
+
511
+ ### Adding Encrypted Fields
512
+
513
+ **For custom models** (integration developers):
514
+
515
+ In `backend/index.js`:
516
+
517
+ ```javascript
518
+ const appDefinition = {
519
+ encryption: {
520
+ schema: {
521
+ MyCustomModel: {
522
+ fields: ['secretData', 'data.apiKey']
523
+ }
524
+ }
525
+ }
526
+ };
527
+ ```
528
+
529
+ **For core models** (framework developers):
530
+
531
+ Edit `database/encryption/encryption-schema-registry.js`:
532
+
533
+ ```javascript
534
+ const ENCRYPTION_SCHEMA = {
535
+ MyModel: {
536
+ fields: ['sensitiveField']
537
+ }
538
+ };
539
+ ```
540
+
541
+ ### Database Migrations
542
+
543
+ **MongoDB** (Prisma push):
544
+
545
+ ```bash
546
+ npm run prisma:push:mongo
547
+ ```
548
+
549
+ **PostgreSQL** (Prisma migrate):
550
+
551
+ ```bash
552
+ npm run prisma:migrate:postgres
553
+ ```
554
+
555
+ ### Integration Development
556
+
557
+ 1. **Extend IntegrationBase** in your app
558
+ 2. **Define static Definition** with name, version, modules
559
+ 3. **Implement lifecycle methods**: `onCreate`, `onUpdate`, `onDelete`
560
+ 4. **Add event handlers** for webhooks and user actions
561
+ 5. **Use framework services**: repositories, encryption, logging
562
+
563
+ ## Testing Strategy
564
+
565
+ ### Test Categories
566
+
567
+ 1. **Unit Tests**: Use cases with mocked repositories
568
+ 2. **Integration Tests**: Full flow with real dependencies
569
+ 3. **Repository Tests**: Database operations
570
+ 4. **Handler Tests**: HTTP/Lambda response testing
571
+
572
+ ### Test Structure
573
+
574
+ ```javascript
575
+ describe('MyUseCase', () => {
576
+ let useCase;
577
+ let mockRepository;
578
+
579
+ beforeEach(() => {
580
+ mockRepository = {
581
+ findById: jest.fn(),
582
+ save: jest.fn()
583
+ };
584
+ useCase = new MyUseCase({ repository: mockRepository });
585
+ });
586
+
587
+ it('executes successfully', async () => {
588
+ mockRepository.findById.mockResolvedValue({ id: '123' });
589
+
590
+ const result = await useCase.execute('123');
591
+
592
+ expect(result).toBeDefined();
593
+ expect(mockRepository.findById).toHaveBeenCalledWith('123');
594
+ });
595
+ });
596
+ ```
597
+
598
+ ### Running Tests
599
+
600
+ ```bash
601
+ # All tests
602
+ npm test
603
+
604
+ # Specific file
605
+ npm test -- path/to/test.test.js
606
+
607
+ # Pattern matching
608
+ npm test -- --testPathPattern="encryption"
609
+
610
+ # With coverage
611
+ npm test -- --coverage
612
+ ```
613
+
614
+ ### Test Doubles
615
+
616
+ Use test doubles from `@friggframework/test` package for consistent mocking.
617
+
618
+ ## Anti-Patterns
619
+
620
+ ### Architecture Anti-Patterns
621
+
622
+ ❌ **Don't call repositories from handlers** - Always use use cases
623
+ ❌ **Don't put business logic in repositories** - Repositories are pure data access
624
+ ❌ **Don't put HTTP concerns in use cases** - Use cases are protocol-agnostic
625
+ ❌ **Don't bypass encryption** - Sensitive data must be encrypted
626
+ ❌ **Don't expose internal errors to users** - Use `isUserFacingResponse: true`
627
+ ❌ **Don't skip connection pooling** - Set `callbackWaitsForEmptyEventLoop = false`
628
+
629
+ ### Development Anti-Patterns
630
+
631
+ ❌ **Don't modify node_modules** - Extend through proper patterns
632
+ ❌ **Don't hardcode credentials** - Use environment variables
633
+ ❌ **Don't skip tests** - Maintain test coverage
634
+ ❌ **Don't commit secrets** - Use .gitignore and AWS Secrets Manager
635
+ ❌ **Don't ignore linting errors** - Run `npm run lint:fix`
636
+
637
+ ### Integration Development Anti-Patterns
638
+
639
+ ❌ **Don't bypass IntegrationBase** - Always extend the base class
640
+ ❌ **Don't ignore lifecycle methods** - Implement onCreate, onUpdate, onDelete
641
+ ❌ **Don't skip signature validation** - Validate all webhooks
642
+ ❌ **Don't sync operations in handlers** - Use background workers for long tasks
643
+ ❌ **Don't ignore errors** - Proper error handling and logging
644
+
645
+ ## Environment Variables
646
+
647
+ ### Required
648
+
649
+ - `AWS_REGION` - AWS region for services
650
+ - `DATABASE_URL` - Database connection string (auto-set)
651
+ - `DB_TYPE` - Database type: 'mongodb' or 'postgresql'
652
+
653
+ ### Encryption
654
+
655
+ - `KMS_KEY_ARN` - AWS KMS key ARN (production)
656
+ - `AES_KEY_ID` - AES key ID (development)
657
+ - `AES_KEY` - AES encryption key (development)
658
+ - `STAGE` - Environment stage (dev, test, local bypass encryption)
659
+
660
+ ### Optional
661
+
662
+ - `SECRET_ARN` - AWS Secrets Manager ARN for auto-injection
663
+ - `DEBUG` - Debug logging pattern
664
+ - `LOG_LEVEL` - Logging level (debug, info, warn, error)
665
+
666
+ ## Version Information
667
+
668
+ - **Current Version**: 2.0.0-next.0 (pre-release)
669
+ - **Node.js**: >=18 required
670
+ - **Dependencies**: See package.json for full list
671
+
672
+ ## Support and Documentation
673
+
674
+ - **Main Framework CLAUDE.md**: See root Frigg CLAUDE.md for framework-wide guidance
675
+ - **Core Runtime**: See `core/CLAUDE.md` for Lambda/Worker patterns
676
+ - **Encryption**: See `database/encryption/README.md` for encryption details
677
+ - **Package README**: See `README.md` for API reference
678
+
679
+ ## Recent Important Changes
680
+
681
+ ### Field-Level Encryption JSON Object Support
682
+
683
+ **Date**: 2025-01-06
684
+
685
+ **Problem**: The `FieldEncryptionService` was converting objects to the string `"[object Object]"` before encrypting, corrupting JSON fields like `IntegrationMapping.mapping`.
686
+
687
+ **Solution**: Added `_serializeForEncryption()` and `_deserializeAfterDecryption()` methods:
688
+ - Objects are now JSON.stringify'd before encryption
689
+ - Decrypted strings are JSON.parse'd back to objects
690
+ - Plain strings work as before
691
+
692
+ **Files Changed**:
693
+ - `database/encryption/field-encryption-service.js`
694
+ - `database/encryption/field-encryption-service.test.js`
695
+
696
+ **Test Coverage**: All 40 tests pass, including new object encryption test.
697
+
698
+ **Impact**: `IntegrationMapping.mapping` and other JSON fields now correctly round-trip through encryption.
699
+
700
+ ---
701
+
702
+ **Built with ❤️ by the Frigg Framework team**