n8n-workflow-builder-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (595) hide show
  1. package/.cursor/rules/cursor_rules.mdc +53 -0
  2. package/.cursor/rules/dev_workflow.mdc +219 -0
  3. package/.cursor/rules/mcp.mdc +430 -0
  4. package/.cursor/rules/self_improve.mdc +72 -0
  5. package/.cursor/rules/taskmaster.mdc +382 -0
  6. package/.cursorignore +1 -0
  7. package/.cursorrules +4 -0
  8. package/.env.example +23 -0
  9. package/.eslintrc.json +38 -0
  10. package/.github/workflows/npm-publish-github-packages.yml +55 -0
  11. package/.prettierrc +9 -0
  12. package/.roo/rules/dev_workflow.md +219 -0
  13. package/.roo/rules/mcp.md +430 -0
  14. package/.roo/rules/roo_rules.md +53 -0
  15. package/.roo/rules/self_improve.md +72 -0
  16. package/.roo/rules/taskmaster.md +382 -0
  17. package/.roo/rules-architect/architect-rules +93 -0
  18. package/.roo/rules-ask/ask-rules +89 -0
  19. package/.roo/rules-boomerang/boomerang-rules +181 -0
  20. package/.roo/rules-code/code-rules +61 -0
  21. package/.roo/rules-debug/debug-rules +68 -0
  22. package/.roo/rules-test/test-rules +61 -0
  23. package/.roomodes +63 -0
  24. package/.taskmasterconfig +31 -0
  25. package/.windsurfrules +2382 -0
  26. package/LICENSE +21 -0
  27. package/README.md +210 -0
  28. package/config/credentials/credentials.json +1 -0
  29. package/config/default.js +41 -0
  30. package/package.json +56 -0
  31. package/scripts/demo-n8n-integration.js +161 -0
  32. package/scripts/demo-workflow-generator.js +102 -0
  33. package/scripts/init.sh +36 -0
  34. package/scripts/prd.txt +197 -0
  35. package/src/index.ts +1440 -0
  36. package/src/middleware/auth.js +273 -0
  37. package/src/middleware/authorize.js +183 -0
  38. package/src/middleware/logging.js +64 -0
  39. package/src/middleware/mcp.js +187 -0
  40. package/src/middleware/rateLimiter.js +82 -0
  41. package/src/middleware/validation.js +241 -0
  42. package/src/models/credential.js +359 -0
  43. package/src/models/llmService.js +236 -0
  44. package/src/models/n8nIntegration.js +542 -0
  45. package/src/models/storage.js +196 -0
  46. package/src/models/tool.js +148 -0
  47. package/src/models/user.js +164 -0
  48. package/src/models/workflow.js +229 -0
  49. package/src/routes/toolDefinitions.js +62 -0
  50. package/src/routes/toolExecution.js +79 -0
  51. package/src/tools/__index.js +242 -0
  52. package/src/tools/connectionManagement.js +500 -0
  53. package/src/tools/n8nIntegration.js +370 -0
  54. package/src/tools/nodeDiscovery.js +488 -0
  55. package/src/tools/nodeManagement.js +674 -0
  56. package/src/tools/toolDefinitions.js +660 -0
  57. package/src/tools/workflowCreation.js +100 -0
  58. package/src/tools/workflowGenerator.js +152 -0
  59. package/src/tools/workflowStorage.js +113 -0
  60. package/src/tools/workflowTesting.js +285 -0
  61. package/src/utils/encryption.js +164 -0
  62. package/src/utils/logger.js +84 -0
  63. package/src/utils/mcp.js +85 -0
  64. package/src/utils/securityLogger.js +109 -0
  65. package/tests/auth.test.js +402 -0
  66. package/tests/authorize.test.js +208 -0
  67. package/tests/run-memory-tests.js +55 -0
  68. package/tests/run-tests.js +55 -0
  69. package/tests/server.test.js +203 -0
  70. package/tests/unit/add-ai-connections.test.js +385 -0
  71. package/tests/unit/connectionManagement.test.js +309 -0
  72. package/tests/unit/langchain-llm-format.test.js +259 -0
  73. package/tests/unit/memory-connection.test.js +140 -0
  74. package/tests/unit/memory-integration.test.js +253 -0
  75. package/tests/unit/n8nIntegration.test.js +291 -0
  76. package/tests/unit/nodeDiscovery.test.js +270 -0
  77. package/tests/unit/nodeManagement.test.js +522 -0
  78. package/tests/unit/utils/mcp-test-utils.js +94 -0
  79. package/tests/unit/workflowCreation.test.js +110 -0
  80. package/tests/unit/workflowTesting.test.js +269 -0
  81. package/tests/user.test.js +181 -0
  82. package/tsconfig.json +20 -0
  83. package/workflow_nodes/Brandfetch.json +85 -0
  84. package/workflow_nodes/WorkflowTrigger.json +28 -0
  85. package/workflow_nodes/actionNetwork.json +218 -0
  86. package/workflow_nodes/activeCampaign.json +722 -0
  87. package/workflow_nodes/activeCampaignTrigger.json +52 -0
  88. package/workflow_nodes/acuitySchedulingTrigger.json +8 -0
  89. package/workflow_nodes/adalo.json +123 -0
  90. package/workflow_nodes/affinity.json +203 -0
  91. package/workflow_nodes/affinityTrigger.json +124 -0
  92. package/workflow_nodes/aggregate.json +119 -0
  93. package/workflow_nodes/agileCrm.json +503 -0
  94. package/workflow_nodes/aiTransform.json +17 -0
  95. package/workflow_nodes/airtable.json +226 -0
  96. package/workflow_nodes/airtableTrigger.json +120 -0
  97. package/workflow_nodes/airtop.json +10 -0
  98. package/workflow_nodes/amqp.json +62 -0
  99. package/workflow_nodes/amqpTrigger.json +8 -0
  100. package/workflow_nodes/apiTemplateIo.json +147 -0
  101. package/workflow_nodes/asana.json +446 -0
  102. package/workflow_nodes/asanaTrigger.json +52 -0
  103. package/workflow_nodes/automizy.json +195 -0
  104. package/workflow_nodes/autopilot.json +287 -0
  105. package/workflow_nodes/autopilotTrigger.json +8 -0
  106. package/workflow_nodes/awsCertificateManager.json +223 -0
  107. package/workflow_nodes/awsComprehend.json +125 -0
  108. package/workflow_nodes/awsDynamoDb.json +251 -0
  109. package/workflow_nodes/awsElb.json +174 -0
  110. package/workflow_nodes/awsLambda.json +69 -0
  111. package/workflow_nodes/awsRekognition.json +191 -0
  112. package/workflow_nodes/awsS3.json +32 -0
  113. package/workflow_nodes/awsSes.json +302 -0
  114. package/workflow_nodes/awsSns.json +110 -0
  115. package/workflow_nodes/awsSnsTrigger.json +47 -0
  116. package/workflow_nodes/awsSqs.json +140 -0
  117. package/workflow_nodes/awsTextract.json +43 -0
  118. package/workflow_nodes/awsTranscribe.json +217 -0
  119. package/workflow_nodes/azureCosmosDb.json +8 -0
  120. package/workflow_nodes/azureStorage.json +17 -0
  121. package/workflow_nodes/bambooHr.json +8 -0
  122. package/workflow_nodes/bannerbear.json +126 -0
  123. package/workflow_nodes/baserow.json +277 -0
  124. package/workflow_nodes/beeminder.json +146 -0
  125. package/workflow_nodes/bitbucketTrigger.json +62 -0
  126. package/workflow_nodes/bitly.json +130 -0
  127. package/workflow_nodes/bitwarden.json +224 -0
  128. package/workflow_nodes/box.json +457 -0
  129. package/workflow_nodes/boxTrigger.json +8 -0
  130. package/workflow_nodes/brevo.json +41 -0
  131. package/workflow_nodes/brevoTrigger.json +145 -0
  132. package/workflow_nodes/bubble.json +212 -0
  133. package/workflow_nodes/calTrigger.json +91 -0
  134. package/workflow_nodes/calendlyTrigger.json +71 -0
  135. package/workflow_nodes/chargebee.json +217 -0
  136. package/workflow_nodes/chargebeeTrigger.json +187 -0
  137. package/workflow_nodes/circleCi.json +89 -0
  138. package/workflow_nodes/ciscoWebex.json +593 -0
  139. package/workflow_nodes/ciscoWebexTrigger.json +159 -0
  140. package/workflow_nodes/clearbit.json +138 -0
  141. package/workflow_nodes/clickUp.json +793 -0
  142. package/workflow_nodes/clickUpTrigger.json +188 -0
  143. package/workflow_nodes/clockify.json +372 -0
  144. package/workflow_nodes/clockifyTrigger.json +26 -0
  145. package/workflow_nodes/cloudflare.json +103 -0
  146. package/workflow_nodes/cockpit.json +161 -0
  147. package/workflow_nodes/coda.json +242 -0
  148. package/workflow_nodes/code.json +40 -0
  149. package/workflow_nodes/coinGecko.json +363 -0
  150. package/workflow_nodes/compareDatasets.json +14 -0
  151. package/workflow_nodes/compression.json +66 -0
  152. package/workflow_nodes/contentful.json +29 -0
  153. package/workflow_nodes/convertKit.json +159 -0
  154. package/workflow_nodes/convertKitTrigger.json +109 -0
  155. package/workflow_nodes/convertToFile.json +64 -0
  156. package/workflow_nodes/copper.json +239 -0
  157. package/workflow_nodes/copperTrigger.json +8 -0
  158. package/workflow_nodes/cortex.json +348 -0
  159. package/workflow_nodes/crateDb.json +90 -0
  160. package/workflow_nodes/cron.json +23 -0
  161. package/workflow_nodes/crowdDev.json +8 -0
  162. package/workflow_nodes/crowdDevTrigger.json +8 -0
  163. package/workflow_nodes/crypto.json +147 -0
  164. package/workflow_nodes/customerIo.json +206 -0
  165. package/workflow_nodes/customerIoTrigger.json +185 -0
  166. package/workflow_nodes/dateTime.json +39 -0
  167. package/workflow_nodes/debughelper.json +162 -0
  168. package/workflow_nodes/deepL.json +103 -0
  169. package/workflow_nodes/demio.json +187 -0
  170. package/workflow_nodes/dhl.json +53 -0
  171. package/workflow_nodes/discord.json +81 -0
  172. package/workflow_nodes/discourse.json +319 -0
  173. package/workflow_nodes/disqus.json +254 -0
  174. package/workflow_nodes/drift.json +112 -0
  175. package/workflow_nodes/dropbox.json +258 -0
  176. package/workflow_nodes/dropcontact.json +154 -0
  177. package/workflow_nodes/e2eTest.json +70 -0
  178. package/workflow_nodes/editImage.json +132 -0
  179. package/workflow_nodes/egoi.json +220 -0
  180. package/workflow_nodes/elasticSecurity.json +401 -0
  181. package/workflow_nodes/elasticsearch.json +422 -0
  182. package/workflow_nodes/emailReadImap.json +88 -0
  183. package/workflow_nodes/emailSend.json +38 -0
  184. package/workflow_nodes/emelia.json +201 -0
  185. package/workflow_nodes/emeliaTrigger.json +57 -0
  186. package/workflow_nodes/erpNext.json +139 -0
  187. package/workflow_nodes/errorTrigger.json +15 -0
  188. package/workflow_nodes/evaluationMetrics.json +21 -0
  189. package/workflow_nodes/eventbriteTrigger.json +125 -0
  190. package/workflow_nodes/executeCommand.json +25 -0
  191. package/workflow_nodes/executeWorkflow.json +102 -0
  192. package/workflow_nodes/executeWorkflowTrigger.json +65 -0
  193. package/workflow_nodes/executionData.json +35 -0
  194. package/workflow_nodes/extractFromFile.json +71 -0
  195. package/workflow_nodes/facebookGraphApi.json +234 -0
  196. package/workflow_nodes/facebookLeadAdsTrigger.json +8 -0
  197. package/workflow_nodes/facebookTrigger.json +112 -0
  198. package/workflow_nodes/figmaTrigger.json +8 -0
  199. package/workflow_nodes/filemaker.json +268 -0
  200. package/workflow_nodes/filter.json +24 -0
  201. package/workflow_nodes/flow.json +323 -0
  202. package/workflow_nodes/flowTrigger.json +52 -0
  203. package/workflow_nodes/form.json +25 -0
  204. package/workflow_nodes/formIoTrigger.json +59 -0
  205. package/workflow_nodes/formTrigger.json +8 -0
  206. package/workflow_nodes/formstackTrigger.json +8 -0
  207. package/workflow_nodes/freshdesk.json +584 -0
  208. package/workflow_nodes/freshservice.json +899 -0
  209. package/workflow_nodes/freshworksCrm.json +772 -0
  210. package/workflow_nodes/ftp.json +127 -0
  211. package/workflow_nodes/function.json +22 -0
  212. package/workflow_nodes/functionItem.json +22 -0
  213. package/workflow_nodes/gSuiteAdmin.json +562 -0
  214. package/workflow_nodes/getResponse.json +310 -0
  215. package/workflow_nodes/getResponseTrigger.json +82 -0
  216. package/workflow_nodes/ghost.json +290 -0
  217. package/workflow_nodes/git.json +184 -0
  218. package/workflow_nodes/github.json +732 -0
  219. package/workflow_nodes/githubTrigger.json +317 -0
  220. package/workflow_nodes/gitlab.json +544 -0
  221. package/workflow_nodes/gitlabTrigger.json +61 -0
  222. package/workflow_nodes/gmail.json +62 -0
  223. package/workflow_nodes/gmailTrigger.json +127 -0
  224. package/workflow_nodes/goToWebinar.json +430 -0
  225. package/workflow_nodes/gong.json +22 -0
  226. package/workflow_nodes/googleAds.json +116 -0
  227. package/workflow_nodes/googleAnalytics.json +28 -0
  228. package/workflow_nodes/googleBigQuery.json +38 -0
  229. package/workflow_nodes/googleBooks.json +154 -0
  230. package/workflow_nodes/googleBusinessProfile.json +277 -0
  231. package/workflow_nodes/googleBusinessProfileTrigger.json +55 -0
  232. package/workflow_nodes/googleCalendar.json +474 -0
  233. package/workflow_nodes/googleCalendarTrigger.json +72 -0
  234. package/workflow_nodes/googleChat.json +187 -0
  235. package/workflow_nodes/googleCloudNaturalLanguage.json +171 -0
  236. package/workflow_nodes/googleCloudStorage.json +466 -0
  237. package/workflow_nodes/googleContacts.json +481 -0
  238. package/workflow_nodes/googleDocs.json +312 -0
  239. package/workflow_nodes/googleDrive.json +920 -0
  240. package/workflow_nodes/googleDriveTrigger.json +181 -0
  241. package/workflow_nodes/googleFirebaseCloudFirestore.json +156 -0
  242. package/workflow_nodes/googleFirebaseRealtimeDatabase.json +75 -0
  243. package/workflow_nodes/googlePerspective.json +94 -0
  244. package/workflow_nodes/googleSheets.json +98 -0
  245. package/workflow_nodes/googleSheetsTrigger.json +192 -0
  246. package/workflow_nodes/googleSlides.json +186 -0
  247. package/workflow_nodes/googleTasks.json +198 -0
  248. package/workflow_nodes/googleTranslate.json +80 -0
  249. package/workflow_nodes/gotify.json +110 -0
  250. package/workflow_nodes/grafana.json +155 -0
  251. package/workflow_nodes/graphql.json +165 -0
  252. package/workflow_nodes/grist.json +13 -0
  253. package/workflow_nodes/gumroadTrigger.json +8 -0
  254. package/workflow_nodes/hackerNews.json +100 -0
  255. package/workflow_nodes/haloPSA.json +286 -0
  256. package/workflow_nodes/harvest.json +699 -0
  257. package/workflow_nodes/helpScout.json +629 -0
  258. package/workflow_nodes/helpScoutTrigger.json +8 -0
  259. package/workflow_nodes/highLevel.json +8 -0
  260. package/workflow_nodes/homeAssistant.json +201 -0
  261. package/workflow_nodes/html.json +118 -0
  262. package/workflow_nodes/htmlExtract.json +87 -0
  263. package/workflow_nodes/httpRequest.json +472 -0
  264. package/workflow_nodes/hubspot.json +62 -0
  265. package/workflow_nodes/hubspotTrigger.json +138 -0
  266. package/workflow_nodes/humanticAi.json +82 -0
  267. package/workflow_nodes/hunter.json +168 -0
  268. package/workflow_nodes/iCal.json +20 -0
  269. package/workflow_nodes/if.json +24 -0
  270. package/workflow_nodes/intercom.json +335 -0
  271. package/workflow_nodes/interval.json +8 -0
  272. package/workflow_nodes/invoiceNinja.json +882 -0
  273. package/workflow_nodes/invoiceNinjaTrigger.json +11 -0
  274. package/workflow_nodes/itemLists.json +313 -0
  275. package/workflow_nodes/iterable.json +168 -0
  276. package/workflow_nodes/jenkins.json +172 -0
  277. package/workflow_nodes/jira.json +529 -0
  278. package/workflow_nodes/jiraTrigger.json +308 -0
  279. package/workflow_nodes/jotFormTrigger.json +44 -0
  280. package/workflow_nodes/jwt.json +195 -0
  281. package/workflow_nodes/kafka.json +132 -0
  282. package/workflow_nodes/kafkaTrigger.json +11 -0
  283. package/workflow_nodes/keap.json +915 -0
  284. package/workflow_nodes/keapTrigger.json +37 -0
  285. package/workflow_nodes/kitemaker.json +153 -0
  286. package/workflow_nodes/koBoToolbox.json +337 -0
  287. package/workflow_nodes/koBoToolboxTrigger.json +8 -0
  288. package/workflow_nodes/langchain_Summarization Chain.json +60 -0
  289. package/workflow_nodes/langchain_agent.json +145 -0
  290. package/workflow_nodes/langchain_allowFileUploads.json +180 -0
  291. package/workflow_nodes/langchain_chainLlm.json +16 -0
  292. package/workflow_nodes/langchain_chainSummarization.json +119 -0
  293. package/workflow_nodes/langchain_code.json +62 -0
  294. package/workflow_nodes/langchain_documentBinaryInputLoader.json +8 -0
  295. package/workflow_nodes/langchain_documentDefaultDataLoader.json +8 -0
  296. package/workflow_nodes/langchain_documentGithubLoader.json +8 -0
  297. package/workflow_nodes/langchain_documentJsonInputLoader.json +8 -0
  298. package/workflow_nodes/langchain_embeddingDimensions.json +17 -0
  299. package/workflow_nodes/langchain_embeddingsAwsBedrock.json +8 -0
  300. package/workflow_nodes/langchain_embeddingsAzureOpenAi.json +151 -0
  301. package/workflow_nodes/langchain_embeddingsCohere.json +8 -0
  302. package/workflow_nodes/langchain_embeddingsGoogleGemini.json +8 -0
  303. package/workflow_nodes/langchain_embeddingsGoogleVertex.json +8 -0
  304. package/workflow_nodes/langchain_embeddingsHuggingFaceInference.json +8 -0
  305. package/workflow_nodes/langchain_embeddingsMistralCloud.json +8 -0
  306. package/workflow_nodes/langchain_embeddingsOllama.json +8 -0
  307. package/workflow_nodes/langchain_informationExtractor.json +81 -0
  308. package/workflow_nodes/langchain_lmChatAwsBedrock.json +8 -0
  309. package/workflow_nodes/langchain_lmChatAzureOpenAi.json +151 -0
  310. package/workflow_nodes/langchain_lmChatDeepSeek.json +10 -0
  311. package/workflow_nodes/langchain_lmChatGoogleGemini.json +31 -0
  312. package/workflow_nodes/langchain_lmChatGoogleVertex.json +32 -0
  313. package/workflow_nodes/langchain_lmChatGroq.json +8 -0
  314. package/workflow_nodes/langchain_lmChatMistralCloud.json +8 -0
  315. package/workflow_nodes/langchain_lmChatOllama.json +8 -0
  316. package/workflow_nodes/langchain_lmChatOpenAi.json +155 -0
  317. package/workflow_nodes/langchain_lmChatOpenRouter.json +10 -0
  318. package/workflow_nodes/langchain_lmChatXAiGrok.json +10 -0
  319. package/workflow_nodes/langchain_lmCohere.json +8 -0
  320. package/workflow_nodes/langchain_lmOllama.json +8 -0
  321. package/workflow_nodes/langchain_lmOpenAi.json +251 -0
  322. package/workflow_nodes/langchain_lmOpenHuggingFaceInference.json +8 -0
  323. package/workflow_nodes/langchain_manualChatTrigger.json +11 -0
  324. package/workflow_nodes/langchain_mcpClientTool.json +86 -0
  325. package/workflow_nodes/langchain_mcpTrigger.json +8 -0
  326. package/workflow_nodes/langchain_memoryBufferWindow.json +13 -0
  327. package/workflow_nodes/langchain_memoryChatRetriever.json +22 -0
  328. package/workflow_nodes/langchain_memoryManager.json +106 -0
  329. package/workflow_nodes/langchain_memoryMongoDbChat.json +10 -0
  330. package/workflow_nodes/langchain_memoryMotorhead.json +13 -0
  331. package/workflow_nodes/langchain_memoryPostgresChat.json +13 -0
  332. package/workflow_nodes/langchain_memoryRedisChat.json +15 -0
  333. package/workflow_nodes/langchain_memoryXata.json +14 -0
  334. package/workflow_nodes/langchain_memoryZep.json +13 -0
  335. package/workflow_nodes/langchain_model.json +155 -0
  336. package/workflow_nodes/langchain_mongoCollection.json +16 -0
  337. package/workflow_nodes/langchain_notice.json +22 -0
  338. package/workflow_nodes/langchain_openAiAssistant.json +132 -0
  339. package/workflow_nodes/langchain_options.json +17 -0
  340. package/workflow_nodes/langchain_outputParserAutofixing.json +8 -0
  341. package/workflow_nodes/langchain_outputParserItemList.json +8 -0
  342. package/workflow_nodes/langchain_outputParserStructured.json +12 -0
  343. package/workflow_nodes/langchain_pineconeNamespace.json +16 -0
  344. package/workflow_nodes/langchain_queryName.json +16 -0
  345. package/workflow_nodes/langchain_retrieverContextualCompression.json +8 -0
  346. package/workflow_nodes/langchain_retrieverMultiQuery.json +8 -0
  347. package/workflow_nodes/langchain_retrieverVectorStore.json +8 -0
  348. package/workflow_nodes/langchain_retrieverWorkflow.json +103 -0
  349. package/workflow_nodes/langchain_sentimentAnalysis.json +52 -0
  350. package/workflow_nodes/langchain_systemPromptTemplate.json +47 -0
  351. package/workflow_nodes/langchain_tableName.json +23 -0
  352. package/workflow_nodes/langchain_textClassifier.json +66 -0
  353. package/workflow_nodes/langchain_textSplitterCharacterTextSplitter.json +8 -0
  354. package/workflow_nodes/langchain_textSplitterRecursiveCharacterTextSplitter.json +8 -0
  355. package/workflow_nodes/langchain_textSplitterTokenSplitter.json +8 -0
  356. package/workflow_nodes/langchain_toolCalculator.json +8 -0
  357. package/workflow_nodes/langchain_toolCode.json +12 -0
  358. package/workflow_nodes/langchain_toolHttpRequest.json +232 -0
  359. package/workflow_nodes/langchain_toolSearXng.json +8 -0
  360. package/workflow_nodes/langchain_toolSerpApi.json +8 -0
  361. package/workflow_nodes/langchain_toolThink.json +8 -0
  362. package/workflow_nodes/langchain_toolVectorStore.json +11 -0
  363. package/workflow_nodes/langchain_toolWikipedia.json +8 -0
  364. package/workflow_nodes/langchain_toolWolframAlpha.json +8 -0
  365. package/workflow_nodes/langchain_toolWorkflow.json +8 -0
  366. package/workflow_nodes/langchain_vectorStoreInMemoryInsert.json +29 -0
  367. package/workflow_nodes/langchain_vectorStoreInMemoryLoad.json +8 -0
  368. package/workflow_nodes/langchain_vectorStorePineconeInsert.json +37 -0
  369. package/workflow_nodes/langchain_vectorStorePineconeLoad.json +8 -0
  370. package/workflow_nodes/langchain_vectorStoreSupabaseInsert.json +32 -0
  371. package/workflow_nodes/langchain_vectorStoreSupabaseLoad.json +8 -0
  372. package/workflow_nodes/langchain_vectorStoreZepInsert.json +46 -0
  373. package/workflow_nodes/langchain_vectorStoreZepLoad.json +8 -0
  374. package/workflow_nodes/ldap.json +182 -0
  375. package/workflow_nodes/lemlist.json +44 -0
  376. package/workflow_nodes/lemlistTrigger.json +45 -0
  377. package/workflow_nodes/limit.json +26 -0
  378. package/workflow_nodes/line.json +95 -0
  379. package/workflow_nodes/linear.json +151 -0
  380. package/workflow_nodes/linearTrigger.json +71 -0
  381. package/workflow_nodes/lingvaNex.json +66 -0
  382. package/workflow_nodes/linkedIn.json +142 -0
  383. package/workflow_nodes/localFileTrigger.json +120 -0
  384. package/workflow_nodes/lonescale.json +171 -0
  385. package/workflow_nodes/lonescaleTrigger.json +8 -0
  386. package/workflow_nodes/magento2.json +164 -0
  387. package/workflow_nodes/mailcheck.json +46 -0
  388. package/workflow_nodes/mailchimp.json +507 -0
  389. package/workflow_nodes/mailchimpTrigger.json +100 -0
  390. package/workflow_nodes/mailerLite.json +24 -0
  391. package/workflow_nodes/mailerLiteTrigger.json +74 -0
  392. package/workflow_nodes/mailgun.json +81 -0
  393. package/workflow_nodes/mailjet.json +201 -0
  394. package/workflow_nodes/mailjetTrigger.json +8 -0
  395. package/workflow_nodes/mandrill.json +372 -0
  396. package/workflow_nodes/manualTrigger.json +8 -0
  397. package/workflow_nodes/markdown.json +376 -0
  398. package/workflow_nodes/marketstack.json +126 -0
  399. package/workflow_nodes/matrix.json +264 -0
  400. package/workflow_nodes/mattermost.json +8 -0
  401. package/workflow_nodes/mautic.json +564 -0
  402. package/workflow_nodes/mauticTrigger.json +54 -0
  403. package/workflow_nodes/medium.json +209 -0
  404. package/workflow_nodes/merge.json +125 -0
  405. package/workflow_nodes/messageBird.json +182 -0
  406. package/workflow_nodes/metabase.json +175 -0
  407. package/workflow_nodes/microsoftDynamicsCrm.json +100 -0
  408. package/workflow_nodes/microsoftEntra.json +51 -0
  409. package/workflow_nodes/microsoftExcel.json +35 -0
  410. package/workflow_nodes/microsoftGraphSecurity.json +113 -0
  411. package/workflow_nodes/microsoftOneDrive.json +232 -0
  412. package/workflow_nodes/microsoftOneDriveTrigger.json +80 -0
  413. package/workflow_nodes/microsoftOutlook.json +40 -0
  414. package/workflow_nodes/microsoftOutlookTrigger.json +24 -0
  415. package/workflow_nodes/microsoftSql.json +81 -0
  416. package/workflow_nodes/microsoftTeams.json +36 -0
  417. package/workflow_nodes/microsoftToDo.json +181 -0
  418. package/workflow_nodes/mindee.json +86 -0
  419. package/workflow_nodes/misp.json +399 -0
  420. package/workflow_nodes/mocean.json +103 -0
  421. package/workflow_nodes/mondayCom.json +290 -0
  422. package/workflow_nodes/mongoDb.json +16 -0
  423. package/workflow_nodes/monicaCrm.json +543 -0
  424. package/workflow_nodes/moveBinaryData.json +121 -0
  425. package/workflow_nodes/mqtt.json +67 -0
  426. package/workflow_nodes/mqttTrigger.json +47 -0
  427. package/workflow_nodes/msg91.json +65 -0
  428. package/workflow_nodes/mySql.json +111 -0
  429. package/workflow_nodes/n8n.json +75 -0
  430. package/workflow_nodes/n8nTrigger.json +27 -0
  431. package/workflow_nodes/nasa.json +310 -0
  432. package/workflow_nodes/netlify.json +87 -0
  433. package/workflow_nodes/netlifyTrigger.json +68 -0
  434. package/workflow_nodes/netscalerAdc.json +243 -0
  435. package/workflow_nodes/nextCloud.json +312 -0
  436. package/workflow_nodes/noOp.json +8 -0
  437. package/workflow_nodes/nocoDb.json +276 -0
  438. package/workflow_nodes/notion.json +8 -0
  439. package/workflow_nodes/notionTrigger.json +75 -0
  440. package/workflow_nodes/npm.json +64 -0
  441. package/workflow_nodes/odoo.json +344 -0
  442. package/workflow_nodes/okta.json +97 -0
  443. package/workflow_nodes/oneSimpleApi.json +281 -0
  444. package/workflow_nodes/onfleet.json +316 -0
  445. package/workflow_nodes/onfleetTrigger.json +8 -0
  446. package/workflow_nodes/openAi.json +154 -0
  447. package/workflow_nodes/openThesaurus.json +81 -0
  448. package/workflow_nodes/openWeatherMap.json +129 -0
  449. package/workflow_nodes/orbit.json +375 -0
  450. package/workflow_nodes/oura.json +74 -0
  451. package/workflow_nodes/paddle.json +403 -0
  452. package/workflow_nodes/pagerDuty.json +351 -0
  453. package/workflow_nodes/payPal.json +196 -0
  454. package/workflow_nodes/payPalTrigger.json +40 -0
  455. package/workflow_nodes/peekalink.json +41 -0
  456. package/workflow_nodes/phantombuster.json +172 -0
  457. package/workflow_nodes/philipsHue.json +177 -0
  458. package/workflow_nodes/pipedrive.json +860 -0
  459. package/workflow_nodes/pipedriveTrigger.json +11 -0
  460. package/workflow_nodes/plivo.json +91 -0
  461. package/workflow_nodes/postHog.json +122 -0
  462. package/workflow_nodes/postbin.json +60 -0
  463. package/workflow_nodes/postgres.json +109 -0
  464. package/workflow_nodes/postgresTrigger.json +8 -0
  465. package/workflow_nodes/postmarkTrigger.json +72 -0
  466. package/workflow_nodes/profitWell.json +305 -0
  467. package/workflow_nodes/pushbullet.json +186 -0
  468. package/workflow_nodes/pushcut.json +75 -0
  469. package/workflow_nodes/pushcutTrigger.json +8 -0
  470. package/workflow_nodes/pushover.json +159 -0
  471. package/workflow_nodes/questDb.json +94 -0
  472. package/workflow_nodes/quickChart.json +188 -0
  473. package/workflow_nodes/quickbase.json +205 -0
  474. package/workflow_nodes/quickbooks.json +550 -0
  475. package/workflow_nodes/rabbitmq.json +165 -0
  476. package/workflow_nodes/rabbitmqTrigger.json +8 -0
  477. package/workflow_nodes/raindrop.json +216 -0
  478. package/workflow_nodes/readBinaryFile.json +26 -0
  479. package/workflow_nodes/readBinaryFiles.json +26 -0
  480. package/workflow_nodes/readPDF.json +31 -0
  481. package/workflow_nodes/readWriteFile.json +27 -0
  482. package/workflow_nodes/reddit.json +309 -0
  483. package/workflow_nodes/redis.json +183 -0
  484. package/workflow_nodes/redisTrigger.json +8 -0
  485. package/workflow_nodes/removeDuplicates.json +8 -0
  486. package/workflow_nodes/renameKeys.json +67 -0
  487. package/workflow_nodes/respondToWebhook.json +126 -0
  488. package/workflow_nodes/rocketchat.json +216 -0
  489. package/workflow_nodes/rssFeedRead.json +28 -0
  490. package/workflow_nodes/rssFeedReadTrigger.json +17 -0
  491. package/workflow_nodes/rundeck.json +79 -0
  492. package/workflow_nodes/s3.json +425 -0
  493. package/workflow_nodes/salesforce.json +1137 -0
  494. package/workflow_nodes/salesforceTrigger.json +122 -0
  495. package/workflow_nodes/salesmate.json +467 -0
  496. package/workflow_nodes/scheduleTrigger.json +270 -0
  497. package/workflow_nodes/seaTable.json +8 -0
  498. package/workflow_nodes/seaTableTrigger.json +87 -0
  499. package/workflow_nodes/securityScorecard.json +459 -0
  500. package/workflow_nodes/segment.json +219 -0
  501. package/workflow_nodes/sendGrid.json +359 -0
  502. package/workflow_nodes/sendy.json +225 -0
  503. package/workflow_nodes/sentryIo.json +426 -0
  504. package/workflow_nodes/serviceNow.json +544 -0
  505. package/workflow_nodes/set.json +124 -0
  506. package/workflow_nodes/shopify.json +707 -0
  507. package/workflow_nodes/shopifyTrigger.json +8 -0
  508. package/workflow_nodes/signl4.json +133 -0
  509. package/workflow_nodes/simulate.json +30 -0
  510. package/workflow_nodes/simulateTrigger.json +8 -0
  511. package/workflow_nodes/slack.json +62 -0
  512. package/workflow_nodes/slackTrigger.json +135 -0
  513. package/workflow_nodes/sms77.json +121 -0
  514. package/workflow_nodes/snowflake.json +65 -0
  515. package/workflow_nodes/sort.json +57 -0
  516. package/workflow_nodes/splitInBatches.json +30 -0
  517. package/workflow_nodes/splitOut.json +62 -0
  518. package/workflow_nodes/splunk.json +40 -0
  519. package/workflow_nodes/spontit.json +123 -0
  520. package/workflow_nodes/spotify.json +285 -0
  521. package/workflow_nodes/spreadsheetFile.json +8 -0
  522. package/workflow_nodes/sseTrigger.json +8 -0
  523. package/workflow_nodes/ssh.json +105 -0
  524. package/workflow_nodes/stackby.json +85 -0
  525. package/workflow_nodes/start.json +15 -0
  526. package/workflow_nodes/stickyNote.json +36 -0
  527. package/workflow_nodes/stopAndError.json +8 -0
  528. package/workflow_nodes/storyblok.json +138 -0
  529. package/workflow_nodes/strapi.json +138 -0
  530. package/workflow_nodes/strava.json +427 -0
  531. package/workflow_nodes/stravaTrigger.json +79 -0
  532. package/workflow_nodes/stripe.json +357 -0
  533. package/workflow_nodes/stripeTrigger.json +775 -0
  534. package/workflow_nodes/summarize.json +124 -0
  535. package/workflow_nodes/supabase.json +136 -0
  536. package/workflow_nodes/surveyMonkeyTrigger.json +160 -0
  537. package/workflow_nodes/switch.json +91 -0
  538. package/workflow_nodes/syncroMsp.json +8 -0
  539. package/workflow_nodes/taiga.json +340 -0
  540. package/workflow_nodes/taigaTrigger.json +81 -0
  541. package/workflow_nodes/tapfiliate.json +241 -0
  542. package/workflow_nodes/telegram.json +612 -0
  543. package/workflow_nodes/telegramTrigger.json +142 -0
  544. package/workflow_nodes/theHive.json +497 -0
  545. package/workflow_nodes/theHiveProject.json +8 -0
  546. package/workflow_nodes/theHiveProjectTrigger.json +162 -0
  547. package/workflow_nodes/theHiveTrigger.json +101 -0
  548. package/workflow_nodes/timescaleDb.json +95 -0
  549. package/workflow_nodes/todoist.json +285 -0
  550. package/workflow_nodes/togglTrigger.json +24 -0
  551. package/workflow_nodes/totp.json +86 -0
  552. package/workflow_nodes/travisCi.json +142 -0
  553. package/workflow_nodes/trello.json +609 -0
  554. package/workflow_nodes/trelloTrigger.json +8 -0
  555. package/workflow_nodes/twake.json +76 -0
  556. package/workflow_nodes/twilio.json +95 -0
  557. package/workflow_nodes/twilioTrigger.json +46 -0
  558. package/workflow_nodes/twist.json +376 -0
  559. package/workflow_nodes/twitter.json +40 -0
  560. package/workflow_nodes/typeformTrigger.json +62 -0
  561. package/workflow_nodes/unleashedSoftware.json +154 -0
  562. package/workflow_nodes/uplead.json +72 -0
  563. package/workflow_nodes/uproc.json +26 -0
  564. package/workflow_nodes/uptimeRobot.json +453 -0
  565. package/workflow_nodes/urlScanIo.json +113 -0
  566. package/workflow_nodes/venafiTlsProtectCloud.json +310 -0
  567. package/workflow_nodes/venafiTlsProtectCloudTrigger.json +38 -0
  568. package/workflow_nodes/venafiTlsProtectDatacenter.json +491 -0
  569. package/workflow_nodes/vero.json +158 -0
  570. package/workflow_nodes/vonage.json +125 -0
  571. package/workflow_nodes/wait.json +71 -0
  572. package/workflow_nodes/webflow.json +38 -0
  573. package/workflow_nodes/webflowTrigger.json +8 -0
  574. package/workflow_nodes/webhook.json +55 -0
  575. package/workflow_nodes/wekan.json +460 -0
  576. package/workflow_nodes/whatsApp.json +476 -0
  577. package/workflow_nodes/whatsAppTrigger.json +103 -0
  578. package/workflow_nodes/wise.json +330 -0
  579. package/workflow_nodes/wiseTrigger.json +8 -0
  580. package/workflow_nodes/wooCommerce.json +812 -0
  581. package/workflow_nodes/wooCommerceTrigger.json +8 -0
  582. package/workflow_nodes/wordpress.json +500 -0
  583. package/workflow_nodes/workableTrigger.json +51 -0
  584. package/workflow_nodes/writeBinaryFile.json +34 -0
  585. package/workflow_nodes/wufooTrigger.json +37 -0
  586. package/workflow_nodes/xero.json +530 -0
  587. package/workflow_nodes/xml.json +129 -0
  588. package/workflow_nodes/youTube.json +578 -0
  589. package/workflow_nodes/yourls.json +71 -0
  590. package/workflow_nodes/zammad.json +406 -0
  591. package/workflow_nodes/zendesk.json +526 -0
  592. package/workflow_nodes/zendeskTrigger.json +187 -0
  593. package/workflow_nodes/zohoCrm.json +721 -0
  594. package/workflow_nodes/zoom.json +507 -0
  595. package/workflow_nodes/zulip.json +371 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Rate Limiter Middleware
3
+ *
4
+ * Protects the API from excessive requests
5
+ */
6
+
7
+ const { logger } = require('../utils/logger');
8
+ const { createErrorResponse } = require('../utils/mcp');
9
+ const { logSecurityEvent } = require('../utils/securityLogger');
10
+
11
+ // In-memory store for rate limiting (in production, use Redis or similar)
12
+ const requestCounts = {};
13
+
14
+ // Constants
15
+ const WINDOW_MS = 60 * 1000; // 1 minute
16
+ const MAX_REQUESTS_PER_WINDOW = 100; // 100 requests per minute
17
+
18
+ /**
19
+ * Simple rate limiter middleware
20
+ *
21
+ * @param {Object} req - Express request object
22
+ * @param {Object} res - Express response object
23
+ * @param {Function} next - Express next middleware function
24
+ */
25
+ const rateLimiter = (req, res, next) => {
26
+ const ip = req.ip || req.connection.remoteAddress;
27
+ const now = Date.now();
28
+
29
+ // Initialize or reset window
30
+ if (!requestCounts[ip] || requestCounts[ip].windowStart < now - WINDOW_MS) {
31
+ requestCounts[ip] = {
32
+ windowStart: now,
33
+ count: 1
34
+ };
35
+ return next();
36
+ }
37
+
38
+ // Increment count for existing window
39
+ requestCounts[ip].count++;
40
+
41
+ // Check if too many requests
42
+ if (requestCounts[ip].count > MAX_REQUESTS_PER_WINDOW) {
43
+ // Log rate limit
44
+ logger.warn(`Rate limit exceeded for IP: ${ip}`);
45
+
46
+ // Security log
47
+ logSecurityEvent({
48
+ level: 'warn',
49
+ eventType: 'rate_limit_exceeded',
50
+ ip,
51
+ details: {
52
+ count: requestCounts[ip].count,
53
+ window: WINDOW_MS,
54
+ limit: MAX_REQUESTS_PER_WINDOW
55
+ }
56
+ });
57
+
58
+ // Create error response
59
+ const errorResponse = createErrorResponse(
60
+ 'Too many requests, please try again later',
61
+ 'RATE_LIMIT_EXCEEDED',
62
+ 429,
63
+ {
64
+ retryAfter: Math.ceil((requestCounts[ip].windowStart + WINDOW_MS - now) / 1000)
65
+ }
66
+ );
67
+
68
+ // Set retry header
69
+ res.setHeader(
70
+ 'Retry-After',
71
+ Math.ceil((requestCounts[ip].windowStart + WINDOW_MS - now) / 1000)
72
+ );
73
+
74
+ return res.status(429).json({ error: errorResponse.error });
75
+ }
76
+
77
+ next();
78
+ };
79
+
80
+ module.exports = {
81
+ rateLimiter
82
+ };
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Input Validation Middleware
3
+ *
4
+ * Provides JSON Schema validation for API endpoints and request sanitization.
5
+ */
6
+
7
+ const Ajv = require('ajv');
8
+ const addFormats = require('ajv-formats');
9
+ const { createErrorResponse } = require('../utils/mcp');
10
+ const { logger } = require('../utils/logger');
11
+ const { logValidationFailure } = require('../utils/securityLogger');
12
+
13
+ // Initialize AJV with additional options
14
+ const ajv = new Ajv({
15
+ allErrors: true,
16
+ removeAdditional: 'all', // Remove additional properties not in schema
17
+ useDefaults: true, // Apply default values from schema
18
+ coerceTypes: true // Convert data types when possible
19
+ });
20
+
21
+ // Add format validators (email, date, uri, etc.)
22
+ addFormats(ajv);
23
+
24
+ /**
25
+ * Creates a validation middleware for a specific schema
26
+ *
27
+ * @param {Object} schema - JSON Schema object to validate against
28
+ * @param {string} property - Request property to validate (body, query, params)
29
+ * @returns {Function} Express middleware function
30
+ */
31
+ const validateSchema = (schema, property = 'body') => {
32
+ const validate = ajv.compile(schema);
33
+
34
+ return (req, res, next) => {
35
+ const data = req[property];
36
+ const valid = validate(data);
37
+
38
+ if (!valid) {
39
+ // Format validation errors for response
40
+ const formattedErrors = formatValidationErrors(validate.errors);
41
+
42
+ // Regular logging
43
+ logger.warn(`Validation error for ${req.method} ${req.path}: ${JSON.stringify(formattedErrors)}`);
44
+
45
+ // Security logging
46
+ const clientIp = req.ip || req.connection.remoteAddress;
47
+ const userId = req.auth ? (req.auth.user ? req.auth.user.id : null) : null;
48
+
49
+ // Log each validation error separately
50
+ Object.keys(formattedErrors).forEach(field => {
51
+ logValidationFailure({
52
+ ip: clientIp,
53
+ userId,
54
+ endpoint: req.path,
55
+ method: req.method,
56
+ violationType: 'schema_validation',
57
+ inputField: field
58
+ });
59
+ });
60
+
61
+ const errorResponse = createErrorResponse(
62
+ 'Validation failed',
63
+ 'VALIDATION_ERROR',
64
+ 400,
65
+ formattedErrors
66
+ );
67
+
68
+ return res.status(errorResponse.status).json({ error: errorResponse.error });
69
+ }
70
+
71
+ next();
72
+ };
73
+ };
74
+
75
+ /**
76
+ * Format validation errors into a more user-friendly structure
77
+ *
78
+ * @param {Array} errors - AJV validation errors
79
+ * @returns {Object} Formatted errors by field
80
+ */
81
+ const formatValidationErrors = (errors) => {
82
+ const formattedErrors = {};
83
+
84
+ for (const error of errors) {
85
+ // Extract the field name from the error path
86
+ const path = error.instancePath.substring(1).split('/');
87
+ const field = path.length ? path[path.length - 1] : error.params.missingProperty || 'value';
88
+
89
+ // Initialize the field in the errors object if it doesn't exist
90
+ if (!formattedErrors[field]) {
91
+ formattedErrors[field] = [];
92
+ }
93
+
94
+ // Add the error message for this field
95
+ let message = error.message;
96
+
97
+ // Customize messages for specific error types
98
+ if (error.keyword === 'required') {
99
+ message = `Missing required field: ${error.params.missingProperty}`;
100
+ } else if (error.keyword === 'additionalProperties') {
101
+ message = `Unexpected field: ${error.params.additionalProperty}`;
102
+ }
103
+
104
+ formattedErrors[field].push(message);
105
+ }
106
+
107
+ return formattedErrors;
108
+ };
109
+
110
+ /**
111
+ * Sanitize input data to prevent injection attacks
112
+ *
113
+ * @param {*} data - Data to sanitize
114
+ * @returns {*} Sanitized data
115
+ */
116
+ const sanitizeInput = (data) => {
117
+ if (typeof data === 'string') {
118
+ // Basic sanitization for strings
119
+ return data
120
+ .replace(/</g, '&lt;')
121
+ .replace(/>/g, '&gt;')
122
+ .replace(/"/g, '&quot;')
123
+ .replace(/'/g, '&#x27;')
124
+ .replace(/\//g, '&#x2F;')
125
+ .replace(/`/g, '&#96;');
126
+ }
127
+
128
+ if (data && typeof data === 'object') {
129
+ if (Array.isArray(data)) {
130
+ // Recursively sanitize array items
131
+ return data.map(item => sanitizeInput(item));
132
+ } else {
133
+ // Recursively sanitize object properties
134
+ const sanitized = {};
135
+ for (const [key, value] of Object.entries(data)) {
136
+ sanitized[key] = sanitizeInput(value);
137
+ }
138
+ return sanitized;
139
+ }
140
+ }
141
+
142
+ // Return non-string, non-object values as is
143
+ return data;
144
+ };
145
+
146
+ /**
147
+ * Creates a sanitization middleware
148
+ *
149
+ * @param {string} property - Request property to sanitize (body, query, params)
150
+ * @returns {Function} Express middleware function
151
+ */
152
+ const sanitizeRequest = (property = 'body') => {
153
+ return (req, res, next) => {
154
+ if (req[property]) {
155
+ req[property] = sanitizeInput(req[property]);
156
+ }
157
+ next();
158
+ };
159
+ };
160
+
161
+ /**
162
+ * Validate workflow-specific inputs
163
+ */
164
+ const validateWorkflow = (req, res, next) => {
165
+ const { name, description } = req.body;
166
+ const clientIp = req.ip || req.connection.remoteAddress;
167
+ const userId = req.auth?.userId || 'anonymous';
168
+
169
+ // Name must be provided
170
+ if (!name) {
171
+ // Log validation failure
172
+ logValidationFailure({
173
+ ip: clientIp,
174
+ userId,
175
+ endpoint: req.path,
176
+ method: req.method,
177
+ violationType: 'required_field_missing',
178
+ inputField: 'name'
179
+ });
180
+
181
+ const errorResponse = createErrorResponse(
182
+ 'Workflow name is required',
183
+ 'MISSING_REQUIRED_FIELD',
184
+ 400
185
+ );
186
+
187
+ return res.status(400).json({ error: errorResponse.error });
188
+ }
189
+
190
+ // Name length validation
191
+ if (name.length > 100) {
192
+ // Log validation failure
193
+ logValidationFailure({
194
+ ip: clientIp,
195
+ userId,
196
+ endpoint: req.path,
197
+ method: req.method,
198
+ violationType: 'field_too_long',
199
+ inputField: 'name'
200
+ });
201
+
202
+ const errorResponse = createErrorResponse(
203
+ 'Workflow name cannot exceed 100 characters',
204
+ 'FIELD_TOO_LONG',
205
+ 400
206
+ );
207
+
208
+ return res.status(400).json({ error: errorResponse.error });
209
+ }
210
+
211
+ // Description length validation
212
+ if (description && description.length > 500) {
213
+ // Log validation failure
214
+ logValidationFailure({
215
+ ip: clientIp,
216
+ userId,
217
+ endpoint: req.path,
218
+ method: req.method,
219
+ violationType: 'field_too_long',
220
+ inputField: 'description'
221
+ });
222
+
223
+ const errorResponse = createErrorResponse(
224
+ 'Workflow description cannot exceed 500 characters',
225
+ 'FIELD_TOO_LONG',
226
+ 400
227
+ );
228
+
229
+ return res.status(400).json({ error: errorResponse.error });
230
+ }
231
+
232
+ next();
233
+ };
234
+
235
+ module.exports = {
236
+ validateSchema,
237
+ sanitizeRequest,
238
+ sanitizeInput,
239
+ formatValidationErrors,
240
+ validateWorkflow
241
+ };
@@ -0,0 +1,359 @@
1
+ /**
2
+ * Credential Model
3
+ *
4
+ * Handles secure credential storage and retrieval with encryption.
5
+ */
6
+
7
+ const fs = require('fs').promises;
8
+ const path = require('path');
9
+ const { encrypt, decrypt, generateKey } = require('../utils/encryption');
10
+ const { logger } = require('../utils/logger');
11
+
12
+ // Configuration
13
+ let config;
14
+ try {
15
+ config = require('../../config/default');
16
+ } catch (err) {
17
+ logger.error('Failed to load config', { error: err.message });
18
+ config = {
19
+ auth: { encryptionKey: process.env.ENCRYPTION_KEY }
20
+ };
21
+ }
22
+
23
+ // Storage location for credentials
24
+ const CREDENTIALS_DIR = path.join(process.cwd(), 'config', 'credentials');
25
+ const CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, 'credentials.json');
26
+
27
+ // Get master encryption key from environment or generate one
28
+ const MASTER_KEY = process.env.ENCRYPTION_KEY ||
29
+ config.auth?.encryptionKey ||
30
+ (() => {
31
+ logger.warn('No encryption key found, generating one. THIS SHOULD NOT BE USED IN PRODUCTION.');
32
+ const key = generateKey();
33
+ logger.warn(`Generated encryption key: ${key}. Add this to your environment variables as ENCRYPTION_KEY.`);
34
+ return key;
35
+ })();
36
+
37
+ // Ensure credentials directory exists
38
+ const ensureCredentialsDir = async () => {
39
+ try {
40
+ await fs.mkdir(CREDENTIALS_DIR, { recursive: true });
41
+ } catch (error) {
42
+ logger.error('Failed to create credentials directory', { error: error.message });
43
+ throw new Error('Failed to create credentials directory');
44
+ }
45
+ };
46
+
47
+ // Initialize credentials storage
48
+ const initCredentialsStorage = async () => {
49
+ await ensureCredentialsDir();
50
+
51
+ try {
52
+ // Check if credentials file exists
53
+ await fs.access(CREDENTIALS_FILE);
54
+ } catch (error) {
55
+ // Create an empty credentials file
56
+ await fs.writeFile(CREDENTIALS_FILE, JSON.stringify({ credentials: {}, meta: { version: '1.0', keyId: 'v1' } }));
57
+ logger.info('Created new credentials file');
58
+ }
59
+ };
60
+
61
+ /**
62
+ * Loads credentials from storage
63
+ *
64
+ * @returns {Object} Credentials data
65
+ */
66
+ const loadCredentials = async () => {
67
+ try {
68
+ await ensureCredentialsDir();
69
+ const data = await fs.readFile(CREDENTIALS_FILE, 'utf8');
70
+ return JSON.parse(data);
71
+ } catch (error) {
72
+ logger.error('Failed to load credentials', { error: error.message });
73
+
74
+ // If file doesn't exist or is corrupted, create a new one
75
+ if (error.code === 'ENOENT' || error instanceof SyntaxError) {
76
+ const emptyData = { credentials: {}, meta: { version: '1.0', keyId: 'v1' } };
77
+ await fs.writeFile(CREDENTIALS_FILE, JSON.stringify(emptyData));
78
+ return emptyData;
79
+ }
80
+
81
+ throw new Error('Failed to load credentials');
82
+ }
83
+ };
84
+
85
+ /**
86
+ * Saves credentials to storage
87
+ *
88
+ * @param {Object} data - Credentials data
89
+ */
90
+ const saveCredentials = async (data) => {
91
+ try {
92
+ await ensureCredentialsDir();
93
+ await fs.writeFile(CREDENTIALS_FILE, JSON.stringify(data, null, 2));
94
+ } catch (error) {
95
+ logger.error('Failed to save credentials', { error: error.message });
96
+ throw new Error('Failed to save credentials');
97
+ }
98
+ };
99
+
100
+ /**
101
+ * Stores a credential securely
102
+ *
103
+ * @param {string} name - Identifier for the credential
104
+ * @param {Object} data - Credential data to store
105
+ * @param {Object} options - Additional options
106
+ * @param {string} options.type - Type of credential (e.g., 'api', 'oauth')
107
+ * @param {string} options.keyId - Key identifier for encryption (for key rotation)
108
+ * @returns {Object} Status of the operation
109
+ */
110
+ const storeCredential = async (name, data, options = {}) => {
111
+ if (!name || typeof name !== 'string') {
112
+ throw new Error('Credential name is required');
113
+ }
114
+
115
+ if (!data) {
116
+ throw new Error('Credential data is required');
117
+ }
118
+
119
+ try {
120
+ const credentialsData = await loadCredentials();
121
+ const keyId = options.keyId || credentialsData.meta.keyId || 'v1';
122
+
123
+ // Encrypt the credential data
124
+ const encryptedData = encrypt(data, MASTER_KEY, keyId);
125
+
126
+ // Store with metadata
127
+ credentialsData.credentials[name] = {
128
+ encrypted: encryptedData,
129
+ type: options.type || 'generic',
130
+ createdAt: new Date().toISOString(),
131
+ updatedAt: new Date().toISOString()
132
+ };
133
+
134
+ await saveCredentials(credentialsData);
135
+
136
+ return {
137
+ success: true,
138
+ name,
139
+ message: `Credential "${name}" stored successfully`
140
+ };
141
+ } catch (error) {
142
+ logger.error('Failed to store credential', { name, error: error.message });
143
+ throw new Error(`Failed to store credential "${name}": ${error.message}`);
144
+ }
145
+ };
146
+
147
+ /**
148
+ * Retrieves a stored credential
149
+ *
150
+ * @param {string} name - Name of the credential to retrieve
151
+ * @returns {Object} Decrypted credential data
152
+ */
153
+ const getCredential = async (name) => {
154
+ if (!name || typeof name !== 'string') {
155
+ throw new Error('Credential name is required');
156
+ }
157
+
158
+ try {
159
+ const credentialsData = await loadCredentials();
160
+
161
+ if (!credentialsData.credentials[name]) {
162
+ throw new Error(`Credential "${name}" not found`);
163
+ }
164
+
165
+ const encryptedData = credentialsData.credentials[name].encrypted;
166
+
167
+ // Decrypt the credential data
168
+ const decryptedData = decrypt(encryptedData, MASTER_KEY);
169
+
170
+ return {
171
+ data: decryptedData,
172
+ type: credentialsData.credentials[name].type,
173
+ createdAt: credentialsData.credentials[name].createdAt,
174
+ updatedAt: credentialsData.credentials[name].updatedAt
175
+ };
176
+ } catch (error) {
177
+ logger.error('Failed to retrieve credential', { name, error: error.message });
178
+ throw new Error(`Failed to retrieve credential "${name}": ${error.message}`);
179
+ }
180
+ };
181
+
182
+ /**
183
+ * Updates a stored credential
184
+ *
185
+ * @param {string} name - Name of the credential to update
186
+ * @param {Object} data - New credential data
187
+ * @param {Object} options - Additional options
188
+ * @returns {Object} Status of the operation
189
+ */
190
+ const updateCredential = async (name, data, options = {}) => {
191
+ if (!name || typeof name !== 'string') {
192
+ throw new Error('Credential name is required');
193
+ }
194
+
195
+ if (!data) {
196
+ throw new Error('Credential data is required');
197
+ }
198
+
199
+ try {
200
+ const credentialsData = await loadCredentials();
201
+
202
+ if (!credentialsData.credentials[name]) {
203
+ throw new Error(`Credential "${name}" not found`);
204
+ }
205
+
206
+ const keyId = options.keyId || credentialsData.meta.keyId || 'v1';
207
+
208
+ // Encrypt the credential data
209
+ const encryptedData = encrypt(data, MASTER_KEY, keyId);
210
+
211
+ // Update the credential
212
+ credentialsData.credentials[name] = {
213
+ ...credentialsData.credentials[name],
214
+ encrypted: encryptedData,
215
+ updatedAt: new Date().toISOString()
216
+ };
217
+
218
+ // Update type if provided
219
+ if (options.type) {
220
+ credentialsData.credentials[name].type = options.type;
221
+ }
222
+
223
+ await saveCredentials(credentialsData);
224
+
225
+ return {
226
+ success: true,
227
+ name,
228
+ message: `Credential "${name}" updated successfully`
229
+ };
230
+ } catch (error) {
231
+ logger.error('Failed to update credential', { name, error: error.message });
232
+ throw new Error(`Failed to update credential "${name}": ${error.message}`);
233
+ }
234
+ };
235
+
236
+ /**
237
+ * Deletes a stored credential
238
+ *
239
+ * @param {string} name - Name of the credential to delete
240
+ * @returns {Object} Status of the operation
241
+ */
242
+ const deleteCredential = async (name) => {
243
+ if (!name || typeof name !== 'string') {
244
+ throw new Error('Credential name is required');
245
+ }
246
+
247
+ try {
248
+ const credentialsData = await loadCredentials();
249
+
250
+ if (!credentialsData.credentials[name]) {
251
+ throw new Error(`Credential "${name}" not found`);
252
+ }
253
+
254
+ // Delete the credential
255
+ delete credentialsData.credentials[name];
256
+
257
+ await saveCredentials(credentialsData);
258
+
259
+ return {
260
+ success: true,
261
+ name,
262
+ message: `Credential "${name}" deleted successfully`
263
+ };
264
+ } catch (error) {
265
+ logger.error('Failed to delete credential', { name, error: error.message });
266
+ throw new Error(`Failed to delete credential "${name}": ${error.message}`);
267
+ }
268
+ };
269
+
270
+ /**
271
+ * Lists all available credentials (without sensitive data)
272
+ *
273
+ * @returns {Object[]} List of credentials with metadata
274
+ */
275
+ const listCredentials = async () => {
276
+ try {
277
+ const credentialsData = await loadCredentials();
278
+
279
+ return Object.entries(credentialsData.credentials).map(([name, cred]) => ({
280
+ name,
281
+ type: cred.type,
282
+ createdAt: cred.createdAt,
283
+ updatedAt: cred.updatedAt
284
+ }));
285
+ } catch (error) {
286
+ logger.error('Failed to list credentials', { error: error.message });
287
+ throw new Error('Failed to list credentials');
288
+ }
289
+ };
290
+
291
+ /**
292
+ * Rotates the encryption key for all credentials
293
+ *
294
+ * @param {string} newKeyId - New key identifier
295
+ * @returns {Object} Status of the operation
296
+ */
297
+ const rotateEncryptionKey = async (newKeyId = `v${Date.now()}`) => {
298
+ try {
299
+ const credentialsData = await loadCredentials();
300
+ const currentKeyId = credentialsData.meta.keyId || 'v1';
301
+
302
+ // Skip if key ID is the same
303
+ if (newKeyId === currentKeyId) {
304
+ return {
305
+ success: true,
306
+ message: 'Key already up to date, no rotation needed',
307
+ keyId: currentKeyId
308
+ };
309
+ }
310
+
311
+ // Re-encrypt all credentials with the new key ID
312
+ for (const [name, cred] of Object.entries(credentialsData.credentials)) {
313
+ try {
314
+ // Decrypt with current key
315
+ const decryptedData = decrypt(cred.encrypted, MASTER_KEY);
316
+
317
+ // Re-encrypt with new key ID
318
+ cred.encrypted = encrypt(decryptedData, MASTER_KEY, newKeyId);
319
+ cred.updatedAt = new Date().toISOString();
320
+ } catch (error) {
321
+ logger.error(`Failed to rotate key for credential "${name}"`, { error: error.message });
322
+ // Continue with other credentials
323
+ }
324
+ }
325
+
326
+ // Update metadata
327
+ credentialsData.meta.keyId = newKeyId;
328
+ credentialsData.meta.keyRotatedAt = new Date().toISOString();
329
+
330
+ await saveCredentials(credentialsData);
331
+
332
+ return {
333
+ success: true,
334
+ message: `Encryption key rotated successfully to "${newKeyId}"`,
335
+ keyId: newKeyId
336
+ };
337
+ } catch (error) {
338
+ logger.error('Failed to rotate encryption key', { error: error.message });
339
+ throw new Error('Failed to rotate encryption key');
340
+ }
341
+ };
342
+
343
+ // Initialize credentials storage on module load
344
+ (async () => {
345
+ try {
346
+ await initCredentialsStorage();
347
+ } catch (error) {
348
+ logger.error('Failed to initialize credentials storage', { error: error.message });
349
+ }
350
+ })();
351
+
352
+ module.exports = {
353
+ storeCredential,
354
+ getCredential,
355
+ updateCredential,
356
+ deleteCredential,
357
+ listCredentials,
358
+ rotateEncryptionKey
359
+ };