@plumbus/core 0.3.3 → 0.4.1

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 (593) 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/ai/security.d.ts.map +1 -1
  15. package/dist/ai/security.js +14 -1
  16. package/dist/ai/security.js.map +1 -1
  17. package/dist/api/route-generator.d.ts.map +1 -1
  18. package/dist/api/route-generator.js +57 -11
  19. package/dist/api/route-generator.js.map +1 -1
  20. package/dist/auth/adapter.d.ts +0 -4
  21. package/dist/auth/adapter.d.ts.map +1 -1
  22. package/dist/auth/adapter.js +4 -0
  23. package/dist/auth/adapter.js.map +1 -1
  24. package/dist/auth/saml-adapter.d.ts.map +1 -1
  25. package/dist/auth/saml-adapter.js +73 -120
  26. package/dist/auth/saml-adapter.js.map +1 -1
  27. package/dist/auth/scim.d.ts.map +1 -1
  28. package/dist/auth/scim.js +6 -1
  29. package/dist/auth/scim.js.map +1 -1
  30. package/dist/cli/cli.d.ts.map +1 -1
  31. package/dist/cli/cli.js +3 -1
  32. package/dist/cli/cli.js.map +1 -1
  33. package/dist/cli/commands/browser-extension.d.ts +10 -0
  34. package/dist/cli/commands/browser-extension.d.ts.map +1 -0
  35. package/dist/cli/commands/browser-extension.js +235 -0
  36. package/dist/cli/commands/browser-extension.js.map +1 -0
  37. package/dist/cli/commands/dev.d.ts +4 -1
  38. package/dist/cli/commands/dev.d.ts.map +1 -1
  39. package/dist/cli/commands/dev.js +21 -30
  40. package/dist/cli/commands/dev.js.map +1 -1
  41. package/dist/cli/commands/doctor.d.ts +6 -0
  42. package/dist/cli/commands/doctor.d.ts.map +1 -1
  43. package/dist/cli/commands/doctor.js +146 -2
  44. package/dist/cli/commands/doctor.js.map +1 -1
  45. package/dist/cli/commands/generate.d.ts.map +1 -1
  46. package/dist/cli/commands/generate.js +18 -0
  47. package/dist/cli/commands/generate.js.map +1 -1
  48. package/dist/cli/commands/index.d.ts +2 -0
  49. package/dist/cli/commands/index.d.ts.map +1 -1
  50. package/dist/cli/commands/index.js +2 -0
  51. package/dist/cli/commands/index.js.map +1 -1
  52. package/dist/cli/commands/init.d.ts +1 -1
  53. package/dist/cli/commands/init.d.ts.map +1 -1
  54. package/dist/cli/commands/init.js +122 -3
  55. package/dist/cli/commands/init.js.map +1 -1
  56. package/dist/cli/commands/mcp.d.ts +9 -0
  57. package/dist/cli/commands/mcp.d.ts.map +1 -0
  58. package/dist/cli/commands/mcp.js +125 -0
  59. package/dist/cli/commands/mcp.js.map +1 -0
  60. package/dist/cli/commands/migrate.d.ts.map +1 -1
  61. package/dist/cli/commands/migrate.js +2 -1
  62. package/dist/cli/commands/migrate.js.map +1 -1
  63. package/dist/cli/commands/start.d.ts +4 -1
  64. package/dist/cli/commands/start.d.ts.map +1 -1
  65. package/dist/cli/commands/start.js +20 -29
  66. package/dist/cli/commands/start.js.map +1 -1
  67. package/dist/cli/commands/translation.d.ts.map +1 -1
  68. package/dist/cli/commands/translation.js +22 -10
  69. package/dist/cli/commands/translation.js.map +1 -1
  70. package/dist/cli/mcp-serve-context.d.ts +13 -0
  71. package/dist/cli/mcp-serve-context.d.ts.map +1 -0
  72. package/dist/cli/mcp-serve-context.js +119 -0
  73. package/dist/cli/mcp-serve-context.js.map +1 -0
  74. package/dist/cli/migrate-snapshot-schema.d.ts +15 -0
  75. package/dist/cli/migrate-snapshot-schema.d.ts.map +1 -0
  76. package/dist/cli/migrate-snapshot-schema.js +23 -0
  77. package/dist/cli/migrate-snapshot-schema.js.map +1 -0
  78. package/dist/cli/project-root.d.ts +9 -0
  79. package/dist/cli/project-root.d.ts.map +1 -0
  80. package/dist/cli/project-root.js +41 -0
  81. package/dist/cli/project-root.js.map +1 -0
  82. package/dist/cli/scaffold-write.d.ts +17 -0
  83. package/dist/cli/scaffold-write.d.ts.map +1 -0
  84. package/dist/cli/scaffold-write.js +40 -0
  85. package/dist/cli/scaffold-write.js.map +1 -0
  86. package/dist/cli/templates/resources.d.ts.map +1 -1
  87. package/dist/cli/templates/resources.js +7 -1
  88. package/dist/cli/templates/resources.js.map +1 -1
  89. package/dist/cli/utils.d.ts +2 -0
  90. package/dist/cli/utils.d.ts.map +1 -1
  91. package/dist/cli/utils.js +14 -0
  92. package/dist/cli/utils.js.map +1 -1
  93. package/dist/config/loader.d.ts +1 -1
  94. package/dist/config/loader.d.ts.map +1 -1
  95. package/dist/config/loader.js +46 -27
  96. package/dist/config/loader.js.map +1 -1
  97. package/dist/data/connection.d.ts +16 -0
  98. package/dist/data/connection.d.ts.map +1 -0
  99. package/dist/data/connection.js +27 -0
  100. package/dist/data/connection.js.map +1 -0
  101. package/dist/data/index.d.ts +1 -0
  102. package/dist/data/index.d.ts.map +1 -1
  103. package/dist/data/index.js +1 -0
  104. package/dist/data/index.js.map +1 -1
  105. package/dist/data/migration.d.ts.map +1 -1
  106. package/dist/data/migration.js +24 -0
  107. package/dist/data/migration.js.map +1 -1
  108. package/dist/data/repository.d.ts.map +1 -1
  109. package/dist/data/repository.js +32 -9
  110. package/dist/data/repository.js.map +1 -1
  111. package/dist/define/defineCapability.d.ts +4 -2
  112. package/dist/define/defineCapability.d.ts.map +1 -1
  113. package/dist/define/defineCapability.js +68 -8
  114. package/dist/define/defineCapability.js.map +1 -1
  115. package/dist/define/defineEntity.d.ts.map +1 -1
  116. package/dist/define/defineEntity.js +8 -4
  117. package/dist/define/defineEntity.js.map +1 -1
  118. package/dist/define/defineEvent.d.ts.map +1 -1
  119. package/dist/define/defineEvent.js +7 -3
  120. package/dist/define/defineEvent.js.map +1 -1
  121. package/dist/define/defineFlow.d.ts.map +1 -1
  122. package/dist/define/defineFlow.js +11 -5
  123. package/dist/define/defineFlow.js.map +1 -1
  124. package/dist/define/definePrompt.d.ts.map +1 -1
  125. package/dist/define/definePrompt.js +11 -5
  126. package/dist/define/definePrompt.js.map +1 -1
  127. package/dist/define/defineTranslation.d.ts.map +1 -1
  128. package/dist/define/defineTranslation.js +12 -10
  129. package/dist/define/defineTranslation.js.map +1 -1
  130. package/dist/define/validation-error.d.ts +2 -0
  131. package/dist/define/validation-error.d.ts.map +1 -0
  132. package/dist/define/validation-error.js +9 -0
  133. package/dist/define/validation-error.js.map +1 -0
  134. package/dist/errors/hints.d.ts +13 -0
  135. package/dist/errors/hints.d.ts.map +1 -0
  136. package/dist/errors/hints.js +15 -0
  137. package/dist/errors/hints.js.map +1 -0
  138. package/dist/errors/hook-log.d.ts +3 -0
  139. package/dist/errors/hook-log.d.ts.map +1 -0
  140. package/dist/errors/hook-log.js +6 -0
  141. package/dist/errors/hook-log.js.map +1 -0
  142. package/dist/errors/http.d.ts +19 -0
  143. package/dist/errors/http.d.ts.map +1 -1
  144. package/dist/errors/http.js +32 -2
  145. package/dist/errors/http.js.map +1 -1
  146. package/dist/errors/safe-metadata.d.ts +5 -0
  147. package/dist/errors/safe-metadata.d.ts.map +1 -0
  148. package/dist/errors/safe-metadata.js +24 -0
  149. package/dist/errors/safe-metadata.js.map +1 -0
  150. package/dist/execution/auth-roles.d.ts +6 -0
  151. package/dist/execution/auth-roles.d.ts.map +1 -0
  152. package/dist/execution/auth-roles.js +12 -0
  153. package/dist/execution/auth-roles.js.map +1 -0
  154. package/dist/execution/authorization.d.ts.map +1 -1
  155. package/dist/execution/authorization.js +3 -5
  156. package/dist/execution/authorization.js.map +1 -1
  157. package/dist/execution/context-factory.d.ts +2 -17
  158. package/dist/execution/context-factory.d.ts.map +1 -1
  159. package/dist/execution/context-factory.js +1 -0
  160. package/dist/execution/context-factory.js.map +1 -1
  161. package/dist/flows/engine.js +1 -1
  162. package/dist/flows/engine.js.map +1 -1
  163. package/dist/flows/evaluate-condition.d.ts +19 -0
  164. package/dist/flows/evaluate-condition.d.ts.map +1 -0
  165. package/dist/flows/evaluate-condition.js +276 -0
  166. package/dist/flows/evaluate-condition.js.map +1 -0
  167. package/dist/flows/index.d.ts +1 -0
  168. package/dist/flows/index.d.ts.map +1 -1
  169. package/dist/flows/index.js +2 -0
  170. package/dist/flows/index.js.map +1 -1
  171. package/dist/flows/step-executor.d.ts.map +1 -1
  172. package/dist/flows/step-executor.js +15 -7
  173. package/dist/flows/step-executor.js.map +1 -1
  174. package/dist/governance/rules/architecture.d.ts.map +1 -1
  175. package/dist/governance/rules/architecture.js +2 -0
  176. package/dist/governance/rules/architecture.js.map +1 -1
  177. package/dist/governance/rules/index.d.ts +1 -0
  178. package/dist/governance/rules/index.d.ts.map +1 -1
  179. package/dist/governance/rules/index.js +1 -0
  180. package/dist/governance/rules/index.js.map +1 -1
  181. package/dist/governance/rules/mcp.d.ts +5 -0
  182. package/dist/governance/rules/mcp.d.ts.map +1 -0
  183. package/dist/governance/rules/mcp.js +34 -0
  184. package/dist/governance/rules/mcp.js.map +1 -0
  185. package/dist/index.d.ts +1 -0
  186. package/dist/index.d.ts.map +1 -1
  187. package/dist/index.js +1 -0
  188. package/dist/index.js.map +1 -1
  189. package/dist/mcp/exposure.d.ts +4 -0
  190. package/dist/mcp/exposure.d.ts.map +1 -0
  191. package/dist/mcp/exposure.js +5 -0
  192. package/dist/mcp/exposure.js.map +1 -0
  193. package/dist/mcp/index.d.ts +4 -0
  194. package/dist/mcp/index.d.ts.map +1 -0
  195. package/dist/mcp/index.js +6 -0
  196. package/dist/mcp/index.js.map +1 -0
  197. package/dist/mcp/manifest-generator.d.ts +19 -0
  198. package/dist/mcp/manifest-generator.d.ts.map +1 -0
  199. package/dist/mcp/manifest-generator.js +29 -0
  200. package/dist/mcp/manifest-generator.js.map +1 -0
  201. package/dist/mcp/skill-generator.d.ts +4 -0
  202. package/dist/mcp/skill-generator.d.ts.map +1 -0
  203. package/dist/mcp/skill-generator.js +59 -0
  204. package/dist/mcp/skill-generator.js.map +1 -0
  205. package/dist/schema/zod-input-to-json-schema.d.ts +4 -0
  206. package/dist/schema/zod-input-to-json-schema.d.ts.map +1 -0
  207. package/dist/schema/zod-input-to-json-schema.js +6 -0
  208. package/dist/schema/zod-input-to-json-schema.js.map +1 -0
  209. package/dist/server/bootstrap.d.ts.map +1 -1
  210. package/dist/server/bootstrap.js +8 -3
  211. package/dist/server/bootstrap.js.map +1 -1
  212. package/dist/testing/context.d.ts +2 -0
  213. package/dist/testing/context.d.ts.map +1 -1
  214. package/dist/testing/context.js +1 -0
  215. package/dist/testing/context.js.map +1 -1
  216. package/dist/testing/e2e.js +1 -1
  217. package/dist/testing/e2e.js.map +1 -1
  218. package/dist/types/capability.d.ts +13 -0
  219. package/dist/types/capability.d.ts.map +1 -1
  220. package/dist/types/config.d.ts +9 -0
  221. package/dist/types/config.d.ts.map +1 -1
  222. package/dist/types/context.d.ts +31 -0
  223. package/dist/types/context.d.ts.map +1 -1
  224. package/dist/types/deep-freeze.d.ts +6 -0
  225. package/dist/types/deep-freeze.d.ts.map +1 -0
  226. package/dist/types/deep-freeze.js +38 -0
  227. package/dist/types/deep-freeze.js.map +1 -0
  228. package/dist/types/enums.d.ts +5 -0
  229. package/dist/types/enums.d.ts.map +1 -1
  230. package/dist/types/enums.js +5 -0
  231. package/dist/types/enums.js.map +1 -1
  232. package/dist/types/index.d.ts +2 -2
  233. package/dist/types/index.d.ts.map +1 -1
  234. package/dist/types/index.js.map +1 -1
  235. package/dist/types/security.d.ts +3 -1
  236. package/dist/types/security.d.ts.map +1 -1
  237. package/instructions/capabilities.md +36 -0
  238. package/instructions/cli.md +44 -0
  239. package/instructions/framework.md +20 -4
  240. package/instructions/mcp.md +20 -0
  241. package/package.json +21 -2
  242. package/dist/ai/__tests__/ai-service.test.d.ts +0 -2
  243. package/dist/ai/__tests__/ai-service.test.d.ts.map +0 -1
  244. package/dist/ai/__tests__/ai-service.test.js +0 -1078
  245. package/dist/ai/__tests__/ai-service.test.js.map +0 -1
  246. package/dist/ai/__tests__/chunking.test.d.ts +0 -2
  247. package/dist/ai/__tests__/chunking.test.d.ts.map +0 -1
  248. package/dist/ai/__tests__/chunking.test.js +0 -78
  249. package/dist/ai/__tests__/chunking.test.js.map +0 -1
  250. package/dist/ai/__tests__/cost-tracker.test.d.ts +0 -2
  251. package/dist/ai/__tests__/cost-tracker.test.d.ts.map +0 -1
  252. package/dist/ai/__tests__/cost-tracker.test.js +0 -201
  253. package/dist/ai/__tests__/cost-tracker.test.js.map +0 -1
  254. package/dist/ai/__tests__/explainability.test.d.ts +0 -2
  255. package/dist/ai/__tests__/explainability.test.d.ts.map +0 -1
  256. package/dist/ai/__tests__/explainability.test.js +0 -100
  257. package/dist/ai/__tests__/explainability.test.js.map +0 -1
  258. package/dist/ai/__tests__/model-pricing.test.d.ts +0 -2
  259. package/dist/ai/__tests__/model-pricing.test.d.ts.map +0 -1
  260. package/dist/ai/__tests__/model-pricing.test.js +0 -156
  261. package/dist/ai/__tests__/model-pricing.test.js.map +0 -1
  262. package/dist/ai/__tests__/prompt-registry.test.d.ts +0 -2
  263. package/dist/ai/__tests__/prompt-registry.test.d.ts.map +0 -1
  264. package/dist/ai/__tests__/prompt-registry.test.js +0 -56
  265. package/dist/ai/__tests__/prompt-registry.test.js.map +0 -1
  266. package/dist/ai/__tests__/provider.test.d.ts +0 -3
  267. package/dist/ai/__tests__/provider.test.d.ts.map +0 -1
  268. package/dist/ai/__tests__/provider.test.js +0 -979
  269. package/dist/ai/__tests__/provider.test.js.map +0 -1
  270. package/dist/ai/__tests__/rag-pipeline.test.d.ts +0 -2
  271. package/dist/ai/__tests__/rag-pipeline.test.d.ts.map +0 -1
  272. package/dist/ai/__tests__/rag-pipeline.test.js +0 -174
  273. package/dist/ai/__tests__/rag-pipeline.test.js.map +0 -1
  274. package/dist/ai/__tests__/security.test.d.ts +0 -2
  275. package/dist/ai/__tests__/security.test.d.ts.map +0 -1
  276. package/dist/ai/__tests__/security.test.js +0 -89
  277. package/dist/ai/__tests__/security.test.js.map +0 -1
  278. package/dist/ai/__tests__/usage-client.test.d.ts +0 -2
  279. package/dist/ai/__tests__/usage-client.test.d.ts.map +0 -1
  280. package/dist/ai/__tests__/usage-client.test.js +0 -120
  281. package/dist/ai/__tests__/usage-client.test.js.map +0 -1
  282. package/dist/ai/__tests__/validation.test.d.ts +0 -2
  283. package/dist/ai/__tests__/validation.test.d.ts.map +0 -1
  284. package/dist/ai/__tests__/validation.test.js +0 -384
  285. package/dist/ai/__tests__/validation.test.js.map +0 -1
  286. package/dist/ai/__tests__/zod-to-provider-schema.test.d.ts +0 -2
  287. package/dist/ai/__tests__/zod-to-provider-schema.test.d.ts.map +0 -1
  288. package/dist/ai/__tests__/zod-to-provider-schema.test.js +0 -60
  289. package/dist/ai/__tests__/zod-to-provider-schema.test.js.map +0 -1
  290. package/dist/api/__tests__/route-generator.test.d.ts +0 -2
  291. package/dist/api/__tests__/route-generator.test.d.ts.map +0 -1
  292. package/dist/api/__tests__/route-generator.test.js +0 -216
  293. package/dist/api/__tests__/route-generator.test.js.map +0 -1
  294. package/dist/audit/__tests__/service.test.d.ts +0 -2
  295. package/dist/audit/__tests__/service.test.d.ts.map +0 -1
  296. package/dist/audit/__tests__/service.test.js +0 -97
  297. package/dist/audit/__tests__/service.test.js.map +0 -1
  298. package/dist/auth/__tests__/adapter.test.d.ts +0 -2
  299. package/dist/auth/__tests__/adapter.test.d.ts.map +0 -1
  300. package/dist/auth/__tests__/adapter.test.js +0 -218
  301. package/dist/auth/__tests__/adapter.test.js.map +0 -1
  302. package/dist/auth/__tests__/oidc-adapter.test.d.ts +0 -2
  303. package/dist/auth/__tests__/oidc-adapter.test.d.ts.map +0 -1
  304. package/dist/auth/__tests__/oidc-adapter.test.js +0 -232
  305. package/dist/auth/__tests__/oidc-adapter.test.js.map +0 -1
  306. package/dist/auth/__tests__/password.test.d.ts +0 -2
  307. package/dist/auth/__tests__/password.test.d.ts.map +0 -1
  308. package/dist/auth/__tests__/password.test.js +0 -30
  309. package/dist/auth/__tests__/password.test.js.map +0 -1
  310. package/dist/auth/__tests__/saml-adapter.test.d.ts +0 -2
  311. package/dist/auth/__tests__/saml-adapter.test.d.ts.map +0 -1
  312. package/dist/auth/__tests__/saml-adapter.test.js +0 -188
  313. package/dist/auth/__tests__/saml-adapter.test.js.map +0 -1
  314. package/dist/auth/__tests__/scim.test.d.ts +0 -2
  315. package/dist/auth/__tests__/scim.test.d.ts.map +0 -1
  316. package/dist/auth/__tests__/scim.test.js +0 -306
  317. package/dist/auth/__tests__/scim.test.js.map +0 -1
  318. package/dist/cli/__tests__/agent.test.d.ts +0 -2
  319. package/dist/cli/__tests__/agent.test.d.ts.map +0 -1
  320. package/dist/cli/__tests__/agent.test.js +0 -63
  321. package/dist/cli/__tests__/agent.test.js.map +0 -1
  322. package/dist/cli/__tests__/certify.test.d.ts +0 -2
  323. package/dist/cli/__tests__/certify.test.d.ts.map +0 -1
  324. package/dist/cli/__tests__/certify.test.js +0 -97
  325. package/dist/cli/__tests__/certify.test.js.map +0 -1
  326. package/dist/cli/__tests__/cli.test.d.ts +0 -2
  327. package/dist/cli/__tests__/cli.test.d.ts.map +0 -1
  328. package/dist/cli/__tests__/cli.test.js +0 -123
  329. package/dist/cli/__tests__/cli.test.js.map +0 -1
  330. package/dist/cli/__tests__/create.test.d.ts +0 -2
  331. package/dist/cli/__tests__/create.test.d.ts.map +0 -1
  332. package/dist/cli/__tests__/create.test.js +0 -183
  333. package/dist/cli/__tests__/create.test.js.map +0 -1
  334. package/dist/cli/__tests__/dev.test.d.ts +0 -2
  335. package/dist/cli/__tests__/dev.test.d.ts.map +0 -1
  336. package/dist/cli/__tests__/dev.test.js +0 -132
  337. package/dist/cli/__tests__/dev.test.js.map +0 -1
  338. package/dist/cli/__tests__/discover.test.d.ts +0 -2
  339. package/dist/cli/__tests__/discover.test.d.ts.map +0 -1
  340. package/dist/cli/__tests__/discover.test.js +0 -48
  341. package/dist/cli/__tests__/discover.test.js.map +0 -1
  342. package/dist/cli/__tests__/doctor.test.d.ts +0 -2
  343. package/dist/cli/__tests__/doctor.test.d.ts.map +0 -1
  344. package/dist/cli/__tests__/doctor.test.js +0 -172
  345. package/dist/cli/__tests__/doctor.test.js.map +0 -1
  346. package/dist/cli/__tests__/generate.test.d.ts +0 -2
  347. package/dist/cli/__tests__/generate.test.d.ts.map +0 -1
  348. package/dist/cli/__tests__/generate.test.js +0 -478
  349. package/dist/cli/__tests__/generate.test.js.map +0 -1
  350. package/dist/cli/__tests__/init.test.d.ts +0 -2
  351. package/dist/cli/__tests__/init.test.d.ts.map +0 -1
  352. package/dist/cli/__tests__/init.test.js +0 -236
  353. package/dist/cli/__tests__/init.test.js.map +0 -1
  354. package/dist/cli/__tests__/migrate.test.d.ts +0 -2
  355. package/dist/cli/__tests__/migrate.test.d.ts.map +0 -1
  356. package/dist/cli/__tests__/migrate.test.js +0 -442
  357. package/dist/cli/__tests__/migrate.test.js.map +0 -1
  358. package/dist/cli/__tests__/start.test.d.ts +0 -2
  359. package/dist/cli/__tests__/start.test.d.ts.map +0 -1
  360. package/dist/cli/__tests__/start.test.js +0 -91
  361. package/dist/cli/__tests__/start.test.js.map +0 -1
  362. package/dist/cli/__tests__/templates.test.d.ts +0 -2
  363. package/dist/cli/__tests__/templates.test.d.ts.map +0 -1
  364. package/dist/cli/__tests__/templates.test.js +0 -49
  365. package/dist/cli/__tests__/templates.test.js.map +0 -1
  366. package/dist/cli/__tests__/test.test.d.ts +0 -2
  367. package/dist/cli/__tests__/test.test.d.ts.map +0 -1
  368. package/dist/cli/__tests__/test.test.js +0 -40
  369. package/dist/cli/__tests__/test.test.js.map +0 -1
  370. package/dist/cli/__tests__/ui.test.d.ts +0 -2
  371. package/dist/cli/__tests__/ui.test.d.ts.map +0 -1
  372. package/dist/cli/__tests__/ui.test.js +0 -76
  373. package/dist/cli/__tests__/ui.test.js.map +0 -1
  374. package/dist/cli/__tests__/upgrade.test.d.ts +0 -2
  375. package/dist/cli/__tests__/upgrade.test.d.ts.map +0 -1
  376. package/dist/cli/__tests__/upgrade.test.js +0 -20
  377. package/dist/cli/__tests__/upgrade.test.js.map +0 -1
  378. package/dist/cli/__tests__/utils.test.d.ts +0 -2
  379. package/dist/cli/__tests__/utils.test.d.ts.map +0 -1
  380. package/dist/cli/__tests__/utils.test.js +0 -255
  381. package/dist/cli/__tests__/utils.test.js.map +0 -1
  382. package/dist/cli/__tests__/verify.test.d.ts +0 -2
  383. package/dist/cli/__tests__/verify.test.d.ts.map +0 -1
  384. package/dist/cli/__tests__/verify.test.js +0 -138
  385. package/dist/cli/__tests__/verify.test.js.map +0 -1
  386. package/dist/cli/commands/__tests__/commands.test.d.ts +0 -2
  387. package/dist/cli/commands/__tests__/commands.test.d.ts.map +0 -1
  388. package/dist/cli/commands/__tests__/commands.test.js +0 -185
  389. package/dist/cli/commands/__tests__/commands.test.js.map +0 -1
  390. package/dist/config/__tests__/loader.test.d.ts +0 -2
  391. package/dist/config/__tests__/loader.test.d.ts.map +0 -1
  392. package/dist/config/__tests__/loader.test.js +0 -462
  393. package/dist/config/__tests__/loader.test.js.map +0 -1
  394. package/dist/data/__tests__/drift-inspector.test.d.ts +0 -2
  395. package/dist/data/__tests__/drift-inspector.test.d.ts.map +0 -1
  396. package/dist/data/__tests__/drift-inspector.test.js +0 -170
  397. package/dist/data/__tests__/drift-inspector.test.js.map +0 -1
  398. package/dist/data/__tests__/framework-migration-rewriter.test.d.ts +0 -2
  399. package/dist/data/__tests__/framework-migration-rewriter.test.d.ts.map +0 -1
  400. package/dist/data/__tests__/framework-migration-rewriter.test.js +0 -329
  401. package/dist/data/__tests__/framework-migration-rewriter.test.js.map +0 -1
  402. package/dist/data/__tests__/migration.test.d.ts +0 -2
  403. package/dist/data/__tests__/migration.test.d.ts.map +0 -1
  404. package/dist/data/__tests__/migration.test.js +0 -145
  405. package/dist/data/__tests__/migration.test.js.map +0 -1
  406. package/dist/data/__tests__/registry.test.d.ts +0 -2
  407. package/dist/data/__tests__/registry.test.d.ts.map +0 -1
  408. package/dist/data/__tests__/registry.test.js +0 -70
  409. package/dist/data/__tests__/registry.test.js.map +0 -1
  410. package/dist/data/__tests__/repository.test.d.ts +0 -2
  411. package/dist/data/__tests__/repository.test.d.ts.map +0 -1
  412. package/dist/data/__tests__/repository.test.js +0 -559
  413. package/dist/data/__tests__/repository.test.js.map +0 -1
  414. package/dist/data/__tests__/schema-generator.test.d.ts +0 -2
  415. package/dist/data/__tests__/schema-generator.test.d.ts.map +0 -1
  416. package/dist/data/__tests__/schema-generator.test.js +0 -112
  417. package/dist/data/__tests__/schema-generator.test.js.map +0 -1
  418. package/dist/define/__tests__/defineCapability.test.d.ts +0 -2
  419. package/dist/define/__tests__/defineCapability.test.d.ts.map +0 -1
  420. package/dist/define/__tests__/defineCapability.test.js +0 -66
  421. package/dist/define/__tests__/defineCapability.test.js.map +0 -1
  422. package/dist/define/__tests__/defineEntity.test.d.ts +0 -2
  423. package/dist/define/__tests__/defineEntity.test.d.ts.map +0 -1
  424. package/dist/define/__tests__/defineEntity.test.js +0 -50
  425. package/dist/define/__tests__/defineEntity.test.js.map +0 -1
  426. package/dist/define/__tests__/defineEvent.test.d.ts +0 -2
  427. package/dist/define/__tests__/defineEvent.test.d.ts.map +0 -1
  428. package/dist/define/__tests__/defineEvent.test.js +0 -35
  429. package/dist/define/__tests__/defineEvent.test.js.map +0 -1
  430. package/dist/define/__tests__/defineFlow.test.d.ts +0 -2
  431. package/dist/define/__tests__/defineFlow.test.d.ts.map +0 -1
  432. package/dist/define/__tests__/defineFlow.test.js +0 -49
  433. package/dist/define/__tests__/defineFlow.test.js.map +0 -1
  434. package/dist/define/__tests__/definePrompt.test.d.ts +0 -2
  435. package/dist/define/__tests__/definePrompt.test.d.ts.map +0 -1
  436. package/dist/define/__tests__/definePrompt.test.js +0 -77
  437. package/dist/define/__tests__/definePrompt.test.js.map +0 -1
  438. package/dist/define/__tests__/defineTranslation.test.d.ts +0 -2
  439. package/dist/define/__tests__/defineTranslation.test.d.ts.map +0 -1
  440. package/dist/define/__tests__/defineTranslation.test.js +0 -90
  441. package/dist/define/__tests__/defineTranslation.test.js.map +0 -1
  442. package/dist/errors/__tests__/errors.test.d.ts +0 -2
  443. package/dist/errors/__tests__/errors.test.d.ts.map +0 -1
  444. package/dist/errors/__tests__/errors.test.js +0 -70
  445. package/dist/errors/__tests__/errors.test.js.map +0 -1
  446. package/dist/errors/__tests__/http.test.d.ts +0 -2
  447. package/dist/errors/__tests__/http.test.d.ts.map +0 -1
  448. package/dist/errors/__tests__/http.test.js +0 -35
  449. package/dist/errors/__tests__/http.test.js.map +0 -1
  450. package/dist/events/__tests__/consumer-registry.test.d.ts +0 -2
  451. package/dist/events/__tests__/consumer-registry.test.d.ts.map +0 -1
  452. package/dist/events/__tests__/consumer-registry.test.js +0 -68
  453. package/dist/events/__tests__/consumer-registry.test.js.map +0 -1
  454. package/dist/events/__tests__/dispatcher.test.d.ts +0 -2
  455. package/dist/events/__tests__/dispatcher.test.d.ts.map +0 -1
  456. package/dist/events/__tests__/dispatcher.test.js +0 -168
  457. package/dist/events/__tests__/dispatcher.test.js.map +0 -1
  458. package/dist/events/__tests__/event-emitter.test.d.ts +0 -2
  459. package/dist/events/__tests__/event-emitter.test.d.ts.map +0 -1
  460. package/dist/events/__tests__/event-emitter.test.js +0 -172
  461. package/dist/events/__tests__/event-emitter.test.js.map +0 -1
  462. package/dist/events/__tests__/event-registry.test.d.ts +0 -2
  463. package/dist/events/__tests__/event-registry.test.d.ts.map +0 -1
  464. package/dist/events/__tests__/event-registry.test.js +0 -55
  465. package/dist/events/__tests__/event-registry.test.js.map +0 -1
  466. package/dist/events/__tests__/event-worker.test.d.ts +0 -2
  467. package/dist/events/__tests__/event-worker.test.d.ts.map +0 -1
  468. package/dist/events/__tests__/event-worker.test.js +0 -174
  469. package/dist/events/__tests__/event-worker.test.js.map +0 -1
  470. package/dist/events/__tests__/queue.test.d.ts +0 -2
  471. package/dist/events/__tests__/queue.test.d.ts.map +0 -1
  472. package/dist/events/__tests__/queue.test.js +0 -73
  473. package/dist/events/__tests__/queue.test.js.map +0 -1
  474. package/dist/execution/__tests__/authorization.test.d.ts +0 -2
  475. package/dist/execution/__tests__/authorization.test.d.ts.map +0 -1
  476. package/dist/execution/__tests__/authorization.test.js +0 -99
  477. package/dist/execution/__tests__/authorization.test.js.map +0 -1
  478. package/dist/execution/__tests__/capability-executor.test.d.ts +0 -2
  479. package/dist/execution/__tests__/capability-executor.test.d.ts.map +0 -1
  480. package/dist/execution/__tests__/capability-executor.test.js +0 -212
  481. package/dist/execution/__tests__/capability-executor.test.js.map +0 -1
  482. package/dist/execution/__tests__/capability-registry.test.d.ts +0 -2
  483. package/dist/execution/__tests__/capability-registry.test.d.ts.map +0 -1
  484. package/dist/execution/__tests__/capability-registry.test.js +0 -50
  485. package/dist/execution/__tests__/capability-registry.test.js.map +0 -1
  486. package/dist/execution/__tests__/context-factory.test.d.ts +0 -2
  487. package/dist/execution/__tests__/context-factory.test.d.ts.map +0 -1
  488. package/dist/execution/__tests__/context-factory.test.js +0 -133
  489. package/dist/execution/__tests__/context-factory.test.js.map +0 -1
  490. package/dist/explanation/__tests__/tracker.test.d.ts +0 -2
  491. package/dist/explanation/__tests__/tracker.test.d.ts.map +0 -1
  492. package/dist/explanation/__tests__/tracker.test.js +0 -169
  493. package/dist/explanation/__tests__/tracker.test.js.map +0 -1
  494. package/dist/fields/__tests__/fields.test.d.ts +0 -2
  495. package/dist/fields/__tests__/fields.test.d.ts.map +0 -1
  496. package/dist/fields/__tests__/fields.test.js +0 -60
  497. package/dist/fields/__tests__/fields.test.js.map +0 -1
  498. package/dist/flows/__tests__/flow-engine.test.d.ts +0 -2
  499. package/dist/flows/__tests__/flow-engine.test.d.ts.map +0 -1
  500. package/dist/flows/__tests__/flow-engine.test.js +0 -797
  501. package/dist/flows/__tests__/flow-engine.test.js.map +0 -1
  502. package/dist/flows/__tests__/flow-registry.test.d.ts +0 -2
  503. package/dist/flows/__tests__/flow-registry.test.d.ts.map +0 -1
  504. package/dist/flows/__tests__/flow-registry.test.js +0 -69
  505. package/dist/flows/__tests__/flow-registry.test.js.map +0 -1
  506. package/dist/flows/__tests__/flow-service.test.d.ts +0 -2
  507. package/dist/flows/__tests__/flow-service.test.d.ts.map +0 -1
  508. package/dist/flows/__tests__/flow-service.test.js +0 -55
  509. package/dist/flows/__tests__/flow-service.test.js.map +0 -1
  510. package/dist/flows/__tests__/scheduler.test.d.ts +0 -2
  511. package/dist/flows/__tests__/scheduler.test.d.ts.map +0 -1
  512. package/dist/flows/__tests__/scheduler.test.js +0 -120
  513. package/dist/flows/__tests__/scheduler.test.js.map +0 -1
  514. package/dist/flows/__tests__/state-machine.test.d.ts +0 -2
  515. package/dist/flows/__tests__/state-machine.test.d.ts.map +0 -1
  516. package/dist/flows/__tests__/state-machine.test.js +0 -62
  517. package/dist/flows/__tests__/state-machine.test.js.map +0 -1
  518. package/dist/flows/__tests__/step-executor.test.d.ts +0 -2
  519. package/dist/flows/__tests__/step-executor.test.d.ts.map +0 -1
  520. package/dist/flows/__tests__/step-executor.test.js +0 -201
  521. package/dist/flows/__tests__/step-executor.test.js.map +0 -1
  522. package/dist/flows/__tests__/triggers.test.d.ts +0 -2
  523. package/dist/flows/__tests__/triggers.test.d.ts.map +0 -1
  524. package/dist/flows/__tests__/triggers.test.js +0 -98
  525. package/dist/flows/__tests__/triggers.test.js.map +0 -1
  526. package/dist/governance/__tests__/overrides.test.d.ts +0 -2
  527. package/dist/governance/__tests__/overrides.test.d.ts.map +0 -1
  528. package/dist/governance/__tests__/overrides.test.js +0 -123
  529. package/dist/governance/__tests__/overrides.test.js.map +0 -1
  530. package/dist/governance/__tests__/policies.test.d.ts +0 -2
  531. package/dist/governance/__tests__/policies.test.d.ts.map +0 -1
  532. package/dist/governance/__tests__/policies.test.js +0 -203
  533. package/dist/governance/__tests__/policies.test.js.map +0 -1
  534. package/dist/governance/__tests__/rules.test.d.ts +0 -2
  535. package/dist/governance/__tests__/rules.test.d.ts.map +0 -1
  536. package/dist/governance/__tests__/rules.test.js +0 -342
  537. package/dist/governance/__tests__/rules.test.js.map +0 -1
  538. package/dist/observability/__tests__/metrics.test.d.ts +0 -2
  539. package/dist/observability/__tests__/metrics.test.d.ts.map +0 -1
  540. package/dist/observability/__tests__/metrics.test.js +0 -301
  541. package/dist/observability/__tests__/metrics.test.js.map +0 -1
  542. package/dist/server/__tests__/bootstrap.test.d.ts +0 -2
  543. package/dist/server/__tests__/bootstrap.test.d.ts.map +0 -1
  544. package/dist/server/__tests__/bootstrap.test.js +0 -381
  545. package/dist/server/__tests__/bootstrap.test.js.map +0 -1
  546. package/dist/testing/__tests__/context.test.d.ts +0 -2
  547. package/dist/testing/__tests__/context.test.d.ts.map +0 -1
  548. package/dist/testing/__tests__/context.test.js +0 -341
  549. package/dist/testing/__tests__/context.test.js.map +0 -1
  550. package/dist/testing/__tests__/e2e.test.d.ts +0 -2
  551. package/dist/testing/__tests__/e2e.test.d.ts.map +0 -1
  552. package/dist/testing/__tests__/e2e.test.js +0 -119
  553. package/dist/testing/__tests__/e2e.test.js.map +0 -1
  554. package/dist/testing/__tests__/field-validation.test.d.ts +0 -2
  555. package/dist/testing/__tests__/field-validation.test.d.ts.map +0 -1
  556. package/dist/testing/__tests__/field-validation.test.js +0 -178
  557. package/dist/testing/__tests__/field-validation.test.js.map +0 -1
  558. package/dist/testing/__tests__/governance.test.d.ts +0 -2
  559. package/dist/testing/__tests__/governance.test.d.ts.map +0 -1
  560. package/dist/testing/__tests__/governance.test.js +0 -222
  561. package/dist/testing/__tests__/governance.test.js.map +0 -1
  562. package/dist/testing/__tests__/run-capability.test.d.ts +0 -2
  563. package/dist/testing/__tests__/run-capability.test.d.ts.map +0 -1
  564. package/dist/testing/__tests__/run-capability.test.js +0 -114
  565. package/dist/testing/__tests__/run-capability.test.js.map +0 -1
  566. package/dist/testing/__tests__/scaffolding.test.d.ts +0 -2
  567. package/dist/testing/__tests__/scaffolding.test.d.ts.map +0 -1
  568. package/dist/testing/__tests__/scaffolding.test.js +0 -70
  569. package/dist/testing/__tests__/scaffolding.test.js.map +0 -1
  570. package/dist/testing/__tests__/security.test.d.ts +0 -2
  571. package/dist/testing/__tests__/security.test.d.ts.map +0 -1
  572. package/dist/testing/__tests__/security.test.js +0 -186
  573. package/dist/testing/__tests__/security.test.js.map +0 -1
  574. package/dist/testing/__tests__/simulate-flow.test.d.ts +0 -2
  575. package/dist/testing/__tests__/simulate-flow.test.d.ts.map +0 -1
  576. package/dist/testing/__tests__/simulate-flow.test.js +0 -230
  577. package/dist/testing/__tests__/simulate-flow.test.js.map +0 -1
  578. package/dist/translations/__tests__/translation-resolver.test.d.ts +0 -2
  579. package/dist/translations/__tests__/translation-resolver.test.d.ts.map +0 -1
  580. package/dist/translations/__tests__/translation-resolver.test.js +0 -140
  581. package/dist/translations/__tests__/translation-resolver.test.js.map +0 -1
  582. package/dist/types/__tests__/registry.test.d.ts +0 -2
  583. package/dist/types/__tests__/registry.test.d.ts.map +0 -1
  584. package/dist/types/__tests__/registry.test.js +0 -34
  585. package/dist/types/__tests__/registry.test.js.map +0 -1
  586. package/dist/worker/__tests__/bootstrap.test.d.ts +0 -2
  587. package/dist/worker/__tests__/bootstrap.test.d.ts.map +0 -1
  588. package/dist/worker/__tests__/bootstrap.test.js +0 -268
  589. package/dist/worker/__tests__/bootstrap.test.js.map +0 -1
  590. package/dist/worker/__tests__/flow-service-wiring.test.d.ts +0 -2
  591. package/dist/worker/__tests__/flow-service-wiring.test.d.ts.map +0 -1
  592. package/dist/worker/__tests__/flow-service-wiring.test.js +0 -64
  593. 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