@plumbus/core 0.3.2 → 0.4.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 (572) hide show
  1. package/README.md +2 -2
  2. package/bin/plumbus.js +16 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/ai/ai-service.d.ts.map +1 -1
  5. package/dist/ai/ai-service.js +8 -3
  6. package/dist/ai/ai-service.js.map +1 -1
  7. package/dist/ai/provider.d.ts.map +1 -1
  8. package/dist/ai/provider.js +1 -2
  9. package/dist/ai/provider.js.map +1 -1
  10. package/dist/ai/rag/pipeline.d.ts +4 -0
  11. package/dist/ai/rag/pipeline.d.ts.map +1 -1
  12. package/dist/ai/rag/pipeline.js +17 -2
  13. package/dist/ai/rag/pipeline.js.map +1 -1
  14. package/dist/api/route-generator.d.ts.map +1 -1
  15. package/dist/api/route-generator.js +10 -6
  16. package/dist/api/route-generator.js.map +1 -1
  17. package/dist/auth/adapter.d.ts +0 -4
  18. package/dist/auth/adapter.d.ts.map +1 -1
  19. package/dist/auth/adapter.js +4 -0
  20. package/dist/auth/adapter.js.map +1 -1
  21. package/dist/cli/cli.d.ts.map +1 -1
  22. package/dist/cli/cli.js +2 -1
  23. package/dist/cli/cli.js.map +1 -1
  24. package/dist/cli/commands/dev.d.ts +4 -1
  25. package/dist/cli/commands/dev.d.ts.map +1 -1
  26. package/dist/cli/commands/dev.js +21 -30
  27. package/dist/cli/commands/dev.js.map +1 -1
  28. package/dist/cli/commands/doctor.d.ts +6 -0
  29. package/dist/cli/commands/doctor.d.ts.map +1 -1
  30. package/dist/cli/commands/doctor.js +146 -2
  31. package/dist/cli/commands/doctor.js.map +1 -1
  32. package/dist/cli/commands/generate.d.ts.map +1 -1
  33. package/dist/cli/commands/generate.js +18 -0
  34. package/dist/cli/commands/generate.js.map +1 -1
  35. package/dist/cli/commands/index.d.ts +1 -0
  36. package/dist/cli/commands/index.d.ts.map +1 -1
  37. package/dist/cli/commands/index.js +1 -0
  38. package/dist/cli/commands/index.js.map +1 -1
  39. package/dist/cli/commands/init.d.ts +1 -1
  40. package/dist/cli/commands/init.d.ts.map +1 -1
  41. package/dist/cli/commands/init.js +113 -3
  42. package/dist/cli/commands/init.js.map +1 -1
  43. package/dist/cli/commands/mcp.d.ts +9 -0
  44. package/dist/cli/commands/mcp.d.ts.map +1 -0
  45. package/dist/cli/commands/mcp.js +125 -0
  46. package/dist/cli/commands/mcp.js.map +1 -0
  47. package/dist/cli/commands/migrate.d.ts.map +1 -1
  48. package/dist/cli/commands/migrate.js +2 -1
  49. package/dist/cli/commands/migrate.js.map +1 -1
  50. package/dist/cli/commands/start.d.ts +4 -1
  51. package/dist/cli/commands/start.d.ts.map +1 -1
  52. package/dist/cli/commands/start.js +20 -29
  53. package/dist/cli/commands/start.js.map +1 -1
  54. package/dist/cli/commands/translation.d.ts.map +1 -1
  55. package/dist/cli/commands/translation.js +22 -10
  56. package/dist/cli/commands/translation.js.map +1 -1
  57. package/dist/cli/mcp-serve-context.d.ts +13 -0
  58. package/dist/cli/mcp-serve-context.d.ts.map +1 -0
  59. package/dist/cli/mcp-serve-context.js +119 -0
  60. package/dist/cli/mcp-serve-context.js.map +1 -0
  61. package/dist/cli/migrate-snapshot-schema.d.ts +15 -0
  62. package/dist/cli/migrate-snapshot-schema.d.ts.map +1 -0
  63. package/dist/cli/migrate-snapshot-schema.js +23 -0
  64. package/dist/cli/migrate-snapshot-schema.js.map +1 -0
  65. package/dist/cli/project-root.d.ts +9 -0
  66. package/dist/cli/project-root.d.ts.map +1 -0
  67. package/dist/cli/project-root.js +41 -0
  68. package/dist/cli/project-root.js.map +1 -0
  69. package/dist/cli/templates/resources.d.ts.map +1 -1
  70. package/dist/cli/templates/resources.js +7 -1
  71. package/dist/cli/templates/resources.js.map +1 -1
  72. package/dist/config/loader.d.ts +1 -1
  73. package/dist/config/loader.d.ts.map +1 -1
  74. package/dist/config/loader.js +46 -27
  75. package/dist/config/loader.js.map +1 -1
  76. package/dist/data/connection.d.ts +16 -0
  77. package/dist/data/connection.d.ts.map +1 -0
  78. package/dist/data/connection.js +27 -0
  79. package/dist/data/connection.js.map +1 -0
  80. package/dist/data/index.d.ts +1 -0
  81. package/dist/data/index.d.ts.map +1 -1
  82. package/dist/data/index.js +1 -0
  83. package/dist/data/index.js.map +1 -1
  84. package/dist/data/migration.d.ts.map +1 -1
  85. package/dist/data/migration.js +34 -6
  86. package/dist/data/migration.js.map +1 -1
  87. package/dist/data/repository.d.ts.map +1 -1
  88. package/dist/data/repository.js +26 -9
  89. package/dist/data/repository.js.map +1 -1
  90. package/dist/define/defineCapability.d.ts +4 -2
  91. package/dist/define/defineCapability.d.ts.map +1 -1
  92. package/dist/define/defineCapability.js +68 -8
  93. package/dist/define/defineCapability.js.map +1 -1
  94. package/dist/define/defineEntity.d.ts.map +1 -1
  95. package/dist/define/defineEntity.js +8 -4
  96. package/dist/define/defineEntity.js.map +1 -1
  97. package/dist/define/defineEvent.d.ts.map +1 -1
  98. package/dist/define/defineEvent.js +7 -3
  99. package/dist/define/defineEvent.js.map +1 -1
  100. package/dist/define/defineFlow.d.ts.map +1 -1
  101. package/dist/define/defineFlow.js +11 -5
  102. package/dist/define/defineFlow.js.map +1 -1
  103. package/dist/define/definePrompt.d.ts.map +1 -1
  104. package/dist/define/definePrompt.js +11 -5
  105. package/dist/define/definePrompt.js.map +1 -1
  106. package/dist/define/defineTranslation.d.ts.map +1 -1
  107. package/dist/define/defineTranslation.js +12 -10
  108. package/dist/define/defineTranslation.js.map +1 -1
  109. package/dist/define/validation-error.d.ts +2 -0
  110. package/dist/define/validation-error.d.ts.map +1 -0
  111. package/dist/define/validation-error.js +9 -0
  112. package/dist/define/validation-error.js.map +1 -0
  113. package/dist/errors/hints.d.ts +13 -0
  114. package/dist/errors/hints.d.ts.map +1 -0
  115. package/dist/errors/hints.js +15 -0
  116. package/dist/errors/hints.js.map +1 -0
  117. package/dist/errors/hook-log.d.ts +3 -0
  118. package/dist/errors/hook-log.d.ts.map +1 -0
  119. package/dist/errors/hook-log.js +6 -0
  120. package/dist/errors/hook-log.js.map +1 -0
  121. package/dist/errors/http.d.ts +18 -0
  122. package/dist/errors/http.d.ts.map +1 -1
  123. package/dist/errors/http.js +32 -2
  124. package/dist/errors/http.js.map +1 -1
  125. package/dist/errors/safe-metadata.d.ts +5 -0
  126. package/dist/errors/safe-metadata.d.ts.map +1 -0
  127. package/dist/errors/safe-metadata.js +24 -0
  128. package/dist/errors/safe-metadata.js.map +1 -0
  129. package/dist/execution/auth-roles.d.ts +6 -0
  130. package/dist/execution/auth-roles.d.ts.map +1 -0
  131. package/dist/execution/auth-roles.js +12 -0
  132. package/dist/execution/auth-roles.js.map +1 -0
  133. package/dist/execution/authorization.d.ts.map +1 -1
  134. package/dist/execution/authorization.js +3 -5
  135. package/dist/execution/authorization.js.map +1 -1
  136. package/dist/execution/context-factory.d.ts +2 -17
  137. package/dist/execution/context-factory.d.ts.map +1 -1
  138. package/dist/execution/context-factory.js +1 -0
  139. package/dist/execution/context-factory.js.map +1 -1
  140. package/dist/flows/engine.js +1 -1
  141. package/dist/flows/engine.js.map +1 -1
  142. package/dist/flows/evaluate-condition.d.ts +19 -0
  143. package/dist/flows/evaluate-condition.d.ts.map +1 -0
  144. package/dist/flows/evaluate-condition.js +276 -0
  145. package/dist/flows/evaluate-condition.js.map +1 -0
  146. package/dist/flows/index.d.ts +1 -0
  147. package/dist/flows/index.d.ts.map +1 -1
  148. package/dist/flows/index.js +2 -0
  149. package/dist/flows/index.js.map +1 -1
  150. package/dist/flows/step-executor.d.ts.map +1 -1
  151. package/dist/flows/step-executor.js +9 -2
  152. package/dist/flows/step-executor.js.map +1 -1
  153. package/dist/governance/rules/architecture.d.ts.map +1 -1
  154. package/dist/governance/rules/architecture.js +2 -0
  155. package/dist/governance/rules/architecture.js.map +1 -1
  156. package/dist/governance/rules/index.d.ts +1 -0
  157. package/dist/governance/rules/index.d.ts.map +1 -1
  158. package/dist/governance/rules/index.js +1 -0
  159. package/dist/governance/rules/index.js.map +1 -1
  160. package/dist/governance/rules/mcp.d.ts +5 -0
  161. package/dist/governance/rules/mcp.d.ts.map +1 -0
  162. package/dist/governance/rules/mcp.js +34 -0
  163. package/dist/governance/rules/mcp.js.map +1 -0
  164. package/dist/index.d.ts +1 -0
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +1 -0
  167. package/dist/index.js.map +1 -1
  168. package/dist/mcp/exposure.d.ts +4 -0
  169. package/dist/mcp/exposure.d.ts.map +1 -0
  170. package/dist/mcp/exposure.js +5 -0
  171. package/dist/mcp/exposure.js.map +1 -0
  172. package/dist/mcp/index.d.ts +4 -0
  173. package/dist/mcp/index.d.ts.map +1 -0
  174. package/dist/mcp/index.js +6 -0
  175. package/dist/mcp/index.js.map +1 -0
  176. package/dist/mcp/manifest-generator.d.ts +19 -0
  177. package/dist/mcp/manifest-generator.d.ts.map +1 -0
  178. package/dist/mcp/manifest-generator.js +29 -0
  179. package/dist/mcp/manifest-generator.js.map +1 -0
  180. package/dist/mcp/skill-generator.d.ts +4 -0
  181. package/dist/mcp/skill-generator.d.ts.map +1 -0
  182. package/dist/mcp/skill-generator.js +59 -0
  183. package/dist/mcp/skill-generator.js.map +1 -0
  184. package/dist/schema/zod-input-to-json-schema.d.ts +4 -0
  185. package/dist/schema/zod-input-to-json-schema.d.ts.map +1 -0
  186. package/dist/schema/zod-input-to-json-schema.js +6 -0
  187. package/dist/schema/zod-input-to-json-schema.js.map +1 -0
  188. package/dist/server/bootstrap.d.ts.map +1 -1
  189. package/dist/server/bootstrap.js +5 -2
  190. package/dist/server/bootstrap.js.map +1 -1
  191. package/dist/testing/context.d.ts +2 -0
  192. package/dist/testing/context.d.ts.map +1 -1
  193. package/dist/testing/context.js +1 -0
  194. package/dist/testing/context.js.map +1 -1
  195. package/dist/testing/e2e.js +1 -1
  196. package/dist/testing/e2e.js.map +1 -1
  197. package/dist/types/capability.d.ts +13 -0
  198. package/dist/types/capability.d.ts.map +1 -1
  199. package/dist/types/config.d.ts +9 -0
  200. package/dist/types/config.d.ts.map +1 -1
  201. package/dist/types/context.d.ts +31 -0
  202. package/dist/types/context.d.ts.map +1 -1
  203. package/dist/types/deep-freeze.d.ts +6 -0
  204. package/dist/types/deep-freeze.d.ts.map +1 -0
  205. package/dist/types/deep-freeze.js +38 -0
  206. package/dist/types/deep-freeze.js.map +1 -0
  207. package/dist/types/enums.d.ts +5 -0
  208. package/dist/types/enums.d.ts.map +1 -1
  209. package/dist/types/enums.js +5 -0
  210. package/dist/types/enums.js.map +1 -1
  211. package/dist/types/index.d.ts +2 -2
  212. package/dist/types/index.d.ts.map +1 -1
  213. package/dist/types/index.js.map +1 -1
  214. package/dist/types/security.d.ts +3 -1
  215. package/dist/types/security.d.ts.map +1 -1
  216. package/instructions/capabilities.md +36 -0
  217. package/instructions/cli.md +44 -0
  218. package/instructions/framework.md +20 -4
  219. package/instructions/mcp.md +20 -0
  220. package/package.json +18 -2
  221. package/dist/ai/__tests__/ai-service.test.d.ts +0 -2
  222. package/dist/ai/__tests__/ai-service.test.d.ts.map +0 -1
  223. package/dist/ai/__tests__/ai-service.test.js +0 -1078
  224. package/dist/ai/__tests__/ai-service.test.js.map +0 -1
  225. package/dist/ai/__tests__/chunking.test.d.ts +0 -2
  226. package/dist/ai/__tests__/chunking.test.d.ts.map +0 -1
  227. package/dist/ai/__tests__/chunking.test.js +0 -78
  228. package/dist/ai/__tests__/chunking.test.js.map +0 -1
  229. package/dist/ai/__tests__/cost-tracker.test.d.ts +0 -2
  230. package/dist/ai/__tests__/cost-tracker.test.d.ts.map +0 -1
  231. package/dist/ai/__tests__/cost-tracker.test.js +0 -201
  232. package/dist/ai/__tests__/cost-tracker.test.js.map +0 -1
  233. package/dist/ai/__tests__/explainability.test.d.ts +0 -2
  234. package/dist/ai/__tests__/explainability.test.d.ts.map +0 -1
  235. package/dist/ai/__tests__/explainability.test.js +0 -100
  236. package/dist/ai/__tests__/explainability.test.js.map +0 -1
  237. package/dist/ai/__tests__/model-pricing.test.d.ts +0 -2
  238. package/dist/ai/__tests__/model-pricing.test.d.ts.map +0 -1
  239. package/dist/ai/__tests__/model-pricing.test.js +0 -156
  240. package/dist/ai/__tests__/model-pricing.test.js.map +0 -1
  241. package/dist/ai/__tests__/prompt-registry.test.d.ts +0 -2
  242. package/dist/ai/__tests__/prompt-registry.test.d.ts.map +0 -1
  243. package/dist/ai/__tests__/prompt-registry.test.js +0 -56
  244. package/dist/ai/__tests__/prompt-registry.test.js.map +0 -1
  245. package/dist/ai/__tests__/provider.test.d.ts +0 -3
  246. package/dist/ai/__tests__/provider.test.d.ts.map +0 -1
  247. package/dist/ai/__tests__/provider.test.js +0 -979
  248. package/dist/ai/__tests__/provider.test.js.map +0 -1
  249. package/dist/ai/__tests__/rag-pipeline.test.d.ts +0 -2
  250. package/dist/ai/__tests__/rag-pipeline.test.d.ts.map +0 -1
  251. package/dist/ai/__tests__/rag-pipeline.test.js +0 -174
  252. package/dist/ai/__tests__/rag-pipeline.test.js.map +0 -1
  253. package/dist/ai/__tests__/security.test.d.ts +0 -2
  254. package/dist/ai/__tests__/security.test.d.ts.map +0 -1
  255. package/dist/ai/__tests__/security.test.js +0 -89
  256. package/dist/ai/__tests__/security.test.js.map +0 -1
  257. package/dist/ai/__tests__/usage-client.test.d.ts +0 -2
  258. package/dist/ai/__tests__/usage-client.test.d.ts.map +0 -1
  259. package/dist/ai/__tests__/usage-client.test.js +0 -120
  260. package/dist/ai/__tests__/usage-client.test.js.map +0 -1
  261. package/dist/ai/__tests__/validation.test.d.ts +0 -2
  262. package/dist/ai/__tests__/validation.test.d.ts.map +0 -1
  263. package/dist/ai/__tests__/validation.test.js +0 -384
  264. package/dist/ai/__tests__/validation.test.js.map +0 -1
  265. package/dist/ai/__tests__/zod-to-provider-schema.test.d.ts +0 -2
  266. package/dist/ai/__tests__/zod-to-provider-schema.test.d.ts.map +0 -1
  267. package/dist/ai/__tests__/zod-to-provider-schema.test.js +0 -60
  268. package/dist/ai/__tests__/zod-to-provider-schema.test.js.map +0 -1
  269. package/dist/api/__tests__/route-generator.test.d.ts +0 -2
  270. package/dist/api/__tests__/route-generator.test.d.ts.map +0 -1
  271. package/dist/api/__tests__/route-generator.test.js +0 -216
  272. package/dist/api/__tests__/route-generator.test.js.map +0 -1
  273. package/dist/audit/__tests__/service.test.d.ts +0 -2
  274. package/dist/audit/__tests__/service.test.d.ts.map +0 -1
  275. package/dist/audit/__tests__/service.test.js +0 -97
  276. package/dist/audit/__tests__/service.test.js.map +0 -1
  277. package/dist/auth/__tests__/adapter.test.d.ts +0 -2
  278. package/dist/auth/__tests__/adapter.test.d.ts.map +0 -1
  279. package/dist/auth/__tests__/adapter.test.js +0 -218
  280. package/dist/auth/__tests__/adapter.test.js.map +0 -1
  281. package/dist/auth/__tests__/oidc-adapter.test.d.ts +0 -2
  282. package/dist/auth/__tests__/oidc-adapter.test.d.ts.map +0 -1
  283. package/dist/auth/__tests__/oidc-adapter.test.js +0 -232
  284. package/dist/auth/__tests__/oidc-adapter.test.js.map +0 -1
  285. package/dist/auth/__tests__/password.test.d.ts +0 -2
  286. package/dist/auth/__tests__/password.test.d.ts.map +0 -1
  287. package/dist/auth/__tests__/password.test.js +0 -30
  288. package/dist/auth/__tests__/password.test.js.map +0 -1
  289. package/dist/auth/__tests__/saml-adapter.test.d.ts +0 -2
  290. package/dist/auth/__tests__/saml-adapter.test.d.ts.map +0 -1
  291. package/dist/auth/__tests__/saml-adapter.test.js +0 -188
  292. package/dist/auth/__tests__/saml-adapter.test.js.map +0 -1
  293. package/dist/auth/__tests__/scim.test.d.ts +0 -2
  294. package/dist/auth/__tests__/scim.test.d.ts.map +0 -1
  295. package/dist/auth/__tests__/scim.test.js +0 -306
  296. package/dist/auth/__tests__/scim.test.js.map +0 -1
  297. package/dist/cli/__tests__/agent.test.d.ts +0 -2
  298. package/dist/cli/__tests__/agent.test.d.ts.map +0 -1
  299. package/dist/cli/__tests__/agent.test.js +0 -63
  300. package/dist/cli/__tests__/agent.test.js.map +0 -1
  301. package/dist/cli/__tests__/certify.test.d.ts +0 -2
  302. package/dist/cli/__tests__/certify.test.d.ts.map +0 -1
  303. package/dist/cli/__tests__/certify.test.js +0 -97
  304. package/dist/cli/__tests__/certify.test.js.map +0 -1
  305. package/dist/cli/__tests__/cli.test.d.ts +0 -2
  306. package/dist/cli/__tests__/cli.test.d.ts.map +0 -1
  307. package/dist/cli/__tests__/cli.test.js +0 -123
  308. package/dist/cli/__tests__/cli.test.js.map +0 -1
  309. package/dist/cli/__tests__/create.test.d.ts +0 -2
  310. package/dist/cli/__tests__/create.test.d.ts.map +0 -1
  311. package/dist/cli/__tests__/create.test.js +0 -183
  312. package/dist/cli/__tests__/create.test.js.map +0 -1
  313. package/dist/cli/__tests__/dev.test.d.ts +0 -2
  314. package/dist/cli/__tests__/dev.test.d.ts.map +0 -1
  315. package/dist/cli/__tests__/dev.test.js +0 -132
  316. package/dist/cli/__tests__/dev.test.js.map +0 -1
  317. package/dist/cli/__tests__/discover.test.d.ts +0 -2
  318. package/dist/cli/__tests__/discover.test.d.ts.map +0 -1
  319. package/dist/cli/__tests__/discover.test.js +0 -48
  320. package/dist/cli/__tests__/discover.test.js.map +0 -1
  321. package/dist/cli/__tests__/doctor.test.d.ts +0 -2
  322. package/dist/cli/__tests__/doctor.test.d.ts.map +0 -1
  323. package/dist/cli/__tests__/doctor.test.js +0 -172
  324. package/dist/cli/__tests__/doctor.test.js.map +0 -1
  325. package/dist/cli/__tests__/generate.test.d.ts +0 -2
  326. package/dist/cli/__tests__/generate.test.d.ts.map +0 -1
  327. package/dist/cli/__tests__/generate.test.js +0 -478
  328. package/dist/cli/__tests__/generate.test.js.map +0 -1
  329. package/dist/cli/__tests__/init.test.d.ts +0 -2
  330. package/dist/cli/__tests__/init.test.d.ts.map +0 -1
  331. package/dist/cli/__tests__/init.test.js +0 -236
  332. package/dist/cli/__tests__/init.test.js.map +0 -1
  333. package/dist/cli/__tests__/migrate.test.d.ts +0 -2
  334. package/dist/cli/__tests__/migrate.test.d.ts.map +0 -1
  335. package/dist/cli/__tests__/migrate.test.js +0 -442
  336. package/dist/cli/__tests__/migrate.test.js.map +0 -1
  337. package/dist/cli/__tests__/start.test.d.ts +0 -2
  338. package/dist/cli/__tests__/start.test.d.ts.map +0 -1
  339. package/dist/cli/__tests__/start.test.js +0 -91
  340. package/dist/cli/__tests__/start.test.js.map +0 -1
  341. package/dist/cli/__tests__/templates.test.d.ts +0 -2
  342. package/dist/cli/__tests__/templates.test.d.ts.map +0 -1
  343. package/dist/cli/__tests__/templates.test.js +0 -49
  344. package/dist/cli/__tests__/templates.test.js.map +0 -1
  345. package/dist/cli/__tests__/test.test.d.ts +0 -2
  346. package/dist/cli/__tests__/test.test.d.ts.map +0 -1
  347. package/dist/cli/__tests__/test.test.js +0 -40
  348. package/dist/cli/__tests__/test.test.js.map +0 -1
  349. package/dist/cli/__tests__/ui.test.d.ts +0 -2
  350. package/dist/cli/__tests__/ui.test.d.ts.map +0 -1
  351. package/dist/cli/__tests__/ui.test.js +0 -76
  352. package/dist/cli/__tests__/ui.test.js.map +0 -1
  353. package/dist/cli/__tests__/upgrade.test.d.ts +0 -2
  354. package/dist/cli/__tests__/upgrade.test.d.ts.map +0 -1
  355. package/dist/cli/__tests__/upgrade.test.js +0 -20
  356. package/dist/cli/__tests__/upgrade.test.js.map +0 -1
  357. package/dist/cli/__tests__/utils.test.d.ts +0 -2
  358. package/dist/cli/__tests__/utils.test.d.ts.map +0 -1
  359. package/dist/cli/__tests__/utils.test.js +0 -255
  360. package/dist/cli/__tests__/utils.test.js.map +0 -1
  361. package/dist/cli/__tests__/verify.test.d.ts +0 -2
  362. package/dist/cli/__tests__/verify.test.d.ts.map +0 -1
  363. package/dist/cli/__tests__/verify.test.js +0 -138
  364. package/dist/cli/__tests__/verify.test.js.map +0 -1
  365. package/dist/cli/commands/__tests__/commands.test.d.ts +0 -2
  366. package/dist/cli/commands/__tests__/commands.test.d.ts.map +0 -1
  367. package/dist/cli/commands/__tests__/commands.test.js +0 -185
  368. package/dist/cli/commands/__tests__/commands.test.js.map +0 -1
  369. package/dist/config/__tests__/loader.test.d.ts +0 -2
  370. package/dist/config/__tests__/loader.test.d.ts.map +0 -1
  371. package/dist/config/__tests__/loader.test.js +0 -462
  372. package/dist/config/__tests__/loader.test.js.map +0 -1
  373. package/dist/data/__tests__/drift-inspector.test.d.ts +0 -2
  374. package/dist/data/__tests__/drift-inspector.test.d.ts.map +0 -1
  375. package/dist/data/__tests__/drift-inspector.test.js +0 -170
  376. package/dist/data/__tests__/drift-inspector.test.js.map +0 -1
  377. package/dist/data/__tests__/framework-migration-rewriter.test.d.ts +0 -2
  378. package/dist/data/__tests__/framework-migration-rewriter.test.d.ts.map +0 -1
  379. package/dist/data/__tests__/framework-migration-rewriter.test.js +0 -329
  380. package/dist/data/__tests__/framework-migration-rewriter.test.js.map +0 -1
  381. package/dist/data/__tests__/migration.test.d.ts +0 -2
  382. package/dist/data/__tests__/migration.test.d.ts.map +0 -1
  383. package/dist/data/__tests__/migration.test.js +0 -143
  384. package/dist/data/__tests__/migration.test.js.map +0 -1
  385. package/dist/data/__tests__/registry.test.d.ts +0 -2
  386. package/dist/data/__tests__/registry.test.d.ts.map +0 -1
  387. package/dist/data/__tests__/registry.test.js +0 -70
  388. package/dist/data/__tests__/registry.test.js.map +0 -1
  389. package/dist/data/__tests__/repository.test.d.ts +0 -2
  390. package/dist/data/__tests__/repository.test.d.ts.map +0 -1
  391. package/dist/data/__tests__/repository.test.js +0 -559
  392. package/dist/data/__tests__/repository.test.js.map +0 -1
  393. package/dist/data/__tests__/schema-generator.test.d.ts +0 -2
  394. package/dist/data/__tests__/schema-generator.test.d.ts.map +0 -1
  395. package/dist/data/__tests__/schema-generator.test.js +0 -112
  396. package/dist/data/__tests__/schema-generator.test.js.map +0 -1
  397. package/dist/define/__tests__/defineCapability.test.d.ts +0 -2
  398. package/dist/define/__tests__/defineCapability.test.d.ts.map +0 -1
  399. package/dist/define/__tests__/defineCapability.test.js +0 -66
  400. package/dist/define/__tests__/defineCapability.test.js.map +0 -1
  401. package/dist/define/__tests__/defineEntity.test.d.ts +0 -2
  402. package/dist/define/__tests__/defineEntity.test.d.ts.map +0 -1
  403. package/dist/define/__tests__/defineEntity.test.js +0 -50
  404. package/dist/define/__tests__/defineEntity.test.js.map +0 -1
  405. package/dist/define/__tests__/defineEvent.test.d.ts +0 -2
  406. package/dist/define/__tests__/defineEvent.test.d.ts.map +0 -1
  407. package/dist/define/__tests__/defineEvent.test.js +0 -35
  408. package/dist/define/__tests__/defineEvent.test.js.map +0 -1
  409. package/dist/define/__tests__/defineFlow.test.d.ts +0 -2
  410. package/dist/define/__tests__/defineFlow.test.d.ts.map +0 -1
  411. package/dist/define/__tests__/defineFlow.test.js +0 -49
  412. package/dist/define/__tests__/defineFlow.test.js.map +0 -1
  413. package/dist/define/__tests__/definePrompt.test.d.ts +0 -2
  414. package/dist/define/__tests__/definePrompt.test.d.ts.map +0 -1
  415. package/dist/define/__tests__/definePrompt.test.js +0 -77
  416. package/dist/define/__tests__/definePrompt.test.js.map +0 -1
  417. package/dist/define/__tests__/defineTranslation.test.d.ts +0 -2
  418. package/dist/define/__tests__/defineTranslation.test.d.ts.map +0 -1
  419. package/dist/define/__tests__/defineTranslation.test.js +0 -90
  420. package/dist/define/__tests__/defineTranslation.test.js.map +0 -1
  421. package/dist/errors/__tests__/errors.test.d.ts +0 -2
  422. package/dist/errors/__tests__/errors.test.d.ts.map +0 -1
  423. package/dist/errors/__tests__/errors.test.js +0 -70
  424. package/dist/errors/__tests__/errors.test.js.map +0 -1
  425. package/dist/errors/__tests__/http.test.d.ts +0 -2
  426. package/dist/errors/__tests__/http.test.d.ts.map +0 -1
  427. package/dist/errors/__tests__/http.test.js +0 -35
  428. package/dist/errors/__tests__/http.test.js.map +0 -1
  429. package/dist/events/__tests__/consumer-registry.test.d.ts +0 -2
  430. package/dist/events/__tests__/consumer-registry.test.d.ts.map +0 -1
  431. package/dist/events/__tests__/consumer-registry.test.js +0 -68
  432. package/dist/events/__tests__/consumer-registry.test.js.map +0 -1
  433. package/dist/events/__tests__/dispatcher.test.d.ts +0 -2
  434. package/dist/events/__tests__/dispatcher.test.d.ts.map +0 -1
  435. package/dist/events/__tests__/dispatcher.test.js +0 -168
  436. package/dist/events/__tests__/dispatcher.test.js.map +0 -1
  437. package/dist/events/__tests__/event-emitter.test.d.ts +0 -2
  438. package/dist/events/__tests__/event-emitter.test.d.ts.map +0 -1
  439. package/dist/events/__tests__/event-emitter.test.js +0 -172
  440. package/dist/events/__tests__/event-emitter.test.js.map +0 -1
  441. package/dist/events/__tests__/event-registry.test.d.ts +0 -2
  442. package/dist/events/__tests__/event-registry.test.d.ts.map +0 -1
  443. package/dist/events/__tests__/event-registry.test.js +0 -55
  444. package/dist/events/__tests__/event-registry.test.js.map +0 -1
  445. package/dist/events/__tests__/event-worker.test.d.ts +0 -2
  446. package/dist/events/__tests__/event-worker.test.d.ts.map +0 -1
  447. package/dist/events/__tests__/event-worker.test.js +0 -174
  448. package/dist/events/__tests__/event-worker.test.js.map +0 -1
  449. package/dist/events/__tests__/queue.test.d.ts +0 -2
  450. package/dist/events/__tests__/queue.test.d.ts.map +0 -1
  451. package/dist/events/__tests__/queue.test.js +0 -73
  452. package/dist/events/__tests__/queue.test.js.map +0 -1
  453. package/dist/execution/__tests__/authorization.test.d.ts +0 -2
  454. package/dist/execution/__tests__/authorization.test.d.ts.map +0 -1
  455. package/dist/execution/__tests__/authorization.test.js +0 -99
  456. package/dist/execution/__tests__/authorization.test.js.map +0 -1
  457. package/dist/execution/__tests__/capability-executor.test.d.ts +0 -2
  458. package/dist/execution/__tests__/capability-executor.test.d.ts.map +0 -1
  459. package/dist/execution/__tests__/capability-executor.test.js +0 -212
  460. package/dist/execution/__tests__/capability-executor.test.js.map +0 -1
  461. package/dist/execution/__tests__/capability-registry.test.d.ts +0 -2
  462. package/dist/execution/__tests__/capability-registry.test.d.ts.map +0 -1
  463. package/dist/execution/__tests__/capability-registry.test.js +0 -50
  464. package/dist/execution/__tests__/capability-registry.test.js.map +0 -1
  465. package/dist/execution/__tests__/context-factory.test.d.ts +0 -2
  466. package/dist/execution/__tests__/context-factory.test.d.ts.map +0 -1
  467. package/dist/execution/__tests__/context-factory.test.js +0 -133
  468. package/dist/execution/__tests__/context-factory.test.js.map +0 -1
  469. package/dist/explanation/__tests__/tracker.test.d.ts +0 -2
  470. package/dist/explanation/__tests__/tracker.test.d.ts.map +0 -1
  471. package/dist/explanation/__tests__/tracker.test.js +0 -169
  472. package/dist/explanation/__tests__/tracker.test.js.map +0 -1
  473. package/dist/fields/__tests__/fields.test.d.ts +0 -2
  474. package/dist/fields/__tests__/fields.test.d.ts.map +0 -1
  475. package/dist/fields/__tests__/fields.test.js +0 -60
  476. package/dist/fields/__tests__/fields.test.js.map +0 -1
  477. package/dist/flows/__tests__/flow-engine.test.d.ts +0 -2
  478. package/dist/flows/__tests__/flow-engine.test.d.ts.map +0 -1
  479. package/dist/flows/__tests__/flow-engine.test.js +0 -797
  480. package/dist/flows/__tests__/flow-engine.test.js.map +0 -1
  481. package/dist/flows/__tests__/flow-registry.test.d.ts +0 -2
  482. package/dist/flows/__tests__/flow-registry.test.d.ts.map +0 -1
  483. package/dist/flows/__tests__/flow-registry.test.js +0 -69
  484. package/dist/flows/__tests__/flow-registry.test.js.map +0 -1
  485. package/dist/flows/__tests__/flow-service.test.d.ts +0 -2
  486. package/dist/flows/__tests__/flow-service.test.d.ts.map +0 -1
  487. package/dist/flows/__tests__/flow-service.test.js +0 -55
  488. package/dist/flows/__tests__/flow-service.test.js.map +0 -1
  489. package/dist/flows/__tests__/scheduler.test.d.ts +0 -2
  490. package/dist/flows/__tests__/scheduler.test.d.ts.map +0 -1
  491. package/dist/flows/__tests__/scheduler.test.js +0 -120
  492. package/dist/flows/__tests__/scheduler.test.js.map +0 -1
  493. package/dist/flows/__tests__/state-machine.test.d.ts +0 -2
  494. package/dist/flows/__tests__/state-machine.test.d.ts.map +0 -1
  495. package/dist/flows/__tests__/state-machine.test.js +0 -62
  496. package/dist/flows/__tests__/state-machine.test.js.map +0 -1
  497. package/dist/flows/__tests__/step-executor.test.d.ts +0 -2
  498. package/dist/flows/__tests__/step-executor.test.d.ts.map +0 -1
  499. package/dist/flows/__tests__/step-executor.test.js +0 -201
  500. package/dist/flows/__tests__/step-executor.test.js.map +0 -1
  501. package/dist/flows/__tests__/triggers.test.d.ts +0 -2
  502. package/dist/flows/__tests__/triggers.test.d.ts.map +0 -1
  503. package/dist/flows/__tests__/triggers.test.js +0 -98
  504. package/dist/flows/__tests__/triggers.test.js.map +0 -1
  505. package/dist/governance/__tests__/overrides.test.d.ts +0 -2
  506. package/dist/governance/__tests__/overrides.test.d.ts.map +0 -1
  507. package/dist/governance/__tests__/overrides.test.js +0 -123
  508. package/dist/governance/__tests__/overrides.test.js.map +0 -1
  509. package/dist/governance/__tests__/policies.test.d.ts +0 -2
  510. package/dist/governance/__tests__/policies.test.d.ts.map +0 -1
  511. package/dist/governance/__tests__/policies.test.js +0 -203
  512. package/dist/governance/__tests__/policies.test.js.map +0 -1
  513. package/dist/governance/__tests__/rules.test.d.ts +0 -2
  514. package/dist/governance/__tests__/rules.test.d.ts.map +0 -1
  515. package/dist/governance/__tests__/rules.test.js +0 -342
  516. package/dist/governance/__tests__/rules.test.js.map +0 -1
  517. package/dist/observability/__tests__/metrics.test.d.ts +0 -2
  518. package/dist/observability/__tests__/metrics.test.d.ts.map +0 -1
  519. package/dist/observability/__tests__/metrics.test.js +0 -301
  520. package/dist/observability/__tests__/metrics.test.js.map +0 -1
  521. package/dist/server/__tests__/bootstrap.test.d.ts +0 -2
  522. package/dist/server/__tests__/bootstrap.test.d.ts.map +0 -1
  523. package/dist/server/__tests__/bootstrap.test.js +0 -381
  524. package/dist/server/__tests__/bootstrap.test.js.map +0 -1
  525. package/dist/testing/__tests__/context.test.d.ts +0 -2
  526. package/dist/testing/__tests__/context.test.d.ts.map +0 -1
  527. package/dist/testing/__tests__/context.test.js +0 -341
  528. package/dist/testing/__tests__/context.test.js.map +0 -1
  529. package/dist/testing/__tests__/e2e.test.d.ts +0 -2
  530. package/dist/testing/__tests__/e2e.test.d.ts.map +0 -1
  531. package/dist/testing/__tests__/e2e.test.js +0 -119
  532. package/dist/testing/__tests__/e2e.test.js.map +0 -1
  533. package/dist/testing/__tests__/field-validation.test.d.ts +0 -2
  534. package/dist/testing/__tests__/field-validation.test.d.ts.map +0 -1
  535. package/dist/testing/__tests__/field-validation.test.js +0 -178
  536. package/dist/testing/__tests__/field-validation.test.js.map +0 -1
  537. package/dist/testing/__tests__/governance.test.d.ts +0 -2
  538. package/dist/testing/__tests__/governance.test.d.ts.map +0 -1
  539. package/dist/testing/__tests__/governance.test.js +0 -222
  540. package/dist/testing/__tests__/governance.test.js.map +0 -1
  541. package/dist/testing/__tests__/run-capability.test.d.ts +0 -2
  542. package/dist/testing/__tests__/run-capability.test.d.ts.map +0 -1
  543. package/dist/testing/__tests__/run-capability.test.js +0 -114
  544. package/dist/testing/__tests__/run-capability.test.js.map +0 -1
  545. package/dist/testing/__tests__/scaffolding.test.d.ts +0 -2
  546. package/dist/testing/__tests__/scaffolding.test.d.ts.map +0 -1
  547. package/dist/testing/__tests__/scaffolding.test.js +0 -70
  548. package/dist/testing/__tests__/scaffolding.test.js.map +0 -1
  549. package/dist/testing/__tests__/security.test.d.ts +0 -2
  550. package/dist/testing/__tests__/security.test.d.ts.map +0 -1
  551. package/dist/testing/__tests__/security.test.js +0 -186
  552. package/dist/testing/__tests__/security.test.js.map +0 -1
  553. package/dist/testing/__tests__/simulate-flow.test.d.ts +0 -2
  554. package/dist/testing/__tests__/simulate-flow.test.d.ts.map +0 -1
  555. package/dist/testing/__tests__/simulate-flow.test.js +0 -230
  556. package/dist/testing/__tests__/simulate-flow.test.js.map +0 -1
  557. package/dist/translations/__tests__/translation-resolver.test.d.ts +0 -2
  558. package/dist/translations/__tests__/translation-resolver.test.d.ts.map +0 -1
  559. package/dist/translations/__tests__/translation-resolver.test.js +0 -140
  560. package/dist/translations/__tests__/translation-resolver.test.js.map +0 -1
  561. package/dist/types/__tests__/registry.test.d.ts +0 -2
  562. package/dist/types/__tests__/registry.test.d.ts.map +0 -1
  563. package/dist/types/__tests__/registry.test.js +0 -34
  564. package/dist/types/__tests__/registry.test.js.map +0 -1
  565. package/dist/worker/__tests__/bootstrap.test.d.ts +0 -2
  566. package/dist/worker/__tests__/bootstrap.test.d.ts.map +0 -1
  567. package/dist/worker/__tests__/bootstrap.test.js +0 -268
  568. package/dist/worker/__tests__/bootstrap.test.js.map +0 -1
  569. package/dist/worker/__tests__/flow-service-wiring.test.d.ts +0 -2
  570. package/dist/worker/__tests__/flow-service-wiring.test.d.ts.map +0 -1
  571. package/dist/worker/__tests__/flow-service-wiring.test.js +0 -64
  572. package/dist/worker/__tests__/flow-service-wiring.test.js.map +0 -1
@@ -1,797 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { z } from 'zod';
3
- import { defineFlow } from '../../define/defineFlow.js';
4
- import { LeaseLostError } from '../../errors/index.js';
5
- import { FlowStepType } from '../../types/enums.js';
6
- import { createFlowEngine } from '../engine.js';
7
- import { FlowRegistry } from '../registry.js';
8
- import { FlowStatus } from '../state-machine.js';
9
- /**
10
- * Creates a mock DB that tracks inserts and updates,
11
- * and returns rows from a provided store.
12
- */
13
- function mockDb(rows = new Map()) {
14
- const inserts = [];
15
- const updates = [];
16
- // Mutable state lets individual tests drive behavior: execute() return value and
17
- // guardedUpdate rowCount (0 simulates a lost lease).
18
- const state = {
19
- executeResult: [],
20
- updateRowCount: 1,
21
- };
22
- return {
23
- _inserts: inserts,
24
- _updates: updates,
25
- _rows: rows,
26
- _state: state,
27
- insert: vi.fn().mockReturnValue({
28
- values: vi.fn().mockImplementation((row) => {
29
- inserts.push(row);
30
- rows.set(row.id, {
31
- ...row,
32
- createdAt: new Date(),
33
- updatedAt: new Date(),
34
- completedAt: null,
35
- });
36
- return Promise.resolve();
37
- }),
38
- }),
39
- select: vi.fn().mockReturnValue({
40
- from: vi.fn().mockReturnValue({
41
- where: vi.fn().mockReturnValue({
42
- limit: vi.fn().mockImplementation(() => {
43
- // Return the most recently queried row from the map
44
- const allRows = Array.from(rows.values());
45
- return Promise.resolve(allRows.length > 0 ? [allRows[allRows.length - 1]] : []);
46
- }),
47
- }),
48
- }),
49
- }),
50
- update: vi.fn().mockReturnValue({
51
- set: vi.fn().mockImplementation((values) => ({
52
- where: vi.fn().mockImplementation(() => {
53
- updates.push(values);
54
- const allRows = Array.from(rows.values());
55
- if (allRows.length > 0 && state.updateRowCount > 0) {
56
- const last = allRows[allRows.length - 1];
57
- Object.assign(last, values);
58
- }
59
- return Promise.resolve({ rowCount: state.updateRowCount });
60
- }),
61
- })),
62
- }),
63
- execute: vi.fn().mockImplementation(() => Promise.resolve(state.executeResult)),
64
- };
65
- }
66
- function makeTestFlow() {
67
- return defineFlow({
68
- name: 'order-processing',
69
- domain: 'orders',
70
- input: z.object({ orderId: z.string() }),
71
- steps: [
72
- { name: 'validate', type: FlowStepType.Capability },
73
- { name: 'process', type: FlowStepType.Capability },
74
- { name: 'notify', type: FlowStepType.Capability },
75
- ],
76
- });
77
- }
78
- function makeAuth() {
79
- return {
80
- userId: 'user-1',
81
- tenantId: 'tenant-1',
82
- roles: ['admin'],
83
- scopes: [],
84
- provider: 'test',
85
- };
86
- }
87
- function makeCtx(overrides) {
88
- return {
89
- auth: makeAuth(),
90
- data: {},
91
- events: {
92
- emit: vi.fn().mockResolvedValue(undefined),
93
- emitMany: vi.fn().mockResolvedValue(undefined),
94
- },
95
- flows: {
96
- start: vi.fn(),
97
- resume: vi.fn(),
98
- cancel: vi.fn(),
99
- status: vi.fn(),
100
- },
101
- ai: {},
102
- audit: { record: vi.fn() },
103
- errors: {},
104
- logger: {
105
- debug: vi.fn(),
106
- info: vi.fn(),
107
- warn: vi.fn(),
108
- error: vi.fn(),
109
- },
110
- time: { now: () => new Date() },
111
- config: {},
112
- security: {},
113
- translations: { locale: 'en', t: (key) => key },
114
- ...overrides,
115
- };
116
- }
117
- function makeStepDeps(succeeds = true) {
118
- return {
119
- executeCapability: vi
120
- .fn()
121
- .mockResolvedValue(succeeds ? { success: true, data: {} } : { success: false, error: 'step failed' }),
122
- evaluateCondition: vi.fn().mockReturnValue(true),
123
- };
124
- }
125
- describe('FlowEngine', () => {
126
- it('starts a flow and creates execution record', async () => {
127
- const registry = new FlowRegistry();
128
- registry.register(makeTestFlow());
129
- const db = mockDb();
130
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps() });
131
- const exec = await engine.start('order-processing', { orderId: '123' }, makeAuth());
132
- expect(exec.flowName).toBe('order-processing');
133
- expect(exec.status).toBe(FlowStatus.Created);
134
- expect(exec.id).toBeTruthy();
135
- expect(db._inserts).toHaveLength(1);
136
- expect(db._inserts[0].flowName).toBe('order-processing');
137
- });
138
- it('throws on unregistered flow', async () => {
139
- const registry = new FlowRegistry();
140
- const db = mockDb();
141
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps() });
142
- await expect(engine.start('nope', {}, makeAuth())).rejects.toThrow('not registered');
143
- });
144
- it('validates input against flow schema', async () => {
145
- const registry = new FlowRegistry();
146
- registry.register(makeTestFlow());
147
- const db = mockDb();
148
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps() });
149
- await expect(engine.start('order-processing', { wrong: 123 }, makeAuth())).rejects.toThrow('invalid input');
150
- });
151
- it('gets flow execution status', async () => {
152
- const registry = new FlowRegistry();
153
- registry.register(makeTestFlow());
154
- const db = mockDb();
155
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps() });
156
- const exec = await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
157
- // Mock the select to return the created row
158
- const row = db._rows.get(exec.id);
159
- db.select = vi.fn().mockReturnValue({
160
- from: vi.fn().mockReturnValue({
161
- where: vi.fn().mockReturnValue({
162
- limit: vi.fn().mockResolvedValue([row]),
163
- }),
164
- }),
165
- });
166
- const st = await engine.status(exec.id);
167
- expect(st.id).toBe(exec.id);
168
- expect(st.flowName).toBe('order-processing');
169
- });
170
- it('cancels a created flow', async () => {
171
- const registry = new FlowRegistry();
172
- registry.register(makeTestFlow());
173
- const db = mockDb();
174
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps() });
175
- const exec = await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
176
- const row = db._rows.get(exec.id);
177
- db.select = vi.fn().mockReturnValue({
178
- from: vi.fn().mockReturnValue({
179
- where: vi.fn().mockReturnValue({
180
- limit: vi.fn().mockResolvedValue([row]),
181
- }),
182
- }),
183
- });
184
- await engine.cancel(exec.id);
185
- expect(db._updates.some((u) => u.status === FlowStatus.Cancelled)).toBe(true);
186
- });
187
- it('throws when cancelling a terminal flow', async () => {
188
- const registry = new FlowRegistry();
189
- registry.register(makeTestFlow());
190
- const rows = new Map();
191
- rows.set('x', {
192
- id: 'x',
193
- flowName: 'order-processing',
194
- status: FlowStatus.Completed,
195
- currentStep: null,
196
- stepHistory: [],
197
- state: null,
198
- retryCount: 0,
199
- });
200
- const db = mockDb(rows);
201
- db.select = vi.fn().mockReturnValue({
202
- from: vi.fn().mockReturnValue({
203
- where: vi.fn().mockReturnValue({
204
- limit: vi.fn().mockResolvedValue([rows.get('x')]),
205
- }),
206
- }),
207
- });
208
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps() });
209
- await expect(engine.cancel('x')).rejects.toThrow('terminal state');
210
- });
211
- it('records audit events when audit service provided', async () => {
212
- const registry = new FlowRegistry();
213
- registry.register(makeTestFlow());
214
- const db = mockDb();
215
- const auditRecords = [];
216
- const audit = {
217
- record: vi.fn().mockImplementation(async (action, meta) => {
218
- auditRecords.push({ action, ...meta });
219
- }),
220
- };
221
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps(), audit });
222
- await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
223
- expect(auditRecords).toHaveLength(1);
224
- expect(auditRecords[0].action).toBe('flow.started.order-processing');
225
- });
226
- it('merges capability output into persisted state between steps', async () => {
227
- const registry = new FlowRegistry();
228
- registry.register(defineFlow({
229
- name: 'stateful-flow',
230
- domain: 'orders',
231
- input: z.object({ orderId: z.string() }),
232
- state: z.object({ manuscriptId: z.string().default('') }),
233
- steps: [
234
- { name: 'plan', type: FlowStepType.Capability },
235
- { name: 'write', type: FlowStepType.Capability },
236
- ],
237
- }));
238
- const db = mockDb();
239
- const stepDeps = {
240
- executeCapability: vi
241
- .fn()
242
- .mockResolvedValueOnce({ success: true, data: { manuscriptId: 'm-1' } })
243
- .mockResolvedValueOnce({ success: true, data: {} }),
244
- evaluateCondition: vi.fn().mockReturnValue(true),
245
- };
246
- const engine = createFlowEngine({ db, registry, stepDeps });
247
- const exec = await engine.start('stateful-flow', { orderId: 'abc' }, makeAuth());
248
- const row = db._rows.get(exec.id);
249
- db.select = vi.fn().mockReturnValue({
250
- from: vi.fn().mockReturnValue({
251
- where: vi.fn().mockReturnValue({
252
- limit: vi.fn().mockResolvedValue([row]),
253
- }),
254
- }),
255
- });
256
- await engine.runNext(exec.id, makeCtx());
257
- expect(row.state).toMatchObject({ manuscriptId: 'm-1' });
258
- expect(row.currentStep).toBe('write');
259
- });
260
- it('passes the live DB connection to onFlowError hooks', async () => {
261
- const registry = new FlowRegistry();
262
- registry.register(makeTestFlow());
263
- const db = mockDb();
264
- const onFlowError = vi.fn();
265
- const engine = createFlowEngine({ db, registry, stepDeps: makeStepDeps(false), onFlowError });
266
- const exec = await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
267
- const row = db._rows.get(exec.id);
268
- db.select = vi.fn().mockReturnValue({
269
- from: vi.fn().mockReturnValue({
270
- where: vi.fn().mockReturnValue({
271
- limit: vi.fn().mockResolvedValue([row]),
272
- }),
273
- }),
274
- });
275
- await engine.runNext(exec.id, makeCtx());
276
- expect(onFlowError).toHaveBeenCalledWith(expect.objectContaining({
277
- db,
278
- executionId: exec.id,
279
- flowName: 'order-processing',
280
- step: 'validate',
281
- error: 'step failed',
282
- }));
283
- });
284
- });
285
- describe('FlowEngine — lease claiming', () => {
286
- it('only one worker claims a row under a SKIP LOCKED race', async () => {
287
- const registry = new FlowRegistry();
288
- registry.register(makeTestFlow());
289
- const claimedRow = {
290
- id: 'race-1',
291
- flowName: 'order-processing',
292
- status: FlowStatus.Running,
293
- currentStep: 'validate',
294
- leaseOwner: null,
295
- };
296
- const dbA = mockDb();
297
- dbA._state.executeResult = [claimedRow];
298
- const dbB = mockDb();
299
- dbB._state.executeResult = [];
300
- const engineA = createFlowEngine({
301
- db: dbA,
302
- registry,
303
- stepDeps: makeStepDeps(),
304
- workerId: 'worker-a',
305
- });
306
- const engineB = createFlowEngine({
307
- db: dbB,
308
- registry,
309
- stepDeps: makeStepDeps(),
310
- workerId: 'worker-b',
311
- });
312
- const [claimedA, claimedB] = await Promise.all([engineA.claimNext(), engineB.claimNext()]);
313
- expect(claimedA).toHaveLength(1);
314
- expect(claimedA[0]?.id).toBe('race-1');
315
- expect(claimedB).toHaveLength(0);
316
- });
317
- it("reclaims a crashed worker's expired lease and audits the reclaim", async () => {
318
- const registry = new FlowRegistry();
319
- registry.register(makeTestFlow());
320
- const db = mockDb();
321
- db._state.executeResult = [
322
- {
323
- id: 'exec-crash',
324
- flowName: 'order-processing',
325
- status: FlowStatus.Running,
326
- currentStep: 'validate',
327
- leaseOwner: 'crashed-worker',
328
- leaseExpiresAt: new Date(Date.now() - 60_000),
329
- },
330
- ];
331
- const audits = [];
332
- const audit = {
333
- record: vi.fn().mockImplementation(async (action, meta) => {
334
- audits.push({ action, ...meta });
335
- }),
336
- };
337
- const engine = createFlowEngine({
338
- db,
339
- registry,
340
- stepDeps: makeStepDeps(),
341
- workerId: 'worker-fresh',
342
- audit,
343
- });
344
- const claimed = await engine.claimNext();
345
- expect(claimed).toHaveLength(1);
346
- expect(claimed[0]?.id).toBe('exec-crash');
347
- const expired = audits.find((a) => a.action === 'flow.lease.expired');
348
- expect(expired).toBeDefined();
349
- expect(expired.previousOwner).toBe('crashed-worker');
350
- expect(expired.workerId).toBe('worker-fresh');
351
- expect(audits.some((a) => a.action === 'flow.lease.claimed')).toBe(true);
352
- });
353
- it('throws LeaseLostError when heartbeat detects the lease was stolen mid-step', async () => {
354
- const registry = new FlowRegistry();
355
- registry.register(makeTestFlow());
356
- const db = mockDb();
357
- db._state.updateRowCount = 0; // every update says "0 rows affected" → heartbeat loses lease
358
- const stepDeps = {
359
- executeCapability: vi.fn().mockImplementation(async () => {
360
- // Give the heartbeat interval at least one tick to fire during the step
361
- await new Promise((r) => setTimeout(r, 40));
362
- return { success: true, data: {} };
363
- }),
364
- evaluateCondition: vi.fn().mockReturnValue(true),
365
- };
366
- const engine = createFlowEngine({
367
- db,
368
- registry,
369
- stepDeps,
370
- workerId: 'worker-x',
371
- flowHeartbeatIntervalMs: 5,
372
- flowLeaseDurationMs: 60_000,
373
- });
374
- const exec = await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
375
- await expect(engine.runNext(exec.id, makeCtx())).rejects.toBeInstanceOf(LeaseLostError);
376
- });
377
- it('skips completion audit when guardedUpdate reports the lease was lost', async () => {
378
- const registry = new FlowRegistry();
379
- registry.register(defineFlow({
380
- name: 'single-step',
381
- domain: 'test',
382
- input: z.object({}),
383
- steps: [{ name: 'only', type: FlowStepType.Capability }],
384
- }));
385
- const db = mockDb();
386
- db._state.updateRowCount = 0; // all guardedUpdates return false → completeFlow aborts before audit
387
- const audits = [];
388
- const audit = {
389
- record: vi.fn().mockImplementation(async (action, meta) => {
390
- audits.push({ action, ...meta });
391
- }),
392
- };
393
- const engine = createFlowEngine({
394
- db,
395
- registry,
396
- stepDeps: makeStepDeps(),
397
- workerId: 'worker-x',
398
- audit,
399
- flowHeartbeatIntervalMs: 60_000, // keep the heartbeat timer idle during the fast test
400
- });
401
- const exec = await engine.start('single-step', {}, makeAuth());
402
- await engine.runNext(exec.id, makeCtx());
403
- expect(audits.some((a) => a.action === 'flow.completed.single-step')).toBe(false);
404
- });
405
- it('20 executions across 4 engines — each claimed exactly once', async () => {
406
- const registry = new FlowRegistry();
407
- registry.register(makeTestFlow());
408
- const available = new Set(Array.from({ length: 20 }, (_, i) => `exec-${i}`));
409
- const engines = ['w1', 'w2', 'w3', 'w4'].map((workerId) => {
410
- const db = mockDb();
411
- // Simulate FOR UPDATE SKIP LOCKED: each execute call atomically takes up to 5 rows
412
- // from the shared `available` set (synchronous mutation — JS single-threaded).
413
- db.execute = vi.fn().mockImplementation(async () => {
414
- const taken = [];
415
- for (const id of Array.from(available)) {
416
- if (taken.length >= 5)
417
- break;
418
- available.delete(id);
419
- taken.push({
420
- id,
421
- flowName: 'order-processing',
422
- status: FlowStatus.Running,
423
- currentStep: 'validate',
424
- leaseOwner: workerId,
425
- });
426
- }
427
- return taken;
428
- });
429
- return createFlowEngine({
430
- db,
431
- registry,
432
- stepDeps: makeStepDeps(),
433
- workerId,
434
- });
435
- });
436
- const results = await Promise.all(engines.map((e) => e.claimNext(5)));
437
- const claimedIds = results.flatMap((batch) => batch.map((row) => row.id));
438
- expect(claimedIds).toHaveLength(20);
439
- expect(new Set(claimedIds).size).toBe(20); // every ID is unique
440
- expect(available.size).toBe(0);
441
- });
442
- it('ctx.flows.heartbeat() extends the lease and throws LeaseLostError when lost', async () => {
443
- const registry = new FlowRegistry();
444
- registry.register(makeTestFlow());
445
- const db = mockDb();
446
- db._state.updateRowCount = 1;
447
- let firstHeartbeatOk = false;
448
- let heartbeatError;
449
- const stepDeps = {
450
- executeCapability: vi.fn().mockImplementation(async (_name, stepCtx) => {
451
- await stepCtx.flows.heartbeat();
452
- firstHeartbeatOk = true;
453
- db._state.updateRowCount = 0; // simulate another worker stealing the lease
454
- try {
455
- await stepCtx.flows.heartbeat();
456
- }
457
- catch (err) {
458
- heartbeatError = err;
459
- }
460
- return { success: true, data: {} };
461
- }),
462
- evaluateCondition: vi.fn().mockReturnValue(true),
463
- };
464
- const engine = createFlowEngine({
465
- db,
466
- registry,
467
- stepDeps,
468
- workerId: 'worker-x',
469
- flowHeartbeatIntervalMs: 60_000, // disable auto-heartbeat; manual heartbeat only
470
- });
471
- const exec = await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
472
- await engine.runNext(exec.id, makeCtx());
473
- expect(firstHeartbeatOk).toBe(true);
474
- expect(heartbeatError).toBeInstanceOf(LeaseLostError);
475
- });
476
- });
477
- describe('FlowEngine — cooperative cancellation (ctx.signal)', () => {
478
- it('exposes an un-aborted ctx.signal to step handlers', async () => {
479
- const registry = new FlowRegistry();
480
- registry.register(makeTestFlow());
481
- const db = mockDb();
482
- let capturedSignal;
483
- const stepDeps = {
484
- executeCapability: vi.fn().mockImplementation(async (_name, stepCtx) => {
485
- capturedSignal = stepCtx.signal;
486
- return { success: true, data: {} };
487
- }),
488
- evaluateCondition: vi.fn().mockReturnValue(true),
489
- };
490
- const engine = createFlowEngine({
491
- db,
492
- registry,
493
- stepDeps,
494
- workerId: 'worker-sig-1',
495
- flowHeartbeatIntervalMs: 60_000,
496
- });
497
- const exec = await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
498
- await engine.runNext(exec.id, makeCtx());
499
- expect(capturedSignal).toBeInstanceOf(AbortSignal);
500
- // Step completed normally; signal.aborted before return should be false.
501
- // (After runNext finishes the finally-block aborts it to wake detached tasks,
502
- // but the assertion is about the state the handler observed during execution.)
503
- });
504
- it('cancel() aborts ctx.signal for the in-flight step in the same process', async () => {
505
- const registry = new FlowRegistry();
506
- registry.register(makeTestFlow());
507
- const db = mockDb();
508
- db._state.updateRowCount = 1;
509
- let stepSignalAborted = false;
510
- let stepSignalReason;
511
- const stepDeps = {
512
- executeCapability: vi.fn().mockImplementation(async (_name, stepCtx) => {
513
- // Wait for the signal to abort — simulates a long-running AI call.
514
- await new Promise((resolve) => {
515
- if (stepCtx.signal.aborted) {
516
- stepSignalAborted = true;
517
- stepSignalReason = stepCtx.signal.reason;
518
- resolve();
519
- return;
520
- }
521
- stepCtx.signal.addEventListener('abort', () => {
522
- stepSignalAborted = true;
523
- stepSignalReason = stepCtx.signal.reason;
524
- resolve();
525
- }, { once: true });
526
- });
527
- return { success: true, data: {} };
528
- }),
529
- evaluateCondition: vi.fn().mockReturnValue(true),
530
- };
531
- const engine = createFlowEngine({
532
- db,
533
- registry,
534
- stepDeps,
535
- workerId: 'worker-cancel-1',
536
- flowHeartbeatIntervalMs: 60_000,
537
- });
538
- const exec = await engine.start('order-processing', { orderId: 'x' }, makeAuth());
539
- // Kick off runNext, then cancel while the step is mid-flight.
540
- const running = engine.runNext(exec.id, makeCtx());
541
- await new Promise((r) => setTimeout(r, 20));
542
- await engine.cancel(exec.id);
543
- await running;
544
- expect(stepSignalAborted).toBe(true);
545
- // reason is a FlowCancelledError
546
- expect(stepSignalReason?.name).toBe('FlowCancelledError');
547
- });
548
- it('heartbeat-driven lease loss aborts ctx.signal with LeaseLostError', async () => {
549
- const registry = new FlowRegistry();
550
- registry.register(makeTestFlow());
551
- const db = mockDb();
552
- db._state.updateRowCount = 0; // every lease-extend reports 0 rows affected
553
- let abortReason;
554
- const stepDeps = {
555
- executeCapability: vi.fn().mockImplementation(async (_name, stepCtx) => {
556
- await new Promise((resolve) => {
557
- stepCtx.signal.addEventListener('abort', () => {
558
- abortReason = stepCtx.signal.reason;
559
- resolve();
560
- }, { once: true });
561
- });
562
- return { success: true, data: {} };
563
- }),
564
- evaluateCondition: vi.fn().mockReturnValue(true),
565
- };
566
- const engine = createFlowEngine({
567
- db,
568
- registry,
569
- stepDeps,
570
- workerId: 'worker-lease-1',
571
- flowHeartbeatIntervalMs: 5,
572
- flowLeaseDurationMs: 60_000,
573
- });
574
- const exec = await engine.start('order-processing', { orderId: 'x' }, makeAuth());
575
- await expect(engine.runNext(exec.id, makeCtx())).rejects.toBeInstanceOf(LeaseLostError);
576
- expect(abortReason?.name).toBe('LeaseLostError');
577
- });
578
- it('threads ctx.signal into ctx.ai.generate by default', async () => {
579
- const registry = new FlowRegistry();
580
- registry.register(makeTestFlow());
581
- const db = mockDb();
582
- const generate = vi.fn().mockResolvedValue({ ok: true });
583
- const ctxWithAi = makeCtx({
584
- ai: {
585
- generate,
586
- generateWithUsage: vi.fn(),
587
- streamGenerate: vi.fn(),
588
- extract: vi.fn(),
589
- classify: vi.fn(),
590
- retrieve: vi.fn(),
591
- },
592
- });
593
- const stepDeps = {
594
- executeCapability: vi.fn().mockImplementation(async (_name, stepCtx) => {
595
- // Capability does NOT pass a signal — engine must default to ctx.signal.
596
- await stepCtx.ai.generate({ prompt: 'p', input: {} });
597
- return { success: true, data: {} };
598
- }),
599
- evaluateCondition: vi.fn().mockReturnValue(true),
600
- };
601
- const engine = createFlowEngine({
602
- db,
603
- registry,
604
- stepDeps,
605
- workerId: 'worker-ai-1',
606
- flowHeartbeatIntervalMs: 60_000,
607
- });
608
- const exec = await engine.start('order-processing', { orderId: 'x' }, makeAuth());
609
- await engine.runNext(exec.id, ctxWithAi);
610
- expect(generate).toHaveBeenCalledTimes(1);
611
- const firstCall = generate.mock.calls[0];
612
- expect(firstCall).toBeDefined();
613
- const calledWith = firstCall?.[0];
614
- expect(calledWith.signal).toBeInstanceOf(AbortSignal);
615
- });
616
- describe('markFailedFromRunner (zombie recovery)', () => {
617
- it('finalizes the row as failed with lease cleared after LeaseLostError from runNext', async () => {
618
- const registry = new FlowRegistry();
619
- registry.register(makeTestFlow());
620
- const db = mockDb();
621
- db._state.updateRowCount = 0; // every update says 0 rows → heartbeat loses lease
622
- const stepDeps = {
623
- executeCapability: vi.fn().mockImplementation(async () => {
624
- await new Promise((r) => setTimeout(r, 40));
625
- return { success: true, data: {} };
626
- }),
627
- evaluateCondition: vi.fn().mockReturnValue(true),
628
- };
629
- const engine = createFlowEngine({
630
- db,
631
- registry,
632
- stepDeps,
633
- workerId: 'worker-recover-1',
634
- flowHeartbeatIntervalMs: 5,
635
- flowLeaseDurationMs: 60_000,
636
- });
637
- const exec = await engine.start('order-processing', { orderId: 'abc' }, makeAuth());
638
- let caught;
639
- try {
640
- await engine.runNext(exec.id, makeCtx());
641
- }
642
- catch (err) {
643
- caught = err;
644
- }
645
- expect(caught).toBeInstanceOf(LeaseLostError);
646
- // Now simulate the bootstrap runner finalizing. Flip the mock back to
647
- // "updates succeed" so the finalizer's UPDATE reports 1 row affected.
648
- db._updates.length = 0;
649
- db._state.updateRowCount = 1;
650
- const finalized = await engine.markFailedFromRunner(exec.id, caught);
651
- expect(finalized).toBe(true);
652
- const finalize = db._updates.at(-1);
653
- expect(finalize).toMatchObject({
654
- status: FlowStatus.Failed,
655
- leaseOwner: null,
656
- leaseExpiresAt: null,
657
- });
658
- expect(finalize.lastError).toMatch(/Lease lost/);
659
- expect(finalize.completedAt).toBeInstanceOf(Date);
660
- });
661
- it('is a no-op when the row is already in a terminal state', async () => {
662
- const registry = new FlowRegistry();
663
- registry.register(makeTestFlow());
664
- const db = mockDb();
665
- const engine = createFlowEngine({
666
- db,
667
- registry,
668
- stepDeps: makeStepDeps(),
669
- workerId: 'worker-recover-2',
670
- });
671
- const exec = await engine.start('order-processing', { orderId: 'x' }, makeAuth());
672
- // Simulate "row already finalized" — UPDATE with status-set guard matches 0 rows.
673
- db._state.updateRowCount = 0;
674
- db._updates.length = 0;
675
- const finalized = await engine.markFailedFromRunner(exec.id, new Error('stale'));
676
- expect(finalized).toBe(false);
677
- // The finalizer did attempt the UPDATE, but the status guard is what
678
- // makes it a no-op against terminal rows — we only assert the return
679
- // value here since the mock filters by updateRowCount, not SQL.
680
- });
681
- it('does not emit flow.runner.finalized audit when the row was already terminal', async () => {
682
- const registry = new FlowRegistry();
683
- registry.register(makeTestFlow());
684
- const db = mockDb();
685
- const audits = [];
686
- const audit = {
687
- record: vi.fn().mockImplementation(async (action) => {
688
- audits.push({ action });
689
- }),
690
- };
691
- const engine = createFlowEngine({
692
- db,
693
- registry,
694
- stepDeps: makeStepDeps(),
695
- workerId: 'worker-recover-3',
696
- audit,
697
- });
698
- const exec = await engine.start('order-processing', { orderId: 'x' }, makeAuth());
699
- db._state.updateRowCount = 0;
700
- await engine.markFailedFromRunner(exec.id, new Error('stale'));
701
- expect(audits.some((a) => a.action === 'flow.runner.finalized')).toBe(false);
702
- });
703
- it('uses "Unknown error" when the thrown value is neither Error nor string', async () => {
704
- const registry = new FlowRegistry();
705
- registry.register(makeTestFlow());
706
- const db = mockDb();
707
- const engine = createFlowEngine({
708
- db,
709
- registry,
710
- stepDeps: makeStepDeps(),
711
- workerId: 'worker-recover-4',
712
- });
713
- const exec = await engine.start('order-processing', { orderId: 'x' }, makeAuth());
714
- db._updates.length = 0;
715
- await engine.markFailedFromRunner(exec.id, { weird: true });
716
- const finalize = db._updates.at(-1);
717
- expect(finalize.lastError).toBe('Unknown error');
718
- });
719
- });
720
- });
721
- // Regression: in production, a flow worker's baseCtx is bound to `systemAuth`
722
- // (userId: 'system-flow-runner', no tenantId). If `ctx.flows.start(...)` from
723
- // inside a flow step inherits that auth, the nested flow row stores
724
- // `tenantId: null`, and any tenantScoped capability inside the nested flow
725
- // rejects with "Tenant context required". The engine must rebind `start` in
726
- // the flow-step ctx so nested flows inherit the calling flow's auth instead.
727
- describe('FlowEngine — flow-step ctx.flows.start propagates flowAuth', () => {
728
- it('uses the executing flow row auth, not the base worker auth, when starting nested flows', async () => {
729
- const registry = new FlowRegistry();
730
- registry.register(defineFlow({
731
- name: 'outer',
732
- domain: 'test',
733
- input: z.object({}),
734
- steps: [{ name: 'kickoff', type: FlowStepType.Capability }],
735
- }));
736
- registry.register(defineFlow({
737
- name: 'inner',
738
- domain: 'test',
739
- input: z.object({ foo: z.string() }),
740
- steps: [{ name: 'inner-step', type: FlowStepType.Capability }],
741
- }));
742
- // Outer step captures ctx and calls ctx.flows.start('inner', ...). We
743
- // assert what auth reaches the recursive engine.start call.
744
- let capturedCtx = null;
745
- const stepDeps = {
746
- executeCapability: vi.fn().mockImplementation(async (_name, ctx) => {
747
- capturedCtx = ctx;
748
- await ctx.flows.start('inner', { foo: 'bar' });
749
- return { success: true, data: {} };
750
- }),
751
- evaluateCondition: vi.fn().mockReturnValue(true),
752
- };
753
- const db = mockDb();
754
- const engine = createFlowEngine({ db, registry, stepDeps });
755
- // Caller (the human/HTTP) is tenant t-A.
756
- const callerAuth = {
757
- userId: 'real-user',
758
- tenantId: 't-A',
759
- roles: ['user'],
760
- scopes: [],
761
- provider: 'http',
762
- };
763
- const exec = await engine.start('outer', {}, callerAuth);
764
- // The worker's baseCtx — `systemAuth`, NO tenantId. This is the exact
765
- // shape the worker's bootstrap creates and the regression we're guarding.
766
- const workerBaseCtx = makeCtx({
767
- auth: {
768
- userId: 'system-flow-runner',
769
- roles: ['system'],
770
- scopes: [],
771
- provider: 'worker',
772
- },
773
- });
774
- const row = db._rows.get(exec.id);
775
- db.select = vi.fn().mockReturnValue({
776
- from: vi.fn().mockReturnValue({
777
- where: vi.fn().mockReturnValue({
778
- limit: vi.fn().mockResolvedValue([row]),
779
- }),
780
- }),
781
- });
782
- await engine.runNext(exec.id, workerBaseCtx);
783
- // Two inserts: outer (from engine.start above), inner (from ctx.flows.start
784
- // inside the step). The inner row must inherit the OUTER flow's tenantId
785
- // and actor, not the worker's systemAuth.
786
- expect(db._inserts).toHaveLength(2);
787
- const innerRow = db._inserts.find((r) => r.flowName === 'inner');
788
- expect(innerRow).toBeDefined();
789
- expect(innerRow.tenantId).toBe('t-A');
790
- expect(innerRow.actor).toBe('real-user');
791
- // The captured ctx given to the step also has flowAuth (sanity).
792
- expect(capturedCtx?.auth?.tenantId).toBe('t-A');
793
- expect(capturedCtx?.auth?.userId).toBe('real-user');
794
- expect(capturedCtx?.auth?.internal).toBe(true);
795
- });
796
- });
797
- //# sourceMappingURL=flow-engine.test.js.map