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

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 +184 -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 +91 -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
@@ -0,0 +1,257 @@
1
+ // Runtime loader that hydrates process.env from SSM Parameter Store. Used to
2
+ // offload env vars that would otherwise blow past Lambda's 4KB env limit.
3
+ // Real process.env always wins over SSM (a documented local-debugging escape
4
+ // hatch); only keys this loader sets are ever refreshed.
5
+
6
+ const DEFAULT_CACHE_TTL_SECONDS = 300;
7
+ const BATCH_SIZE = 10;
8
+ const THROTTLE_BACKOFF_MS = [100, 200, 400];
9
+ const REFRESH_RETRY_MS = 30_000;
10
+
11
+ let client = null;
12
+ let cacheExpiresAt = null;
13
+ let inflight = null;
14
+ const ownedKeys = new Set();
15
+
16
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
17
+
18
+ const chunk = (items, size) => {
19
+ const batches = [];
20
+ for (let i = 0; i < items.length; i += size) {
21
+ batches.push(items.slice(i, i + size));
22
+ }
23
+ return batches;
24
+ };
25
+
26
+ const getCacheTtlSeconds = () => {
27
+ const raw = process.env.FRIGG_SSM_CACHE_TTL;
28
+ if (raw === undefined || raw === '') {
29
+ return DEFAULT_CACHE_TTL_SECONDS;
30
+ }
31
+ const parsed = Number(raw);
32
+ return Number.isNaN(parsed) ? DEFAULT_CACHE_TTL_SECONDS : parsed;
33
+ };
34
+
35
+ const parseKeys = (raw) =>
36
+ raw
37
+ .split(',')
38
+ .map((key) => key.trim())
39
+ .filter(Boolean);
40
+
41
+ const sendWithRetry = async (ssmClient, command) => {
42
+ let attempt = 0;
43
+ for (;;) {
44
+ try {
45
+ return await ssmClient.send(command);
46
+ } catch (err) {
47
+ if (
48
+ err.name === 'ThrottlingException' &&
49
+ attempt < THROTTLE_BACKOFF_MS.length
50
+ ) {
51
+ await sleep(THROTTLE_BACKOFF_MS[attempt]);
52
+ attempt += 1;
53
+ continue;
54
+ }
55
+ throw err;
56
+ }
57
+ }
58
+ };
59
+
60
+ /**
61
+ * Fetch offloaded parameters and return a plain { key: value } map. Fetch-only:
62
+ * no process.env mutation, no caching, no ownership tracking. Shared by the
63
+ * runtime loader and the INIT-phase preload (ssm-preload.js). Throws (listing
64
+ * every missing name) if any requested key is absent from SSM.
65
+ */
66
+ const fetchOffloadedParameters = async (prefix, keys, { region } = {}) => {
67
+ const { SSMClient, GetParametersCommand } = require('@aws-sdk/client-ssm');
68
+ const ssmClient = new SSMClient({
69
+ region: region || process.env.AWS_REGION,
70
+ });
71
+ const nameFor = (key) => `${prefix}/${key}`;
72
+
73
+ const found = new Map();
74
+ for (const batch of chunk(keys, BATCH_SIZE)) {
75
+ const { Parameters = [] } = await sendWithRetry(
76
+ ssmClient,
77
+ new GetParametersCommand({
78
+ Names: batch.map(nameFor),
79
+ WithDecryption: true,
80
+ })
81
+ );
82
+ for (const param of Parameters) {
83
+ found.set(param.Name, param);
84
+ }
85
+ }
86
+
87
+ const missing = keys.map(nameFor).filter((name) => !found.has(name));
88
+ if (missing.length > 0) {
89
+ throw new Error(
90
+ `missing SSM parameters under ${prefix}: ${missing.join(', ')}`
91
+ );
92
+ }
93
+
94
+ const values = {};
95
+ for (const key of keys) {
96
+ values[key] = found.get(nameFor(key)).Value;
97
+ }
98
+ return values;
99
+ };
100
+
101
+ const loadParameters = async (prefix, keys) => {
102
+ const { SSMClient, GetParametersCommand } = require('@aws-sdk/client-ssm');
103
+ if (!client) {
104
+ client = new SSMClient({ region: process.env.AWS_REGION });
105
+ }
106
+
107
+ // A key already living in process.env wins over SSM, except keys we set
108
+ // ourselves — those we refresh so later invocations pick up rotations.
109
+ const keysToFetch = keys.filter(
110
+ (key) => ownedKeys.has(key) || process.env[key] === undefined
111
+ );
112
+ const nameFor = (key) => `${prefix}/${key}`;
113
+
114
+ // A refresh means every key already has a served value; a warm container
115
+ // must keep serving stale values through an SSM blip instead of erroring.
116
+ const isRefresh =
117
+ keysToFetch.length > 0 &&
118
+ keysToFetch.every((key) => ownedKeys.has(key));
119
+
120
+ const found = new Map();
121
+ try {
122
+ for (const batch of chunk(keysToFetch, BATCH_SIZE)) {
123
+ const { Parameters = [] } = await sendWithRetry(
124
+ client,
125
+ new GetParametersCommand({
126
+ Names: batch.map(nameFor),
127
+ WithDecryption: true,
128
+ })
129
+ );
130
+ for (const param of Parameters) {
131
+ found.set(param.Name, param);
132
+ }
133
+ }
134
+
135
+ const missing = keysToFetch
136
+ .map(nameFor)
137
+ .filter((name) => !found.has(name));
138
+ if (missing.length > 0) {
139
+ throw new Error(
140
+ `parametersToEnv: missing SSM parameters under ${prefix}: ${missing.join(
141
+ ', '
142
+ )}`
143
+ );
144
+ }
145
+ } catch (err) {
146
+ if (!isRefresh) {
147
+ throw err;
148
+ }
149
+ console.warn(
150
+ `parametersToEnv: refresh failed, keeping cached values: ${err.message}`
151
+ );
152
+ cacheExpiresAt = Date.now() + REFRESH_RETRY_MS;
153
+ return;
154
+ }
155
+
156
+ const loaded = keysToFetch.map((key) => {
157
+ const param = found.get(nameFor(key));
158
+ process.env[key] = param.Value;
159
+ ownedKeys.add(key);
160
+ return `${param.Name} (v${param.Version})`;
161
+ });
162
+
163
+ const ttlSeconds = getCacheTtlSeconds();
164
+ cacheExpiresAt =
165
+ ttlSeconds === 0 ? Infinity : Date.now() + ttlSeconds * 1000;
166
+
167
+ if (loaded.length > 0) {
168
+ console.log('parametersToEnv: loaded', loaded);
169
+ }
170
+ };
171
+
172
+ /**
173
+ * Hydrate process.env from SSM Parameter Store.
174
+ *
175
+ * No-op unless both SSM_PARAMETER_PREFIX and FRIGG_SSM_OFFLOADED_KEYS are set.
176
+ * Results are cached for FRIGG_SSM_CACHE_TTL seconds (default 300; 0 = forever).
177
+ * A failed fetch is never cached, so the next invocation retries.
178
+ */
179
+ const parametersToEnv = async () => {
180
+ const prefix = process.env.SSM_PARAMETER_PREFIX;
181
+ const rawKeys = process.env.FRIGG_SSM_OFFLOADED_KEYS;
182
+ if (!prefix || !rawKeys) {
183
+ return;
184
+ }
185
+ const keys = parseKeys(rawKeys);
186
+ if (keys.length === 0) {
187
+ return;
188
+ }
189
+
190
+ if (cacheExpiresAt !== null && Date.now() < cacheExpiresAt) {
191
+ return;
192
+ }
193
+
194
+ if (!inflight) {
195
+ inflight = loadParameters(prefix, keys).finally(() => {
196
+ inflight = null;
197
+ });
198
+ }
199
+ return inflight;
200
+ };
201
+
202
+ /**
203
+ * Adopt keys the INIT preload (ssm-preload.mjs) already populated into
204
+ * process.env, so the handler-time loader treats them as its own: it seeds
205
+ * the cache TTL and marks the keys owned so the TTL-refresh path re-fetches
206
+ * them. The preload runs in-process (NODE_OPTIONS=--import), sharing this
207
+ * module singleton. Pass ONLY the keys the preload actually set (not keys
208
+ * already present as real env vars) so the real-env-wins rule is preserved.
209
+ */
210
+ const adoptPreloadedKeys = (keys) => {
211
+ for (const key of keys) {
212
+ ownedKeys.add(key);
213
+ }
214
+ const ttlSeconds = getCacheTtlSeconds();
215
+ cacheExpiresAt =
216
+ ttlSeconds === 0 ? Infinity : Date.now() + ttlSeconds * 1000;
217
+ };
218
+
219
+ /**
220
+ * INIT-phase preload used by ssm-preload.mjs: fetch offloaded parameters and
221
+ * set them into process.env, then adopt the keys it set so the handler-time
222
+ * loader refreshes them on TTL. Real env wins — a key already present is never
223
+ * fetched or overwritten, so a console override keeps working even if that
224
+ * key's parameter is absent from SSM (fetching it would fail INIT). Returns the
225
+ * keys actually set (empty when every key was already in real env). Throws,
226
+ * listing the names, only for a genuinely-needed parameter that is missing.
227
+ */
228
+ const preloadOffloadedParameters = async (prefix, keys, options = {}) => {
229
+ const keysToFetch = keys.filter((key) => process.env[key] === undefined);
230
+ if (keysToFetch.length === 0) {
231
+ return [];
232
+ }
233
+
234
+ const values = await fetchOffloadedParameters(prefix, keysToFetch, options);
235
+ const setKeys = [];
236
+ for (const [key, value] of Object.entries(values)) {
237
+ process.env[key] = value;
238
+ setKeys.push(key);
239
+ }
240
+ adoptPreloadedKeys(setKeys);
241
+ return setKeys;
242
+ };
243
+
244
+ const _resetCache = () => {
245
+ client = null;
246
+ cacheExpiresAt = null;
247
+ inflight = null;
248
+ ownedKeys.clear();
249
+ };
250
+
251
+ module.exports = {
252
+ parametersToEnv,
253
+ fetchOffloadedParameters,
254
+ preloadOffloadedParameters,
255
+ adoptPreloadedKeys,
256
+ _resetCache,
257
+ };
@@ -1,5 +1,9 @@
1
+ const { getLogger } = require('../logs');
2
+
3
+ const log = getLogger('frigg.core.secrets');
4
+
1
5
  const getSecretValue = async () => {
2
- console.log('Fetching secrets...');
6
+ log.debug('Fetching secrets', { eventName: 'frigg.core.secrets.fetching' });
3
7
 
4
8
  const httpPort = process.env.PARAMETERS_SECRETS_EXTENSION_HTTP_PORT || 2773;
5
9
  const url = `http://localhost:${httpPort}/secretsmanager/get?secretId=${encodeURIComponent(
@@ -15,10 +19,7 @@ const getSecretValue = async () => {
15
19
  const response = await fetch(url, options);
16
20
 
17
21
  if (!response.ok) {
18
- const json = await response.json().catch((err) => err.message);
19
- console.error('Invalid response - response:', JSON.stringify(response));
20
- console.error('Invalid response - json:', json);
21
- throw new Error(`Invalid ${response.status} response`);
22
+ throw new Error(`Secrets fetch failed with ${response.status}`);
22
23
  }
23
24
 
24
25
  const result = await response.json();
@@ -44,7 +45,7 @@ const secretsToEnv = async () => {
44
45
  if (!process.env.SECRET_ARN) {
45
46
  return;
46
47
  }
47
- console.log('Secrets to env');
48
+ log.debug('Secrets to env', { eventName: 'frigg.core.secrets.to_env' });
48
49
 
49
50
  try {
50
51
  const secrets = await getSecretValue();
@@ -0,0 +1,34 @@
1
+ // INIT-phase SSM loader (ADR-027).
2
+ //
3
+ // Loaded via NODE_OPTIONS=--import BEFORE the Lambda handler and any api-module
4
+ // is required, so SSM-offloaded values are present in process.env at
5
+ // module-load time — when api-modules capture their OAuth client credentials
6
+ // in a top-level `const Definition = { env: { client_secret: process.env.X } }`.
7
+ // The runtime loader (parameters-to-env.js) runs inside the handler, which is
8
+ // too late for those module-load reads; this preload closes that gap.
9
+ //
10
+ // Top-level await here is awaited by Node before the entry module loads, so the
11
+ // fetch completes first. A fetch failure rejects the preload, failing Lambda
12
+ // INIT loudly (fail-fast) rather than starting with undefined credentials.
13
+
14
+ import { createRequire } from 'module';
15
+
16
+ const require = createRequire(import.meta.url);
17
+
18
+ const prefix = process.env.SSM_PARAMETER_PREFIX;
19
+ const rawKeys = process.env.FRIGG_SSM_OFFLOADED_KEYS;
20
+
21
+ if (prefix && rawKeys) {
22
+ const keys = rawKeys
23
+ .split(',')
24
+ .map((key) => key.trim())
25
+ .filter(Boolean);
26
+
27
+ if (keys.length > 0) {
28
+ // The fetch/real-env-wins/adopt logic lives in the CJS module (tested
29
+ // there); this preload is a thin INIT-phase shim over it.
30
+ const { preloadOffloadedParameters } = require('./parameters-to-env');
31
+ const setKeys = await preloadOffloadedParameters(prefix, keys);
32
+ console.log(`frigg-ssm-preload: loaded ${setKeys.length} parameter(s) at INIT under ${prefix}`);
33
+ }
34
+ }
@@ -0,0 +1,32 @@
1
+ const UNKNOWN_TYPE = 'unknown';
2
+
3
+ /**
4
+ * Type is derived from the related Entity.moduleName since Credential carries
5
+ * no type column. Counted once per distinct linked moduleName; none → `unknown`.
6
+ * Reads only the non-encrypted projection — never `data`/secrets.
7
+ */
8
+ function tallyActiveCredentialsByType(credentials = []) {
9
+ const counts = new Map();
10
+
11
+ for (const credential of credentials) {
12
+ const modules = new Set(
13
+ (credential?.entities || [])
14
+ .map((entity) => entity?.moduleName)
15
+ .filter(
16
+ (moduleName) => moduleName != null && moduleName !== ''
17
+ )
18
+ );
19
+ const types = modules.size > 0 ? [...modules] : [UNKNOWN_TYPE];
20
+
21
+ for (const type of types) {
22
+ counts.set(type, (counts.get(type) || 0) + 1);
23
+ }
24
+ }
25
+
26
+ return [...counts].map(([integrationType, count]) => ({
27
+ integrationType,
28
+ count,
29
+ }));
30
+ }
31
+
32
+ module.exports = { tallyActiveCredentialsByType, UNKNOWN_TYPE };