@open-mercato/core 0.7.1-develop.7193.1.910a5b0a1e → 0.7.1-develop.7195.1.b5efd1d51a

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 (1241) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/AGENTS.md +4 -3
  3. package/agentic/standalone-guide.md +1 -1
  4. package/build.mjs +16 -0
  5. package/dist/bootstrap.js +7 -3
  6. package/dist/bootstrap.js.map +2 -2
  7. package/dist/generated/entities/action_log/index.js +2 -0
  8. package/dist/generated/entities/action_log/index.js.map +2 -2
  9. package/dist/generated/entities/user/index.js +2 -0
  10. package/dist/generated/entities/user/index.js.map +2 -2
  11. package/dist/generated/entities/user_task/index.js +14 -0
  12. package/dist/generated/entities/user_task/index.js.map +2 -2
  13. package/dist/generated/entities/workflow_definition/index.js +6 -0
  14. package/dist/generated/entities/workflow_definition/index.js.map +2 -2
  15. package/dist/generated/entities/workflow_definition_draft/index.js +25 -0
  16. package/dist/generated/entities/workflow_definition_draft/index.js.map +7 -0
  17. package/dist/generated/entities/workflow_definition_metric_rollup/index.js +23 -0
  18. package/dist/generated/entities/workflow_definition_metric_rollup/index.js.map +7 -0
  19. package/dist/generated/entities/workflow_instance/index.js +4 -0
  20. package/dist/generated/entities/workflow_instance/index.js.map +2 -2
  21. package/dist/generated/entities.ids.generated.js +4 -1
  22. package/dist/generated/entities.ids.generated.js.map +2 -2
  23. package/dist/generated/entity-fields-registry.js +39 -0
  24. package/dist/generated/entity-fields-registry.js.map +2 -2
  25. package/dist/helpers/integration/workflowsFixtures.js +477 -2
  26. package/dist/helpers/integration/workflowsFixtures.js.map +2 -2
  27. package/dist/helpers/integration/workflowsUi.js +148 -0
  28. package/dist/helpers/integration/workflowsUi.js.map +7 -0
  29. package/dist/modules/attachments/lib/createFromBuffer.js +79 -0
  30. package/dist/modules/attachments/lib/createFromBuffer.js.map +7 -0
  31. package/dist/modules/audit_logs/data/entities.js +5 -0
  32. package/dist/modules/audit_logs/data/entities.js.map +2 -2
  33. package/dist/modules/audit_logs/data/validators.js +1 -0
  34. package/dist/modules/audit_logs/data/validators.js.map +2 -2
  35. package/dist/modules/audit_logs/lib/projections.js +2 -1
  36. package/dist/modules/audit_logs/lib/projections.js.map +2 -2
  37. package/dist/modules/audit_logs/migrations/Migration20260625120000.js +15 -0
  38. package/dist/modules/audit_logs/migrations/Migration20260625120000.js.map +7 -0
  39. package/dist/modules/audit_logs/services/actionLogService.js +3 -0
  40. package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
  41. package/dist/modules/auth/data/entities.js +6 -0
  42. package/dist/modules/auth/data/entities.js.map +2 -2
  43. package/dist/modules/auth/lib/executionPrincipal.js +140 -0
  44. package/dist/modules/auth/lib/executionPrincipal.js.map +7 -0
  45. package/dist/modules/auth/migrations/Migration20260625050000.js +13 -0
  46. package/dist/modules/auth/migrations/Migration20260625050000.js.map +7 -0
  47. package/dist/modules/business_rules/components/InlineRuleEditor.js +154 -0
  48. package/dist/modules/business_rules/components/InlineRuleEditor.js.map +7 -0
  49. package/dist/modules/business_rules/data/validators.js +6 -0
  50. package/dist/modules/business_rules/data/validators.js.map +2 -2
  51. package/dist/modules/business_rules/lib/rule-engine.js +5 -3
  52. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  53. package/dist/modules/catalog/commands/products.js +5 -0
  54. package/dist/modules/catalog/commands/products.js.map +2 -2
  55. package/dist/modules/catalog/workflows.js +19 -0
  56. package/dist/modules/catalog/workflows.js.map +7 -0
  57. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +3 -1
  58. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  59. package/dist/modules/customer_accounts/cli.js +80 -0
  60. package/dist/modules/customer_accounts/cli.js.map +7 -0
  61. package/dist/modules/customer_accounts/lib/customerRoleAclSync.js +59 -0
  62. package/dist/modules/customer_accounts/lib/customerRoleAclSync.js.map +7 -0
  63. package/dist/modules/customer_accounts/setup.js +4 -2
  64. package/dist/modules/customer_accounts/setup.js.map +2 -2
  65. package/dist/modules/customers/commands/deals.js +4 -0
  66. package/dist/modules/customers/commands/deals.js.map +2 -2
  67. package/dist/modules/customers/components/detail/ChangelogEntryRow.js +1 -1
  68. package/dist/modules/customers/components/detail/ChangelogEntryRow.js.map +2 -2
  69. package/dist/modules/customers/components/detail/utils.js +2 -0
  70. package/dist/modules/customers/components/detail/utils.js.map +2 -2
  71. package/dist/modules/customers/events.js +13 -2
  72. package/dist/modules/customers/events.js.map +2 -2
  73. package/dist/modules/customers/lib/link-workflow-task-handler.js +64 -0
  74. package/dist/modules/customers/lib/link-workflow-task-handler.js.map +7 -0
  75. package/dist/modules/customers/lib/todoCompatibility.js +1 -1
  76. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  77. package/dist/modules/customers/lib/workflowTaskLink.js +9 -0
  78. package/dist/modules/customers/lib/workflowTaskLink.js.map +7 -0
  79. package/dist/modules/customers/subscribers/link-workflow-task.js +12 -0
  80. package/dist/modules/customers/subscribers/link-workflow-task.js.map +7 -0
  81. package/dist/modules/customers/workflows.js +29 -0
  82. package/dist/modules/customers/workflows.js.map +7 -0
  83. package/dist/modules/entities/api/records.js +13 -33
  84. package/dist/modules/entities/api/records.js.map +3 -3
  85. package/dist/modules/entities/lib/entityClassification.js +60 -0
  86. package/dist/modules/entities/lib/entityClassification.js.map +7 -0
  87. package/dist/modules/sales/commands/documents.js +31 -0
  88. package/dist/modules/sales/commands/documents.js.map +2 -2
  89. package/dist/modules/sales/events.js +12 -1
  90. package/dist/modules/sales/events.js.map +2 -2
  91. package/dist/modules/sales/workflows.js +12 -1
  92. package/dist/modules/sales/workflows.js.map +2 -2
  93. package/dist/modules/seeds/cli.js +199 -0
  94. package/dist/modules/seeds/cli.js.map +7 -0
  95. package/dist/modules/seeds/examples/sample-seed.json +26 -0
  96. package/dist/modules/seeds/index.js +12 -0
  97. package/dist/modules/seeds/index.js.map +7 -0
  98. package/dist/modules/workflows/acl.js +96 -0
  99. package/dist/modules/workflows/acl.js.map +2 -2
  100. package/dist/modules/workflows/ai-agents.js +50 -0
  101. package/dist/modules/workflows/ai-agents.js.map +7 -0
  102. package/dist/modules/workflows/ai-tools/authoring-pack.js +582 -0
  103. package/dist/modules/workflows/ai-tools/authoring-pack.js.map +7 -0
  104. package/dist/modules/workflows/ai-tools/types.js +43 -0
  105. package/dist/modules/workflows/ai-tools/types.js.map +7 -0
  106. package/dist/modules/workflows/ai-tools.js +10 -0
  107. package/dist/modules/workflows/ai-tools.js.map +7 -0
  108. package/dist/modules/workflows/api/command-settings/route.js +137 -0
  109. package/dist/modules/workflows/api/command-settings/route.js.map +7 -0
  110. package/dist/modules/workflows/api/commands/route.js +72 -0
  111. package/dist/modules/workflows/api/commands/route.js.map +7 -0
  112. package/dist/modules/workflows/api/definitions/[id]/callers/route.js +76 -0
  113. package/dist/modules/workflows/api/definitions/[id]/callers/route.js.map +7 -0
  114. package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js +134 -0
  115. package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js.map +7 -0
  116. package/dist/modules/workflows/api/definitions/[id]/customize/route.js +5 -1
  117. package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
  118. package/dist/modules/workflows/api/definitions/[id]/draft/route.js +286 -0
  119. package/dist/modules/workflows/api/definitions/[id]/draft/route.js.map +7 -0
  120. package/dist/modules/workflows/api/definitions/[id]/publish/route.js +207 -0
  121. package/dist/modules/workflows/api/definitions/[id]/publish/route.js.map +7 -0
  122. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +5 -0
  123. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
  124. package/dist/modules/workflows/api/definitions/[id]/route.js +93 -9
  125. package/dist/modules/workflows/api/definitions/[id]/route.js.map +3 -3
  126. package/dist/modules/workflows/api/definitions/[id]/test-step/route.js +210 -0
  127. package/dist/modules/workflows/api/definitions/[id]/test-step/route.js.map +7 -0
  128. package/dist/modules/workflows/api/definitions/generate/route.js +233 -0
  129. package/dist/modules/workflows/api/definitions/generate/route.js.map +7 -0
  130. package/dist/modules/workflows/api/definitions/route.js +61 -113
  131. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  132. package/dist/modules/workflows/api/definitions/serialize.js +9 -0
  133. package/dist/modules/workflows/api/definitions/serialize.js.map +2 -2
  134. package/dist/modules/workflows/api/endpoints/route.js +69 -0
  135. package/dist/modules/workflows/api/endpoints/route.js.map +7 -0
  136. package/dist/modules/workflows/api/functions/route.js +73 -0
  137. package/dist/modules/workflows/api/functions/route.js.map +7 -0
  138. package/dist/modules/workflows/api/grantable-features/route.js +75 -0
  139. package/dist/modules/workflows/api/grantable-features/route.js.map +7 -0
  140. package/dist/modules/workflows/api/instances/[id]/context/route.js +180 -0
  141. package/dist/modules/workflows/api/instances/[id]/context/route.js.map +7 -0
  142. package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js +184 -0
  143. package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js.map +7 -0
  144. package/dist/modules/workflows/api/instances/[id]/retry/route.js +12 -2
  145. package/dist/modules/workflows/api/instances/[id]/retry/route.js.map +2 -2
  146. package/dist/modules/workflows/api/instances/[id]/step-through/route.js +148 -0
  147. package/dist/modules/workflows/api/instances/[id]/step-through/route.js.map +7 -0
  148. package/dist/modules/workflows/api/instances/[id]/steps/route.js +123 -0
  149. package/dist/modules/workflows/api/instances/[id]/steps/route.js.map +7 -0
  150. package/dist/modules/workflows/api/instances/[id]/would-do/route.js +172 -0
  151. package/dist/modules/workflows/api/instances/[id]/would-do/route.js.map +7 -0
  152. package/dist/modules/workflows/api/instances/bulk-replay/route.js +117 -0
  153. package/dist/modules/workflows/api/instances/bulk-replay/route.js.map +7 -0
  154. package/dist/modules/workflows/api/instances/failure-queue/route.js +165 -0
  155. package/dist/modules/workflows/api/instances/failure-queue/route.js.map +7 -0
  156. package/dist/modules/workflows/api/instances/route.js +94 -3
  157. package/dist/modules/workflows/api/instances/route.js.map +2 -2
  158. package/dist/modules/workflows/api/metrics/definitions/route.js +188 -0
  159. package/dist/modules/workflows/api/metrics/definitions/route.js.map +7 -0
  160. package/dist/modules/workflows/api/openapi.js +415 -4
  161. package/dist/modules/workflows/api/openapi.js.map +2 -2
  162. package/dist/modules/workflows/api/portal/tasks/[id]/complete/route.js +132 -0
  163. package/dist/modules/workflows/api/portal/tasks/[id]/complete/route.js.map +7 -0
  164. package/dist/modules/workflows/api/portal/tasks/[id]/route.js +97 -0
  165. package/dist/modules/workflows/api/portal/tasks/[id]/route.js.map +7 -0
  166. package/dist/modules/workflows/api/portal/tasks/route.js +126 -0
  167. package/dist/modules/workflows/api/portal/tasks/route.js.map +7 -0
  168. package/dist/modules/workflows/api/rule-usage/route.js +80 -0
  169. package/dist/modules/workflows/api/rule-usage/route.js.map +7 -0
  170. package/dist/modules/workflows/api/task-settings/route.js +107 -0
  171. package/dist/modules/workflows/api/task-settings/route.js.map +7 -0
  172. package/dist/modules/workflows/api/tasks/[id]/claim/route.js +27 -16
  173. package/dist/modules/workflows/api/tasks/[id]/claim/route.js.map +2 -2
  174. package/dist/modules/workflows/api/tasks/[id]/complete/route.js +40 -16
  175. package/dist/modules/workflows/api/tasks/[id]/complete/route.js.map +2 -2
  176. package/dist/modules/workflows/api/tasks/[id]/reassign/route.js +150 -0
  177. package/dist/modules/workflows/api/tasks/[id]/reassign/route.js.map +7 -0
  178. package/dist/modules/workflows/api/tasks/[id]/route.js +39 -6
  179. package/dist/modules/workflows/api/tasks/[id]/route.js.map +2 -2
  180. package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js +100 -0
  181. package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js.map +7 -0
  182. package/dist/modules/workflows/api/tasks/route.js +37 -6
  183. package/dist/modules/workflows/api/tasks/route.js.map +2 -2
  184. package/dist/modules/workflows/api/tasks/serialize.js +83 -0
  185. package/dist/modules/workflows/api/tasks/serialize.js.map +7 -0
  186. package/dist/modules/workflows/api/templates/route.js +69 -0
  187. package/dist/modules/workflows/api/templates/route.js.map +7 -0
  188. package/dist/modules/workflows/api/work-inbox/next/route.js +129 -0
  189. package/dist/modules/workflows/api/work-inbox/next/route.js.map +7 -0
  190. package/dist/modules/workflows/api/work-inbox/route.js +119 -0
  191. package/dist/modules/workflows/api/work-inbox/route.js.map +7 -0
  192. package/dist/modules/workflows/backend/config/workflows/page.js +10 -0
  193. package/dist/modules/workflows/backend/config/workflows/page.js.map +7 -0
  194. package/dist/modules/workflows/backend/config/workflows/page.meta.js +35 -0
  195. package/dist/modules/workflows/backend/config/workflows/page.meta.js.map +7 -0
  196. package/dist/modules/workflows/backend/definitions/[id]/page.js +6 -271
  197. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +3 -3
  198. package/dist/modules/workflows/backend/definitions/create/page.js +7 -56
  199. package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
  200. package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
  201. package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
  202. package/dist/modules/workflows/backend/definitions/page.js +131 -51
  203. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  204. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +2606 -677
  205. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +3 -3
  206. package/dist/modules/workflows/backend/instances/[id]/page.js +532 -421
  207. package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
  208. package/dist/modules/workflows/backend/instances/[id]/page.meta.js +1 -1
  209. package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +1 -1
  210. package/dist/modules/workflows/backend/instances/failure-queue/page.js +211 -0
  211. package/dist/modules/workflows/backend/instances/failure-queue/page.js.map +7 -0
  212. package/dist/modules/workflows/backend/instances/failure-queue/page.meta.js +20 -0
  213. package/dist/modules/workflows/backend/instances/failure-queue/page.meta.js.map +7 -0
  214. package/dist/modules/workflows/backend/instances/page.js +159 -22
  215. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  216. package/dist/modules/workflows/backend/instances/page.meta.js +1 -1
  217. package/dist/modules/workflows/backend/instances/page.meta.js.map +1 -1
  218. package/dist/modules/workflows/backend/tasks/[id]/page.js +553 -392
  219. package/dist/modules/workflows/backend/tasks/[id]/page.js.map +3 -3
  220. package/dist/modules/workflows/backend/tasks/page.js +8 -250
  221. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  222. package/dist/modules/workflows/backend/tasks/page.meta.js +1 -0
  223. package/dist/modules/workflows/backend/tasks/page.meta.js.map +2 -2
  224. package/dist/modules/workflows/backend/work-inbox/page.js +399 -0
  225. package/dist/modules/workflows/backend/work-inbox/page.js.map +7 -0
  226. package/dist/modules/workflows/backend/work-inbox/page.meta.js +19 -0
  227. package/dist/modules/workflows/backend/work-inbox/page.meta.js.map +7 -0
  228. package/dist/modules/workflows/cli.js +1 -1
  229. package/dist/modules/workflows/cli.js.map +2 -2
  230. package/dist/modules/workflows/commands/tasks.js +81 -0
  231. package/dist/modules/workflows/commands/tasks.js.map +7 -0
  232. package/dist/modules/workflows/components/ActivitiesEditor.js +281 -287
  233. package/dist/modules/workflows/components/ActivitiesEditor.js.map +2 -2
  234. package/dist/modules/workflows/components/ActivityEditDialog.js +220 -0
  235. package/dist/modules/workflows/components/ActivityEditDialog.js.map +7 -0
  236. package/dist/modules/workflows/components/AgentSelector.js +115 -0
  237. package/dist/modules/workflows/components/AgentSelector.js.map +7 -0
  238. package/dist/modules/workflows/components/AnnotationEditDialog.js +110 -0
  239. package/dist/modules/workflows/components/AnnotationEditDialog.js.map +7 -0
  240. package/dist/modules/workflows/components/BusinessRuleUsagePanel.js +71 -0
  241. package/dist/modules/workflows/components/BusinessRuleUsagePanel.js.map +7 -0
  242. package/dist/modules/workflows/components/BusinessRulesSelector.js +151 -93
  243. package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
  244. package/dist/modules/workflows/components/ConfigJsonTextarea.js +85 -0
  245. package/dist/modules/workflows/components/ConfigJsonTextarea.js.map +7 -0
  246. package/dist/modules/workflows/components/ContextSchemaEditor.js +150 -0
  247. package/dist/modules/workflows/components/ContextSchemaEditor.js.map +7 -0
  248. package/dist/modules/workflows/components/DefinitionErrorHandlerField.js +102 -0
  249. package/dist/modules/workflows/components/DefinitionErrorHandlerField.js.map +7 -0
  250. package/dist/modules/workflows/components/DefinitionMetadataDrawer.js +377 -0
  251. package/dist/modules/workflows/components/DefinitionMetadataDrawer.js.map +7 -0
  252. package/dist/modules/workflows/components/DefinitionMetricsCells.js +132 -0
  253. package/dist/modules/workflows/components/DefinitionMetricsCells.js.map +7 -0
  254. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +307 -216
  255. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  256. package/dist/modules/workflows/components/EdgeEditDialog.js +11 -18
  257. package/dist/modules/workflows/components/EdgeEditDialog.js.map +2 -2
  258. package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js +112 -72
  259. package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js.map +2 -2
  260. package/dist/modules/workflows/components/InputDataPanel.js +128 -0
  261. package/dist/modules/workflows/components/InputDataPanel.js.map +7 -0
  262. package/dist/modules/workflows/components/InspectorPanel.js +161 -0
  263. package/dist/modules/workflows/components/InspectorPanel.js.map +7 -0
  264. package/dist/modules/workflows/components/NodeEditDialog.js +363 -41
  265. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  266. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +714 -159
  267. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
  268. package/dist/modules/workflows/components/StepsEditor.js.map +2 -2
  269. package/dist/modules/workflows/components/TemplateGalleryDialog.js +148 -0
  270. package/dist/modules/workflows/components/TemplateGalleryDialog.js.map +7 -0
  271. package/dist/modules/workflows/components/TransitionsEditor.js +80 -74
  272. package/dist/modules/workflows/components/TransitionsEditor.js.map +2 -2
  273. package/dist/modules/workflows/components/TriggersDialog.js +53 -0
  274. package/dist/modules/workflows/components/TriggersDialog.js.map +7 -0
  275. package/dist/modules/workflows/components/TriggersEditor.js +331 -0
  276. package/dist/modules/workflows/components/TriggersEditor.js.map +7 -0
  277. package/dist/modules/workflows/components/WorkflowAiDraftDialog.js +278 -0
  278. package/dist/modules/workflows/components/WorkflowAiDraftDialog.js.map +7 -0
  279. package/dist/modules/workflows/components/WorkflowCodeView.js +173 -0
  280. package/dist/modules/workflows/components/WorkflowCodeView.js.map +7 -0
  281. package/dist/modules/workflows/components/WorkflowCommandPalette.js +62 -0
  282. package/dist/modules/workflows/components/WorkflowCommandPalette.js.map +7 -0
  283. package/dist/modules/workflows/components/WorkflowCompensationGhostEdge.js +70 -0
  284. package/dist/modules/workflows/components/WorkflowCompensationGhostEdge.js.map +7 -0
  285. package/dist/modules/workflows/components/WorkflowDataMappingEdge.js +36 -0
  286. package/dist/modules/workflows/components/WorkflowDataMappingEdge.js.map +7 -0
  287. package/dist/modules/workflows/components/WorkflowGraph.js +4 -2
  288. package/dist/modules/workflows/components/WorkflowGraph.js.map +2 -2
  289. package/dist/modules/workflows/components/WorkflowGraphImpl.js +324 -86
  290. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +3 -3
  291. package/dist/modules/workflows/components/WorkflowIconPicker.js +109 -0
  292. package/dist/modules/workflows/components/WorkflowIconPicker.js.map +7 -0
  293. package/dist/modules/workflows/components/WorkflowLegend.js +45 -29
  294. package/dist/modules/workflows/components/WorkflowLegend.js.map +2 -2
  295. package/dist/modules/workflows/components/WorkflowNodeCard.js +221 -22
  296. package/dist/modules/workflows/components/WorkflowNodeCard.js.map +2 -2
  297. package/dist/modules/workflows/components/WorkflowRouteChips.js +111 -0
  298. package/dist/modules/workflows/components/WorkflowRouteChips.js.map +7 -0
  299. package/dist/modules/workflows/components/WorkflowSelector.js +108 -88
  300. package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
  301. package/dist/modules/workflows/components/WorkflowTransitionEdge.js +61 -11
  302. package/dist/modules/workflows/components/WorkflowTransitionEdge.js.map +2 -2
  303. package/dist/modules/workflows/components/WorkflowTransitionLabel.js +15 -5
  304. package/dist/modules/workflows/components/WorkflowTransitionLabel.js.map +2 -2
  305. package/dist/modules/workflows/components/fields/ActivityArrayEditor.js +88 -21
  306. package/dist/modules/workflows/components/fields/ActivityArrayEditor.js.map +2 -2
  307. package/dist/modules/workflows/components/fields/ActivityConfigFields.js +615 -0
  308. package/dist/modules/workflows/components/fields/ActivityConfigFields.js.map +7 -0
  309. package/dist/modules/workflows/components/fields/ActivityTestPanel.js +191 -0
  310. package/dist/modules/workflows/components/fields/ActivityTestPanel.js.map +7 -0
  311. package/dist/modules/workflows/components/fields/AgentInvokeConfigField.js +488 -0
  312. package/dist/modules/workflows/components/fields/AgentInvokeConfigField.js.map +7 -0
  313. package/dist/modules/workflows/components/fields/AgentReviewOnBreachField.js +61 -0
  314. package/dist/modules/workflows/components/fields/AgentReviewOnBreachField.js.map +7 -0
  315. package/dist/modules/workflows/components/fields/BranchingRoutesEditor.js +227 -0
  316. package/dist/modules/workflows/components/fields/BranchingRoutesEditor.js.map +7 -0
  317. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +37 -4
  318. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
  319. package/dist/modules/workflows/components/fields/CommandPicker.js +111 -0
  320. package/dist/modules/workflows/components/fields/CommandPicker.js.map +7 -0
  321. package/dist/modules/workflows/components/fields/EndpointPicker.js +235 -0
  322. package/dist/modules/workflows/components/fields/EndpointPicker.js.map +7 -0
  323. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +2 -2
  324. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
  325. package/dist/modules/workflows/components/fields/FunctionPicker.js +55 -0
  326. package/dist/modules/workflows/components/fields/FunctionPicker.js.map +7 -0
  327. package/dist/modules/workflows/components/fields/MappingArrayEditor.js +38 -15
  328. package/dist/modules/workflows/components/fields/MappingArrayEditor.js.map +2 -2
  329. package/dist/modules/workflows/components/fields/PortFieldArrayEditor.js +206 -0
  330. package/dist/modules/workflows/components/fields/PortFieldArrayEditor.js.map +7 -0
  331. package/dist/modules/workflows/components/fields/RolesMultiSelect.js +53 -0
  332. package/dist/modules/workflows/components/fields/RolesMultiSelect.js.map +7 -0
  333. package/dist/modules/workflows/components/fields/RouteOrderEditor.js +130 -0
  334. package/dist/modules/workflows/components/fields/RouteOrderEditor.js.map +7 -0
  335. package/dist/modules/workflows/components/fields/SchemaBuilderDialog.js +104 -0
  336. package/dist/modules/workflows/components/fields/SchemaBuilderDialog.js.map +7 -0
  337. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +2 -2
  338. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
  339. package/dist/modules/workflows/components/fields/TaskAssignmentField.js +210 -0
  340. package/dist/modules/workflows/components/fields/TaskAssignmentField.js.map +7 -0
  341. package/dist/modules/workflows/components/fields/TaskDeadlineFields.js +126 -0
  342. package/dist/modules/workflows/components/fields/TaskDeadlineFields.js.map +7 -0
  343. package/dist/modules/workflows/components/fields/TaskDecisionsField.js +218 -0
  344. package/dist/modules/workflows/components/fields/TaskDecisionsField.js.map +7 -0
  345. package/dist/modules/workflows/components/fields/TaskEntityBindingsField.js +114 -0
  346. package/dist/modules/workflows/components/fields/TaskEntityBindingsField.js.map +7 -0
  347. package/dist/modules/workflows/components/fields/TemplateTextControl.js +64 -0
  348. package/dist/modules/workflows/components/fields/TemplateTextControl.js.map +7 -0
  349. package/dist/modules/workflows/components/fields/VariablePickerButton.js +121 -0
  350. package/dist/modules/workflows/components/fields/VariablePickerButton.js.map +7 -0
  351. package/dist/modules/workflows/components/fields/ledgerDropTarget.js +35 -0
  352. package/dist/modules/workflows/components/fields/ledgerDropTarget.js.map +7 -0
  353. package/dist/modules/workflows/components/fields/useActivityTypeOptions.js +16 -0
  354. package/dist/modules/workflows/components/fields/useActivityTypeOptions.js.map +7 -0
  355. package/dist/modules/workflows/components/formConfig.js +39 -10
  356. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  357. package/dist/modules/workflows/components/mobile/MobileDefinitionDetail.js.map +2 -2
  358. package/dist/modules/workflows/components/mobile/MobileMetadataSheet.js.map +2 -2
  359. package/dist/modules/workflows/components/mobile/MobileTaskForm.js +29 -2
  360. package/dist/modules/workflows/components/mobile/MobileTaskForm.js.map +2 -2
  361. package/dist/modules/workflows/components/mobile/MobileVisualEditor.js +64 -65
  362. package/dist/modules/workflows/components/mobile/MobileVisualEditor.js.map +2 -2
  363. package/dist/modules/workflows/components/nodes/AnnotationGroupNode.js +64 -0
  364. package/dist/modules/workflows/components/nodes/AnnotationGroupNode.js.map +7 -0
  365. package/dist/modules/workflows/components/nodes/AutomatedNode.js +24 -16
  366. package/dist/modules/workflows/components/nodes/AutomatedNode.js.map +2 -2
  367. package/dist/modules/workflows/components/nodes/EndNode.js +13 -12
  368. package/dist/modules/workflows/components/nodes/EndNode.js.map +2 -2
  369. package/dist/modules/workflows/components/nodes/ErrorOutputHandle.js +29 -0
  370. package/dist/modules/workflows/components/nodes/ErrorOutputHandle.js.map +7 -0
  371. package/dist/modules/workflows/components/nodes/IfElseNode.js +51 -0
  372. package/dist/modules/workflows/components/nodes/IfElseNode.js.map +7 -0
  373. package/dist/modules/workflows/components/nodes/InvokeAgentNode.js +122 -0
  374. package/dist/modules/workflows/components/nodes/InvokeAgentNode.js.map +7 -0
  375. package/dist/modules/workflows/components/nodes/NodeOutcomeRows.js +100 -0
  376. package/dist/modules/workflows/components/nodes/NodeOutcomeRows.js.map +7 -0
  377. package/dist/modules/workflows/components/nodes/ParallelForkNode.js +18 -14
  378. package/dist/modules/workflows/components/nodes/ParallelForkNode.js.map +2 -2
  379. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js +18 -14
  380. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js.map +2 -2
  381. package/dist/modules/workflows/components/nodes/StartNode.js +66 -15
  382. package/dist/modules/workflows/components/nodes/StartNode.js.map +2 -2
  383. package/dist/modules/workflows/components/nodes/StickyNoteNode.js +54 -0
  384. package/dist/modules/workflows/components/nodes/StickyNoteNode.js.map +7 -0
  385. package/dist/modules/workflows/components/nodes/SubWorkflowNode.js +107 -41
  386. package/dist/modules/workflows/components/nodes/SubWorkflowNode.js.map +2 -2
  387. package/dist/modules/workflows/components/nodes/SwitchNode.js +51 -0
  388. package/dist/modules/workflows/components/nodes/SwitchNode.js.map +7 -0
  389. package/dist/modules/workflows/components/nodes/TriggerCap.js +65 -0
  390. package/dist/modules/workflows/components/nodes/TriggerCap.js.map +7 -0
  391. package/dist/modules/workflows/components/nodes/TriggerNode.js +111 -0
  392. package/dist/modules/workflows/components/nodes/TriggerNode.js.map +7 -0
  393. package/dist/modules/workflows/components/nodes/UserTaskNode.js +43 -17
  394. package/dist/modules/workflows/components/nodes/UserTaskNode.js.map +2 -2
  395. package/dist/modules/workflows/components/nodes/WaitForConditionNode.js +53 -0
  396. package/dist/modules/workflows/components/nodes/WaitForConditionNode.js.map +7 -0
  397. package/dist/modules/workflows/components/nodes/WaitForSignalNode.js +21 -15
  398. package/dist/modules/workflows/components/nodes/WaitForSignalNode.js.map +2 -2
  399. package/dist/modules/workflows/components/nodes/WaitForTimerNode.js +21 -15
  400. package/dist/modules/workflows/components/nodes/WaitForTimerNode.js.map +2 -2
  401. package/dist/modules/workflows/components/nodes/index.js +14 -0
  402. package/dist/modules/workflows/components/nodes/index.js.map +2 -2
  403. package/dist/modules/workflows/components/portal/PortalTaskForm.js +196 -0
  404. package/dist/modules/workflows/components/portal/PortalTaskForm.js.map +7 -0
  405. package/dist/modules/workflows/components/run/AgentActivityPanel.js +22 -0
  406. package/dist/modules/workflows/components/run/AgentActivityPanel.js.map +7 -0
  407. package/dist/modules/workflows/components/run/RerunStepDialog.js +106 -0
  408. package/dist/modules/workflows/components/run/RerunStepDialog.js.map +7 -0
  409. package/dist/modules/workflows/components/run/RunEventBadge.js +30 -0
  410. package/dist/modules/workflows/components/run/RunEventBadge.js.map +7 -0
  411. package/dist/modules/workflows/components/run/RunGantt.js +130 -0
  412. package/dist/modules/workflows/components/run/RunGantt.js.map +7 -0
  413. package/dist/modules/workflows/components/run/RunStatusBadge.js +82 -0
  414. package/dist/modules/workflows/components/run/RunStatusBadge.js.map +7 -0
  415. package/dist/modules/workflows/components/run/RunStepInspector.js +116 -0
  416. package/dist/modules/workflows/components/run/RunStepInspector.js.map +7 -0
  417. package/dist/modules/workflows/components/run/WouldDoReport.js +52 -0
  418. package/dist/modules/workflows/components/run/WouldDoReport.js.map +7 -0
  419. package/dist/modules/workflows/components/run/useAgentLabels.js +28 -0
  420. package/dist/modules/workflows/components/run/useAgentLabels.js.map +7 -0
  421. package/dist/modules/workflows/components/run/useLastRunOverlay.js +89 -0
  422. package/dist/modules/workflows/components/run/useLastRunOverlay.js.map +7 -0
  423. package/dist/modules/workflows/components/run/useLiveAgentActions.js +41 -0
  424. package/dist/modules/workflows/components/run/useLiveAgentActions.js.map +7 -0
  425. package/dist/modules/workflows/components/run/useLiveRunUpdates.js +57 -0
  426. package/dist/modules/workflows/components/run/useLiveRunUpdates.js.map +7 -0
  427. package/dist/modules/workflows/components/settings/CommandSettingsPageClient.js +156 -0
  428. package/dist/modules/workflows/components/settings/CommandSettingsPageClient.js.map +7 -0
  429. package/dist/modules/workflows/components/work-inbox/EntityContextPanel.js +72 -0
  430. package/dist/modules/workflows/components/work-inbox/EntityContextPanel.js.map +7 -0
  431. package/dist/modules/workflows/components/work-inbox/ReassignTaskDialog.js +156 -0
  432. package/dist/modules/workflows/components/work-inbox/ReassignTaskDialog.js.map +7 -0
  433. package/dist/modules/workflows/components/work-inbox/StatusChip.js +46 -0
  434. package/dist/modules/workflows/components/work-inbox/StatusChip.js.map +7 -0
  435. package/dist/modules/workflows/components/work-inbox/TaskActionNotice.js +53 -0
  436. package/dist/modules/workflows/components/work-inbox/TaskActionNotice.js.map +7 -0
  437. package/dist/modules/workflows/components/work-inbox/TaskFormFields.js +261 -0
  438. package/dist/modules/workflows/components/work-inbox/TaskFormFields.js.map +7 -0
  439. package/dist/modules/workflows/components/work-inbox/WorkInboxEmptyState.js +27 -0
  440. package/dist/modules/workflows/components/work-inbox/WorkInboxEmptyState.js.map +7 -0
  441. package/dist/modules/workflows/data/activity-config-schemas.js +191 -0
  442. package/dist/modules/workflows/data/activity-config-schemas.js.map +7 -0
  443. package/dist/modules/workflows/data/activity-config-warnings.js +42 -0
  444. package/dist/modules/workflows/data/activity-config-warnings.js.map +7 -0
  445. package/dist/modules/workflows/data/branching-route-warnings.js +65 -0
  446. package/dist/modules/workflows/data/branching-route-warnings.js.map +7 -0
  447. package/dist/modules/workflows/data/entities.js +144 -4
  448. package/dist/modules/workflows/data/entities.js.map +2 -2
  449. package/dist/modules/workflows/data/metrics-validators.js +35 -0
  450. package/dist/modules/workflows/data/metrics-validators.js.map +7 -0
  451. package/dist/modules/workflows/data/task-primitives.js +14 -0
  452. package/dist/modules/workflows/data/task-primitives.js.map +7 -0
  453. package/dist/modules/workflows/data/validators.js +504 -61
  454. package/dist/modules/workflows/data/validators.js.map +3 -3
  455. package/dist/modules/workflows/di.js +16 -1
  456. package/dist/modules/workflows/di.js.map +2 -2
  457. package/dist/modules/workflows/events.js +66 -8
  458. package/dist/modules/workflows/events.js.map +2 -2
  459. package/dist/modules/workflows/examples/oze-residential-install-60-nodes.json +1545 -0
  460. package/dist/modules/workflows/examples/sales-pipeline-definition.json +35 -35
  461. package/dist/modules/workflows/examples/templates/lead-to-install.json +160 -0
  462. package/dist/modules/workflows/examples/templates/order-approval.json +230 -0
  463. package/dist/modules/workflows/examples/templates/task-escalation.json +110 -0
  464. package/dist/modules/workflows/examples/templates/webhook-integration.json +113 -0
  465. package/dist/modules/workflows/extension-points.js +1 -1
  466. package/dist/modules/workflows/extension-points.js.map +2 -2
  467. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js +144 -0
  468. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js.map +7 -0
  469. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.meta.js +12 -0
  470. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.meta.js.map +7 -0
  471. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.js +114 -0
  472. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.js.map +7 -0
  473. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.meta.js +18 -0
  474. package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.meta.js.map +7 -0
  475. package/dist/modules/workflows/lib/activity-executor.js +505 -137
  476. package/dist/modules/workflows/lib/activity-executor.js.map +3 -3
  477. package/dist/modules/workflows/lib/activity-queue-types.js +3 -1
  478. package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
  479. package/dist/modules/workflows/lib/activity-registry-bootstrap.js +2 -0
  480. package/dist/modules/workflows/lib/activity-registry-bootstrap.js.map +7 -0
  481. package/dist/modules/workflows/lib/activity-registry.js +27 -0
  482. package/dist/modules/workflows/lib/activity-registry.js.map +7 -0
  483. package/dist/modules/workflows/lib/activity-types.js +291 -0
  484. package/dist/modules/workflows/lib/activity-types.js.map +7 -0
  485. package/dist/modules/workflows/lib/activity-worker-handler.js +456 -32
  486. package/dist/modules/workflows/lib/activity-worker-handler.js.map +3 -3
  487. package/dist/modules/workflows/lib/advanced-config.js +31 -0
  488. package/dist/modules/workflows/lib/advanced-config.js.map +7 -0
  489. package/dist/modules/workflows/lib/agent-disposition-task.js +198 -0
  490. package/dist/modules/workflows/lib/agent-disposition-task.js.map +7 -0
  491. package/dist/modules/workflows/lib/agent-outcome-paths.js +82 -0
  492. package/dist/modules/workflows/lib/agent-outcome-paths.js.map +7 -0
  493. package/dist/modules/workflows/lib/agent-result-mapping.js +54 -0
  494. package/dist/modules/workflows/lib/agent-result-mapping.js.map +7 -0
  495. package/dist/modules/workflows/lib/agent-review-inspector.js +61 -0
  496. package/dist/modules/workflows/lib/agent-review-inspector.js.map +7 -0
  497. package/dist/modules/workflows/lib/agent-review.js +66 -0
  498. package/dist/modules/workflows/lib/agent-review.js.map +7 -0
  499. package/dist/modules/workflows/lib/ai-authoring.js +155 -0
  500. package/dist/modules/workflows/lib/ai-authoring.js.map +7 -0
  501. package/dist/modules/workflows/lib/ai-draft-runner.js +43 -0
  502. package/dist/modules/workflows/lib/ai-draft-runner.js.map +7 -0
  503. package/dist/modules/workflows/lib/annotation-events.js +10 -0
  504. package/dist/modules/workflows/lib/annotation-events.js.map +7 -0
  505. package/dist/modules/workflows/lib/branching-routes.js +182 -0
  506. package/dist/modules/workflows/lib/branching-routes.js.map +7 -0
  507. package/dist/modules/workflows/lib/breach-routing.js +50 -0
  508. package/dist/modules/workflows/lib/breach-routing.js.map +7 -0
  509. package/dist/modules/workflows/lib/bulk-replay.js +101 -0
  510. package/dist/modules/workflows/lib/bulk-replay.js.map +7 -0
  511. package/dist/modules/workflows/lib/business-rule-usage.js +91 -0
  512. package/dist/modules/workflows/lib/business-rule-usage.js.map +7 -0
  513. package/dist/modules/workflows/lib/caller-graph.js +53 -0
  514. package/dist/modules/workflows/lib/caller-graph.js.map +7 -0
  515. package/dist/modules/workflows/lib/code-view-apply.js +86 -0
  516. package/dist/modules/workflows/lib/code-view-apply.js.map +7 -0
  517. package/dist/modules/workflows/lib/collect-validation-issues.js +164 -0
  518. package/dist/modules/workflows/lib/collect-validation-issues.js.map +7 -0
  519. package/dist/modules/workflows/lib/compensation-ghosts.js +72 -0
  520. package/dist/modules/workflows/lib/compensation-ghosts.js.map +7 -0
  521. package/dist/modules/workflows/lib/component-guard.js +7 -0
  522. package/dist/modules/workflows/lib/component-guard.js.map +7 -0
  523. package/dist/modules/workflows/lib/condition-handler.js +443 -0
  524. package/dist/modules/workflows/lib/condition-handler.js.map +7 -0
  525. package/dist/modules/workflows/lib/context-ledger.js +448 -0
  526. package/dist/modules/workflows/lib/context-ledger.js.map +7 -0
  527. package/dist/modules/workflows/lib/crud-form-dialogs-flag.js +8 -0
  528. package/dist/modules/workflows/lib/crud-form-dialogs-flag.js.map +7 -0
  529. package/dist/modules/workflows/lib/data-edge-mapping.js +63 -0
  530. package/dist/modules/workflows/lib/data-edge-mapping.js.map +7 -0
  531. package/dist/modules/workflows/lib/definition-context-schema.js +56 -0
  532. package/dist/modules/workflows/lib/definition-context-schema.js.map +7 -0
  533. package/dist/modules/workflows/lib/definition-edit-safety.js +123 -0
  534. package/dist/modules/workflows/lib/definition-edit-safety.js.map +7 -0
  535. package/dist/modules/workflows/lib/definition-error-body.js +33 -0
  536. package/dist/modules/workflows/lib/definition-error-body.js.map +7 -0
  537. package/dist/modules/workflows/lib/definition-evaluation.js +79 -0
  538. package/dist/modules/workflows/lib/definition-evaluation.js.map +7 -0
  539. package/dist/modules/workflows/lib/definition-grant.js +90 -0
  540. package/dist/modules/workflows/lib/definition-grant.js.map +7 -0
  541. package/dist/modules/workflows/lib/definition-json-locations.js +139 -0
  542. package/dist/modules/workflows/lib/definition-json-locations.js.map +7 -0
  543. package/dist/modules/workflows/lib/definition-payload.js +31 -0
  544. package/dist/modules/workflows/lib/definition-payload.js.map +7 -0
  545. package/dist/modules/workflows/lib/draft-restore.js +49 -0
  546. package/dist/modules/workflows/lib/draft-restore.js.map +7 -0
  547. package/dist/modules/workflows/lib/dry-run.js +106 -0
  548. package/dist/modules/workflows/lib/dry-run.js.map +7 -0
  549. package/dist/modules/workflows/lib/duration.js +66 -17
  550. package/dist/modules/workflows/lib/duration.js.map +2 -2
  551. package/dist/modules/workflows/lib/edge-reattachment.js +79 -0
  552. package/dist/modules/workflows/lib/edge-reattachment.js.map +7 -0
  553. package/dist/modules/workflows/lib/edgeFormTransforms.js +7 -11
  554. package/dist/modules/workflows/lib/edgeFormTransforms.js.map +2 -2
  555. package/dist/modules/workflows/lib/editor-annotations.js +195 -0
  556. package/dist/modules/workflows/lib/editor-annotations.js.map +7 -0
  557. package/dist/modules/workflows/lib/editor-commands.js +103 -0
  558. package/dist/modules/workflows/lib/editor-commands.js.map +7 -0
  559. package/dist/modules/workflows/lib/editor-history.js +51 -0
  560. package/dist/modules/workflows/lib/editor-history.js.map +7 -0
  561. package/dist/modules/workflows/lib/endpoint-catalog.js +181 -0
  562. package/dist/modules/workflows/lib/endpoint-catalog.js.map +7 -0
  563. package/dist/modules/workflows/lib/endpoint-path.js +90 -0
  564. package/dist/modules/workflows/lib/endpoint-path.js.map +7 -0
  565. package/dist/modules/workflows/lib/engine-version.js +42 -0
  566. package/dist/modules/workflows/lib/engine-version.js.map +7 -0
  567. package/dist/modules/workflows/lib/error-handler.js +132 -0
  568. package/dist/modules/workflows/lib/error-handler.js.map +7 -0
  569. package/dist/modules/workflows/lib/error-routing.js +104 -0
  570. package/dist/modules/workflows/lib/error-routing.js.map +7 -0
  571. package/dist/modules/workflows/lib/event-logger.js +23 -0
  572. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  573. package/dist/modules/workflows/lib/expression-refs.js +168 -0
  574. package/dist/modules/workflows/lib/expression-refs.js.map +7 -0
  575. package/dist/modules/workflows/lib/failure-grouping.js +62 -0
  576. package/dist/modules/workflows/lib/failure-grouping.js.map +7 -0
  577. package/dist/modules/workflows/lib/find-definition.js +1 -0
  578. package/dist/modules/workflows/lib/find-definition.js.map +2 -2
  579. package/dist/modules/workflows/lib/flow-logic-warnings.js +338 -0
  580. package/dist/modules/workflows/lib/flow-logic-warnings.js.map +7 -0
  581. package/dist/modules/workflows/lib/graph-utils.js +328 -77
  582. package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
  583. package/dist/modules/workflows/lib/icon-search.js +32 -0
  584. package/dist/modules/workflows/lib/icon-search.js.map +7 -0
  585. package/dist/modules/workflows/lib/insert-at-cursor.js +26 -0
  586. package/dist/modules/workflows/lib/insert-at-cursor.js.map +7 -0
  587. package/dist/modules/workflows/lib/instance-date-filter.js +28 -0
  588. package/dist/modules/workflows/lib/instance-date-filter.js.map +7 -0
  589. package/dist/modules/workflows/lib/interpolation-pipeline.js +271 -0
  590. package/dist/modules/workflows/lib/interpolation-pipeline.js.map +7 -0
  591. package/dist/modules/workflows/lib/ledger-drag.js +28 -0
  592. package/dist/modules/workflows/lib/ledger-drag.js.map +7 -0
  593. package/dist/modules/workflows/lib/ledger-entry-display.js +66 -0
  594. package/dist/modules/workflows/lib/ledger-entry-display.js.map +7 -0
  595. package/dist/modules/workflows/lib/ledger-schema-flatten.js +82 -0
  596. package/dist/modules/workflows/lib/ledger-schema-flatten.js.map +7 -0
  597. package/dist/modules/workflows/lib/metrics/definition-metrics.js +110 -0
  598. package/dist/modules/workflows/lib/metrics/definition-metrics.js.map +7 -0
  599. package/dist/modules/workflows/lib/metrics/metrics-display.js +26 -0
  600. package/dist/modules/workflows/lib/metrics/metrics-display.js.map +7 -0
  601. package/dist/modules/workflows/lib/metrics/rollup-schedule.js +7 -0
  602. package/dist/modules/workflows/lib/metrics/rollup-schedule.js.map +7 -0
  603. package/dist/modules/workflows/lib/metrics/rollup-service.js +160 -0
  604. package/dist/modules/workflows/lib/metrics/rollup-service.js.map +7 -0
  605. package/dist/modules/workflows/lib/node-config-summary.js +128 -0
  606. package/dist/modules/workflows/lib/node-config-summary.js.map +7 -0
  607. package/dist/modules/workflows/lib/node-geometry.js +53 -0
  608. package/dist/modules/workflows/lib/node-geometry.js.map +7 -0
  609. package/dist/modules/workflows/lib/node-nudge.js +44 -0
  610. package/dist/modules/workflows/lib/node-nudge.js.map +7 -0
  611. package/dist/modules/workflows/lib/node-outcome-rows.js +88 -0
  612. package/dist/modules/workflows/lib/node-outcome-rows.js.map +7 -0
  613. package/dist/modules/workflows/lib/node-placement.js +55 -0
  614. package/dist/modules/workflows/lib/node-placement.js.map +7 -0
  615. package/dist/modules/workflows/lib/node-type-icons.js +54 -13
  616. package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
  617. package/dist/modules/workflows/lib/nodeFormTransforms.js +329 -19
  618. package/dist/modules/workflows/lib/nodeFormTransforms.js.map +2 -2
  619. package/dist/modules/workflows/lib/outcome-routing.js +158 -0
  620. package/dist/modules/workflows/lib/outcome-routing.js.map +7 -0
  621. package/dist/modules/workflows/lib/owned-definition.js +107 -0
  622. package/dist/modules/workflows/lib/owned-definition.js.map +7 -0
  623. package/dist/modules/workflows/lib/owned-node-changes.js +10 -0
  624. package/dist/modules/workflows/lib/owned-node-changes.js.map +7 -0
  625. package/dist/modules/workflows/lib/palette-drag.js +36 -0
  626. package/dist/modules/workflows/lib/palette-drag.js.map +7 -0
  627. package/dist/modules/workflows/lib/palette-drop.js +45 -0
  628. package/dist/modules/workflows/lib/palette-drop.js.map +7 -0
  629. package/dist/modules/workflows/lib/parallel-handler.js +57 -2
  630. package/dist/modules/workflows/lib/parallel-handler.js.map +2 -2
  631. package/dist/modules/workflows/lib/port-contract.js +54 -0
  632. package/dist/modules/workflows/lib/port-contract.js.map +7 -0
  633. package/dist/modules/workflows/lib/portal-task-access.js +89 -0
  634. package/dist/modules/workflows/lib/portal-task-access.js.map +7 -0
  635. package/dist/modules/workflows/lib/rerun-from-step.js +65 -0
  636. package/dist/modules/workflows/lib/rerun-from-step.js.map +7 -0
  637. package/dist/modules/workflows/lib/route-chip-events.js +23 -0
  638. package/dist/modules/workflows/lib/route-chip-events.js.map +7 -0
  639. package/dist/modules/workflows/lib/route-chips.js +91 -0
  640. package/dist/modules/workflows/lib/route-chips.js.map +7 -0
  641. package/dist/modules/workflows/lib/route-edge.js +17 -0
  642. package/dist/modules/workflows/lib/route-edge.js.map +7 -0
  643. package/dist/modules/workflows/lib/route-kinds.js +67 -0
  644. package/dist/modules/workflows/lib/route-kinds.js.map +7 -0
  645. package/dist/modules/workflows/lib/route-priority.js +104 -0
  646. package/dist/modules/workflows/lib/route-priority.js.map +7 -0
  647. package/dist/modules/workflows/lib/run-duration.js +44 -0
  648. package/dist/modules/workflows/lib/run-duration.js.map +7 -0
  649. package/dist/modules/workflows/lib/run-event-tone.js +25 -0
  650. package/dist/modules/workflows/lib/run-event-tone.js.map +7 -0
  651. package/dist/modules/workflows/lib/run-execution.js +305 -0
  652. package/dist/modules/workflows/lib/run-execution.js.map +7 -0
  653. package/dist/modules/workflows/lib/run-gantt.js +180 -0
  654. package/dist/modules/workflows/lib/run-gantt.js.map +7 -0
  655. package/dist/modules/workflows/lib/run-outcome-evidence.js +33 -0
  656. package/dist/modules/workflows/lib/run-outcome-evidence.js.map +7 -0
  657. package/dist/modules/workflows/lib/run-outcome.js +48 -0
  658. package/dist/modules/workflows/lib/run-outcome.js.map +7 -0
  659. package/dist/modules/workflows/lib/sample-resolver.js +71 -0
  660. package/dist/modules/workflows/lib/sample-resolver.js.map +7 -0
  661. package/dist/modules/workflows/lib/seeds.js +1 -1
  662. package/dist/modules/workflows/lib/seeds.js.map +2 -2
  663. package/dist/modules/workflows/lib/server-output-contract.js +65 -0
  664. package/dist/modules/workflows/lib/server-output-contract.js.map +7 -0
  665. package/dist/modules/workflows/lib/set-variable.js +47 -0
  666. package/dist/modules/workflows/lib/set-variable.js.map +7 -0
  667. package/dist/modules/workflows/lib/signal-handler.js +63 -4
  668. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  669. package/dist/modules/workflows/lib/start-fixtures.js +42 -0
  670. package/dist/modules/workflows/lib/start-fixtures.js.map +7 -0
  671. package/dist/modules/workflows/lib/status-colors.js +153 -22
  672. package/dist/modules/workflows/lib/status-colors.js.map +2 -2
  673. package/dist/modules/workflows/lib/step-handler.js +529 -53
  674. package/dist/modules/workflows/lib/step-handler.js.map +3 -3
  675. package/dist/modules/workflows/lib/step-presentation.js +147 -0
  676. package/dist/modules/workflows/lib/step-presentation.js.map +7 -0
  677. package/dist/modules/workflows/lib/step-through.js +26 -0
  678. package/dist/modules/workflows/lib/step-through.js.map +7 -0
  679. package/dist/modules/workflows/lib/step-type-conversion.js +167 -0
  680. package/dist/modules/workflows/lib/step-type-conversion.js.map +7 -0
  681. package/dist/modules/workflows/lib/subgraph-clipboard.js +114 -0
  682. package/dist/modules/workflows/lib/subgraph-clipboard.js.map +7 -0
  683. package/dist/modules/workflows/lib/task-decision-context.js +38 -0
  684. package/dist/modules/workflows/lib/task-decision-context.js.map +7 -0
  685. package/dist/modules/workflows/lib/task-decisions.js +49 -0
  686. package/dist/modules/workflows/lib/task-decisions.js.map +7 -0
  687. package/dist/modules/workflows/lib/task-entity-access.js +62 -0
  688. package/dist/modules/workflows/lib/task-entity-access.js.map +7 -0
  689. package/dist/modules/workflows/lib/task-entity-aliases.js +39 -0
  690. package/dist/modules/workflows/lib/task-entity-aliases.js.map +7 -0
  691. package/dist/modules/workflows/lib/task-entity-types.js +36 -0
  692. package/dist/modules/workflows/lib/task-entity-types.js.map +7 -0
  693. package/dist/modules/workflows/lib/task-form-registry.js +33 -0
  694. package/dist/modules/workflows/lib/task-form-registry.js.map +7 -0
  695. package/dist/modules/workflows/lib/task-form-schema.js +75 -0
  696. package/dist/modules/workflows/lib/task-form-schema.js.map +7 -0
  697. package/dist/modules/workflows/lib/task-handler.js +251 -32
  698. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  699. package/dist/modules/workflows/lib/task-inspector-config.js +182 -0
  700. package/dist/modules/workflows/lib/task-inspector-config.js.map +7 -0
  701. package/dist/modules/workflows/lib/task-list-query.js +19 -0
  702. package/dist/modules/workflows/lib/task-list-query.js.map +7 -0
  703. package/dist/modules/workflows/lib/task-notifications.js +119 -0
  704. package/dist/modules/workflows/lib/task-notifications.js.map +7 -0
  705. package/dist/modules/workflows/lib/task-permission-settings.js +43 -0
  706. package/dist/modules/workflows/lib/task-permission-settings.js.map +7 -0
  707. package/dist/modules/workflows/lib/task-presets.js +35 -0
  708. package/dist/modules/workflows/lib/task-presets.js.map +7 -0
  709. package/dist/modules/workflows/lib/task-quick-action.js +45 -0
  710. package/dist/modules/workflows/lib/task-quick-action.js.map +7 -0
  711. package/dist/modules/workflows/lib/task-resolution.js +120 -0
  712. package/dist/modules/workflows/lib/task-resolution.js.map +7 -0
  713. package/dist/modules/workflows/lib/task-sla.js +357 -0
  714. package/dist/modules/workflows/lib/task-sla.js.map +7 -0
  715. package/dist/modules/workflows/lib/task-visibility-request.js +266 -0
  716. package/dist/modules/workflows/lib/task-visibility-request.js.map +7 -0
  717. package/dist/modules/workflows/lib/task-visibility.js +194 -0
  718. package/dist/modules/workflows/lib/task-visibility.js.map +7 -0
  719. package/dist/modules/workflows/lib/timer-handler.js +3 -1
  720. package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
  721. package/dist/modules/workflows/lib/transition-handler.js +148 -20
  722. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  723. package/dist/modules/workflows/lib/trigger-node.js +121 -0
  724. package/dist/modules/workflows/lib/trigger-node.js.map +7 -0
  725. package/dist/modules/workflows/lib/visual-editor-navigation.js +14 -0
  726. package/dist/modules/workflows/lib/visual-editor-navigation.js.map +7 -0
  727. package/dist/modules/workflows/lib/work-inbox/empty-state.js +52 -0
  728. package/dist/modules/workflows/lib/work-inbox/empty-state.js.map +7 -0
  729. package/dist/modules/workflows/lib/work-inbox/entity-links.js +63 -0
  730. package/dist/modules/workflows/lib/work-inbox/entity-links.js.map +7 -0
  731. package/dist/modules/workflows/lib/work-inbox/navigation.js +11 -0
  732. package/dist/modules/workflows/lib/work-inbox/navigation.js.map +7 -0
  733. package/dist/modules/workflows/lib/work-inbox/presentation.js +90 -0
  734. package/dist/modules/workflows/lib/work-inbox/presentation.js.map +7 -0
  735. package/dist/modules/workflows/lib/work-inbox/provider.js +118 -0
  736. package/dist/modules/workflows/lib/work-inbox/provider.js.map +7 -0
  737. package/dist/modules/workflows/lib/work-inbox/query.js +70 -0
  738. package/dist/modules/workflows/lib/work-inbox/query.js.map +7 -0
  739. package/dist/modules/workflows/lib/work-inbox/service.js +56 -0
  740. package/dist/modules/workflows/lib/work-inbox/service.js.map +7 -0
  741. package/dist/modules/workflows/lib/work-inbox/user-task-source.js +149 -0
  742. package/dist/modules/workflows/lib/work-inbox/user-task-source.js.map +7 -0
  743. package/dist/modules/workflows/lib/workflow-command-enablement.js +57 -0
  744. package/dist/modules/workflows/lib/workflow-command-enablement.js.map +7 -0
  745. package/dist/modules/workflows/lib/workflow-command-settings.js +54 -0
  746. package/dist/modules/workflows/lib/workflow-command-settings.js.map +7 -0
  747. package/dist/modules/workflows/lib/workflow-executor.js +658 -6
  748. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  749. package/dist/modules/workflows/lib/workflow-function-registry.js +40 -0
  750. package/dist/modules/workflows/lib/workflow-function-registry.js.map +7 -0
  751. package/dist/modules/workflows/lib/workflow-safe-commands.js +11 -1
  752. package/dist/modules/workflows/lib/workflow-safe-commands.js.map +2 -2
  753. package/dist/modules/workflows/lib/workflow-templates.js +69 -0
  754. package/dist/modules/workflows/lib/workflow-templates.js.map +7 -0
  755. package/dist/modules/workflows/migrations/Migration20260626214855_workflows.js +15 -0
  756. package/dist/modules/workflows/migrations/Migration20260626214855_workflows.js.map +7 -0
  757. package/dist/modules/workflows/migrations/Migration20260626222424_workflows.js +17 -0
  758. package/dist/modules/workflows/migrations/Migration20260626222424_workflows.js.map +7 -0
  759. package/dist/modules/workflows/migrations/Migration20260727074335_workflows.js +15 -0
  760. package/dist/modules/workflows/migrations/Migration20260727074335_workflows.js.map +7 -0
  761. package/dist/modules/workflows/migrations/Migration20260728104038_workflows.js +13 -0
  762. package/dist/modules/workflows/migrations/Migration20260728104038_workflows.js.map +7 -0
  763. package/dist/modules/workflows/migrations/Migration20260728163001_workflows.js +15 -0
  764. package/dist/modules/workflows/migrations/Migration20260728163001_workflows.js.map +7 -0
  765. package/dist/modules/workflows/migrations/Migration20260729061736_workflows.js +13 -0
  766. package/dist/modules/workflows/migrations/Migration20260729061736_workflows.js.map +7 -0
  767. package/dist/modules/workflows/migrations/Migration20260729192652_workflows.js +12 -0
  768. package/dist/modules/workflows/migrations/Migration20260729192652_workflows.js.map +7 -0
  769. package/dist/modules/workflows/migrations/Migration20260730085000_workflows.js +13 -0
  770. package/dist/modules/workflows/migrations/Migration20260730085000_workflows.js.map +7 -0
  771. package/dist/modules/workflows/migrations/Migration20260730092706_workflows.js +13 -0
  772. package/dist/modules/workflows/migrations/Migration20260730092706_workflows.js.map +7 -0
  773. package/dist/modules/workflows/notifications.js +38 -10
  774. package/dist/modules/workflows/notifications.js.map +2 -2
  775. package/dist/modules/workflows/setup.js +81 -1
  776. package/dist/modules/workflows/setup.js.map +2 -2
  777. package/dist/modules/workflows/subscribers/task-assigned-notification.js +19 -27
  778. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +2 -2
  779. package/dist/modules/workflows/subscribers/task-deadline-breached-notification.js +24 -0
  780. package/dist/modules/workflows/subscribers/task-deadline-breached-notification.js.map +7 -0
  781. package/dist/modules/workflows/subscribers/task-reminder-notification.js +24 -0
  782. package/dist/modules/workflows/subscribers/task-reminder-notification.js.map +7 -0
  783. package/dist/modules/workflows/widgets/injection/pending-work/widget.client.js +73 -0
  784. package/dist/modules/workflows/widgets/injection/pending-work/widget.client.js.map +7 -0
  785. package/dist/modules/workflows/widgets/injection/pending-work/widget.js +17 -0
  786. package/dist/modules/workflows/widgets/injection/pending-work/widget.js.map +7 -0
  787. package/dist/modules/workflows/widgets/injection-table.js +26 -0
  788. package/dist/modules/workflows/widgets/injection-table.js.map +2 -2
  789. package/dist/modules/workflows/workers/workflow-activities.worker.js +61 -39
  790. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  791. package/dist/modules/workflows/workers/workflow-definition-metric-rollup.worker.js +40 -0
  792. package/dist/modules/workflows/workers/workflow-definition-metric-rollup.worker.js.map +7 -0
  793. package/dist/modules/workflows/workers/workflow-instance-bulk-replay.js +43 -0
  794. package/dist/modules/workflows/workers/workflow-instance-bulk-replay.js.map +7 -0
  795. package/dist/modules/workflows/workers/workflow-invoke-agent.worker.js +30 -0
  796. package/dist/modules/workflows/workers/workflow-invoke-agent.worker.js.map +7 -0
  797. package/generated/entities/action_log/index.ts +1 -0
  798. package/generated/entities/user/index.ts +1 -0
  799. package/generated/entities/user_task/index.ts +7 -0
  800. package/generated/entities/workflow_definition/index.ts +3 -0
  801. package/generated/entities/workflow_definition_draft/index.ts +11 -0
  802. package/generated/entities/workflow_definition_metric_rollup/index.ts +10 -0
  803. package/generated/entities/workflow_instance/index.ts +2 -0
  804. package/generated/entities.ids.generated.ts +4 -1
  805. package/generated/entity-fields-registry.ts +39 -0
  806. package/jest.setup.ts +13 -0
  807. package/package.json +8 -7
  808. package/src/bootstrap.ts +13 -3
  809. package/src/helpers/integration/workflowsFixtures.ts +765 -5
  810. package/src/helpers/integration/workflowsUi.ts +318 -0
  811. package/src/modules/attachments/lib/createFromBuffer.ts +120 -0
  812. package/src/modules/audit_logs/data/entities.ts +12 -0
  813. package/src/modules/audit_logs/data/validators.ts +1 -0
  814. package/src/modules/audit_logs/lib/projections.ts +5 -1
  815. package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +26 -0
  816. package/src/modules/audit_logs/migrations/Migration20260625120000.ts +15 -0
  817. package/src/modules/audit_logs/services/actionLogService.ts +3 -0
  818. package/src/modules/auth/data/entities.ts +21 -0
  819. package/src/modules/auth/i18n/de.json +31 -0
  820. package/src/modules/auth/i18n/en.json +31 -0
  821. package/src/modules/auth/i18n/es.json +31 -0
  822. package/src/modules/auth/i18n/ko.json +31 -0
  823. package/src/modules/auth/i18n/pl.json +31 -0
  824. package/src/modules/auth/lib/executionPrincipal.ts +235 -0
  825. package/src/modules/auth/migrations/.snapshot-open-mercato.json +16 -0
  826. package/src/modules/auth/migrations/Migration20260625050000.ts +21 -0
  827. package/src/modules/business_rules/components/InlineRuleEditor.tsx +231 -0
  828. package/src/modules/business_rules/data/validators.ts +6 -0
  829. package/src/modules/business_rules/i18n/de.json +4 -0
  830. package/src/modules/business_rules/i18n/en.json +4 -0
  831. package/src/modules/business_rules/i18n/es.json +4 -0
  832. package/src/modules/business_rules/i18n/ko.json +4 -0
  833. package/src/modules/business_rules/i18n/pl.json +4 -0
  834. package/src/modules/business_rules/lib/rule-engine.ts +15 -1
  835. package/src/modules/catalog/commands/products.ts +12 -0
  836. package/src/modules/catalog/i18n/de.json +1 -0
  837. package/src/modules/catalog/i18n/en.json +1 -0
  838. package/src/modules/catalog/i18n/es.json +1 -0
  839. package/src/modules/catalog/i18n/ko.json +1 -0
  840. package/src/modules/catalog/i18n/pl.json +1 -0
  841. package/src/modules/catalog/workflows.ts +35 -0
  842. package/src/modules/customer_accounts/AGENTS.md +11 -0
  843. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +2 -0
  844. package/src/modules/customer_accounts/cli.ts +96 -0
  845. package/src/modules/customer_accounts/i18n/de.json +5 -0
  846. package/src/modules/customer_accounts/i18n/en.json +5 -0
  847. package/src/modules/customer_accounts/i18n/es.json +5 -0
  848. package/src/modules/customer_accounts/i18n/ko.json +5 -0
  849. package/src/modules/customer_accounts/i18n/pl.json +5 -0
  850. package/src/modules/customer_accounts/lib/customerRoleAclSync.ts +92 -0
  851. package/src/modules/customer_accounts/setup.ts +15 -3
  852. package/src/modules/customers/commands/deals.ts +5 -0
  853. package/src/modules/customers/components/detail/ChangelogEntryRow.tsx +4 -2
  854. package/src/modules/customers/components/detail/utils.ts +2 -0
  855. package/src/modules/customers/events.ts +21 -3
  856. package/src/modules/customers/i18n/de.json +4 -0
  857. package/src/modules/customers/i18n/en.json +4 -0
  858. package/src/modules/customers/i18n/es.json +4 -0
  859. package/src/modules/customers/i18n/ko.json +4 -0
  860. package/src/modules/customers/i18n/pl.json +4 -0
  861. package/src/modules/customers/lib/link-workflow-task-handler.ts +136 -0
  862. package/src/modules/customers/lib/todoCompatibility.ts +4 -1
  863. package/src/modules/customers/lib/workflowTaskLink.ts +23 -0
  864. package/src/modules/customers/subscribers/link-workflow-task.ts +19 -0
  865. package/src/modules/customers/workflows.ts +57 -0
  866. package/src/modules/entities/api/records.ts +18 -62
  867. package/src/modules/entities/lib/entityClassification.ts +102 -0
  868. package/src/modules/sales/commands/documents.ts +46 -0
  869. package/src/modules/sales/events.ts +20 -2
  870. package/src/modules/sales/i18n/de.json +2 -1
  871. package/src/modules/sales/i18n/en.json +2 -1
  872. package/src/modules/sales/i18n/es.json +2 -1
  873. package/src/modules/sales/i18n/ko.json +2 -1
  874. package/src/modules/sales/i18n/pl.json +2 -1
  875. package/src/modules/sales/workflows.ts +12 -1
  876. package/src/modules/seeds/README.md +86 -0
  877. package/src/modules/seeds/cli.ts +220 -0
  878. package/src/modules/seeds/examples/sample-seed.json +26 -0
  879. package/src/modules/seeds/index.ts +11 -0
  880. package/src/modules/workflows/AGENTS.md +851 -10
  881. package/src/modules/workflows/acl.ts +96 -0
  882. package/src/modules/workflows/ai-agents.ts +80 -0
  883. package/src/modules/workflows/ai-tools/authoring-pack.ts +798 -0
  884. package/src/modules/workflows/ai-tools/types.ts +117 -0
  885. package/src/modules/workflows/ai-tools.ts +20 -0
  886. package/src/modules/workflows/api/command-settings/route.ts +171 -0
  887. package/src/modules/workflows/api/commands/route.ts +109 -0
  888. package/src/modules/workflows/api/definitions/[id]/callers/route.ts +95 -0
  889. package/src/modules/workflows/api/definitions/[id]/context-schema/route.ts +187 -0
  890. package/src/modules/workflows/api/definitions/[id]/customize/route.ts +6 -1
  891. package/src/modules/workflows/api/definitions/[id]/draft/route.ts +395 -0
  892. package/src/modules/workflows/api/definitions/[id]/publish/route.ts +250 -0
  893. package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +5 -0
  894. package/src/modules/workflows/api/definitions/[id]/route.ts +107 -7
  895. package/src/modules/workflows/api/definitions/[id]/test-step/route.ts +288 -0
  896. package/src/modules/workflows/api/definitions/generate/route.ts +335 -0
  897. package/src/modules/workflows/api/definitions/route.ts +88 -113
  898. package/src/modules/workflows/api/definitions/serialize.ts +9 -0
  899. package/src/modules/workflows/api/endpoints/route.ts +88 -0
  900. package/src/modules/workflows/api/functions/route.ts +91 -0
  901. package/src/modules/workflows/api/grantable-features/route.ts +102 -0
  902. package/src/modules/workflows/api/instances/[id]/context/route.ts +214 -0
  903. package/src/modules/workflows/api/instances/[id]/rerun-step/route.ts +226 -0
  904. package/src/modules/workflows/api/instances/[id]/retry/route.ts +18 -2
  905. package/src/modules/workflows/api/instances/[id]/step-through/route.ts +195 -0
  906. package/src/modules/workflows/api/instances/[id]/steps/route.ts +160 -0
  907. package/src/modules/workflows/api/instances/[id]/would-do/route.ts +216 -0
  908. package/src/modules/workflows/api/instances/bulk-replay/route.ts +141 -0
  909. package/src/modules/workflows/api/instances/failure-queue/route.ts +197 -0
  910. package/src/modules/workflows/api/instances/route.ts +135 -3
  911. package/src/modules/workflows/api/metrics/definitions/route.ts +262 -0
  912. package/src/modules/workflows/api/openapi.ts +549 -2
  913. package/src/modules/workflows/api/portal/tasks/[id]/complete/route.ts +160 -0
  914. package/src/modules/workflows/api/portal/tasks/[id]/route.ts +124 -0
  915. package/src/modules/workflows/api/portal/tasks/route.ts +157 -0
  916. package/src/modules/workflows/api/rule-usage/route.ts +94 -0
  917. package/src/modules/workflows/api/task-settings/route.ts +138 -0
  918. package/src/modules/workflows/api/tasks/[id]/claim/route.ts +42 -17
  919. package/src/modules/workflows/api/tasks/[id]/complete/route.ts +47 -15
  920. package/src/modules/workflows/api/tasks/[id]/reassign/route.ts +197 -0
  921. package/src/modules/workflows/api/tasks/[id]/route.ts +57 -6
  922. package/src/modules/workflows/api/tasks/[id]/unclaim/route.ts +132 -0
  923. package/src/modules/workflows/api/tasks/route.ts +60 -5
  924. package/src/modules/workflows/api/tasks/serialize.ts +119 -0
  925. package/src/modules/workflows/api/templates/route.ts +87 -0
  926. package/src/modules/workflows/api/work-inbox/next/route.ts +170 -0
  927. package/src/modules/workflows/api/work-inbox/route.ts +153 -0
  928. package/src/modules/workflows/backend/config/workflows/page.meta.ts +33 -0
  929. package/src/modules/workflows/backend/config/workflows/page.tsx +12 -0
  930. package/src/modules/workflows/backend/definitions/[id]/page.tsx +19 -343
  931. package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
  932. package/src/modules/workflows/backend/definitions/create/page.tsx +19 -59
  933. package/src/modules/workflows/backend/definitions/page.tsx +156 -76
  934. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3129 -584
  935. package/src/modules/workflows/backend/instances/[id]/page.meta.ts +1 -1
  936. package/src/modules/workflows/backend/instances/[id]/page.tsx +711 -539
  937. package/src/modules/workflows/backend/instances/failure-queue/page.meta.ts +16 -0
  938. package/src/modules/workflows/backend/instances/failure-queue/page.tsx +311 -0
  939. package/src/modules/workflows/backend/instances/page.meta.ts +1 -1
  940. package/src/modules/workflows/backend/instances/page.tsx +218 -38
  941. package/src/modules/workflows/backend/tasks/[id]/page.tsx +639 -400
  942. package/src/modules/workflows/backend/tasks/page.meta.ts +7 -0
  943. package/src/modules/workflows/backend/tasks/page.tsx +20 -333
  944. package/src/modules/workflows/backend/work-inbox/page.meta.ts +15 -0
  945. package/src/modules/workflows/backend/work-inbox/page.tsx +506 -0
  946. package/src/modules/workflows/cli.ts +1 -1
  947. package/src/modules/workflows/commands/tasks.ts +146 -0
  948. package/src/modules/workflows/components/ActivitiesEditor.tsx +91 -114
  949. package/src/modules/workflows/components/ActivityEditDialog.tsx +244 -0
  950. package/src/modules/workflows/components/AgentSelector.tsx +200 -0
  951. package/src/modules/workflows/components/AnnotationEditDialog.tsx +157 -0
  952. package/src/modules/workflows/components/BusinessRuleUsagePanel.tsx +106 -0
  953. package/src/modules/workflows/components/BusinessRulesSelector.tsx +71 -17
  954. package/src/modules/workflows/components/ConfigJsonTextarea.tsx +111 -0
  955. package/src/modules/workflows/components/ContextSchemaEditor.tsx +165 -0
  956. package/src/modules/workflows/components/DefinitionErrorHandlerField.tsx +133 -0
  957. package/src/modules/workflows/components/DefinitionMetadataDrawer.tsx +456 -0
  958. package/src/modules/workflows/components/DefinitionMetricsCells.tsx +212 -0
  959. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +196 -95
  960. package/src/modules/workflows/components/EdgeEditDialog.tsx +15 -16
  961. package/src/modules/workflows/components/EdgeEditDialogCrudForm.tsx +130 -80
  962. package/src/modules/workflows/components/InputDataPanel.tsx +177 -0
  963. package/src/modules/workflows/components/InspectorPanel.tsx +250 -0
  964. package/src/modules/workflows/components/NodeEditDialog.tsx +444 -38
  965. package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +848 -178
  966. package/src/modules/workflows/components/StepsEditor.tsx +9 -2
  967. package/src/modules/workflows/components/TemplateGalleryDialog.tsx +205 -0
  968. package/src/modules/workflows/components/TransitionsEditor.tsx +98 -89
  969. package/src/modules/workflows/components/TriggersDialog.tsx +83 -0
  970. package/src/modules/workflows/components/TriggersEditor.tsx +363 -0
  971. package/src/modules/workflows/components/WorkflowAiDraftDialog.tsx +383 -0
  972. package/src/modules/workflows/components/WorkflowCodeView.tsx +257 -0
  973. package/src/modules/workflows/components/WorkflowCommandPalette.tsx +82 -0
  974. package/src/modules/workflows/components/WorkflowCompensationGhostEdge.tsx +78 -0
  975. package/src/modules/workflows/components/WorkflowDataMappingEdge.tsx +46 -0
  976. package/src/modules/workflows/components/WorkflowGraph.tsx +54 -1
  977. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +463 -37
  978. package/src/modules/workflows/components/WorkflowIconPicker.tsx +144 -0
  979. package/src/modules/workflows/components/WorkflowLegend.tsx +59 -33
  980. package/src/modules/workflows/components/WorkflowNodeCard.tsx +355 -28
  981. package/src/modules/workflows/components/WorkflowRouteChips.tsx +145 -0
  982. package/src/modules/workflows/components/WorkflowSelector.tsx +33 -14
  983. package/src/modules/workflows/components/WorkflowTransitionEdge.tsx +83 -10
  984. package/src/modules/workflows/components/WorkflowTransitionLabel.tsx +13 -2
  985. package/src/modules/workflows/components/fields/ActivityArrayEditor.tsx +120 -30
  986. package/src/modules/workflows/components/fields/ActivityConfigFields.tsx +675 -0
  987. package/src/modules/workflows/components/fields/ActivityTestPanel.tsx +250 -0
  988. package/src/modules/workflows/components/fields/AgentInvokeConfigField.tsx +580 -0
  989. package/src/modules/workflows/components/fields/AgentReviewOnBreachField.tsx +88 -0
  990. package/src/modules/workflows/components/fields/BranchingRoutesEditor.tsx +323 -0
  991. package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +36 -4
  992. package/src/modules/workflows/components/fields/CommandPicker.tsx +158 -0
  993. package/src/modules/workflows/components/fields/EndpointPicker.tsx +330 -0
  994. package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +2 -2
  995. package/src/modules/workflows/components/fields/FunctionPicker.tsx +68 -0
  996. package/src/modules/workflows/components/fields/MappingArrayEditor.tsx +46 -12
  997. package/src/modules/workflows/components/fields/PortFieldArrayEditor.tsx +255 -0
  998. package/src/modules/workflows/components/fields/RolesMultiSelect.tsx +68 -0
  999. package/src/modules/workflows/components/fields/RouteOrderEditor.tsx +169 -0
  1000. package/src/modules/workflows/components/fields/SchemaBuilderDialog.tsx +139 -0
  1001. package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +2 -2
  1002. package/src/modules/workflows/components/fields/TaskAssignmentField.tsx +355 -0
  1003. package/src/modules/workflows/components/fields/TaskDeadlineFields.tsx +172 -0
  1004. package/src/modules/workflows/components/fields/TaskDecisionsField.tsx +294 -0
  1005. package/src/modules/workflows/components/fields/TaskEntityBindingsField.tsx +156 -0
  1006. package/src/modules/workflows/components/fields/TemplateTextControl.tsx +85 -0
  1007. package/src/modules/workflows/components/fields/VariablePickerButton.tsx +177 -0
  1008. package/src/modules/workflows/components/fields/ledgerDropTarget.ts +55 -0
  1009. package/src/modules/workflows/components/fields/useActivityTypeOptions.ts +19 -0
  1010. package/src/modules/workflows/components/formConfig.tsx +84 -10
  1011. package/src/modules/workflows/components/mobile/MobileDefinitionDetail.tsx +5 -0
  1012. package/src/modules/workflows/components/mobile/MobileMetadataSheet.tsx +10 -0
  1013. package/src/modules/workflows/components/mobile/MobileTaskForm.tsx +55 -19
  1014. package/src/modules/workflows/components/mobile/MobileVisualEditor.tsx +49 -40
  1015. package/src/modules/workflows/components/nodes/AnnotationGroupNode.tsx +81 -0
  1016. package/src/modules/workflows/components/nodes/AutomatedNode.tsx +34 -17
  1017. package/src/modules/workflows/components/nodes/EndNode.tsx +15 -14
  1018. package/src/modules/workflows/components/nodes/ErrorOutputHandle.tsx +32 -0
  1019. package/src/modules/workflows/components/nodes/IfElseNode.tsx +64 -0
  1020. package/src/modules/workflows/components/nodes/InvokeAgentNode.tsx +180 -0
  1021. package/src/modules/workflows/components/nodes/NodeOutcomeRows.tsx +143 -0
  1022. package/src/modules/workflows/components/nodes/ParallelForkNode.tsx +28 -15
  1023. package/src/modules/workflows/components/nodes/ParallelJoinNode.tsx +28 -15
  1024. package/src/modules/workflows/components/nodes/StartNode.tsx +78 -18
  1025. package/src/modules/workflows/components/nodes/StickyNoteNode.tsx +65 -0
  1026. package/src/modules/workflows/components/nodes/SubWorkflowNode.tsx +124 -23
  1027. package/src/modules/workflows/components/nodes/SwitchNode.tsx +64 -0
  1028. package/src/modules/workflows/components/nodes/TriggerCap.tsx +103 -0
  1029. package/src/modules/workflows/components/nodes/TriggerNode.tsx +151 -0
  1030. package/src/modules/workflows/components/nodes/UserTaskNode.tsx +67 -22
  1031. package/src/modules/workflows/components/nodes/WaitForConditionNode.tsx +74 -0
  1032. package/src/modules/workflows/components/nodes/WaitForSignalNode.tsx +31 -17
  1033. package/src/modules/workflows/components/nodes/WaitForTimerNode.tsx +31 -16
  1034. package/src/modules/workflows/components/nodes/index.ts +17 -0
  1035. package/src/modules/workflows/components/portal/PortalTaskForm.tsx +280 -0
  1036. package/src/modules/workflows/components/run/AgentActivityPanel.tsx +48 -0
  1037. package/src/modules/workflows/components/run/RerunStepDialog.tsx +133 -0
  1038. package/src/modules/workflows/components/run/RunEventBadge.tsx +37 -0
  1039. package/src/modules/workflows/components/run/RunGantt.tsx +180 -0
  1040. package/src/modules/workflows/components/run/RunStatusBadge.tsx +112 -0
  1041. package/src/modules/workflows/components/run/RunStepInspector.tsx +176 -0
  1042. package/src/modules/workflows/components/run/WouldDoReport.tsx +93 -0
  1043. package/src/modules/workflows/components/run/useAgentLabels.ts +42 -0
  1044. package/src/modules/workflows/components/run/useLastRunOverlay.ts +150 -0
  1045. package/src/modules/workflows/components/run/useLiveAgentActions.ts +70 -0
  1046. package/src/modules/workflows/components/run/useLiveRunUpdates.ts +89 -0
  1047. package/src/modules/workflows/components/settings/CommandSettingsPageClient.tsx +228 -0
  1048. package/src/modules/workflows/components/work-inbox/EntityContextPanel.tsx +179 -0
  1049. package/src/modules/workflows/components/work-inbox/ReassignTaskDialog.tsx +203 -0
  1050. package/src/modules/workflows/components/work-inbox/StatusChip.tsx +61 -0
  1051. package/src/modules/workflows/components/work-inbox/TaskActionNotice.tsx +77 -0
  1052. package/src/modules/workflows/components/work-inbox/TaskFormFields.tsx +322 -0
  1053. package/src/modules/workflows/components/work-inbox/WorkInboxEmptyState.tsx +43 -0
  1054. package/src/modules/workflows/data/activity-config-schemas.ts +249 -0
  1055. package/src/modules/workflows/data/activity-config-warnings.ts +71 -0
  1056. package/src/modules/workflows/data/branching-route-warnings.ts +129 -0
  1057. package/src/modules/workflows/data/entities.ts +397 -4
  1058. package/src/modules/workflows/data/metrics-validators.ts +51 -0
  1059. package/src/modules/workflows/data/task-primitives.ts +36 -0
  1060. package/src/modules/workflows/data/types.ts +81 -2
  1061. package/src/modules/workflows/data/validators.ts +729 -60
  1062. package/src/modules/workflows/di.ts +22 -0
  1063. package/src/modules/workflows/events.ts +68 -8
  1064. package/src/modules/workflows/examples/oze-residential-install-60-nodes.json +1545 -0
  1065. package/src/modules/workflows/examples/sales-pipeline-definition.json +35 -35
  1066. package/src/modules/workflows/examples/templates/lead-to-install.json +160 -0
  1067. package/src/modules/workflows/examples/templates/order-approval.json +230 -0
  1068. package/src/modules/workflows/examples/templates/task-escalation.json +110 -0
  1069. package/src/modules/workflows/examples/templates/webhook-integration.json +113 -0
  1070. package/src/modules/workflows/extension-points.ts +1 -1
  1071. package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.meta.ts +21 -0
  1072. package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.tsx +212 -0
  1073. package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/page.meta.ts +25 -0
  1074. package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/page.tsx +185 -0
  1075. package/src/modules/workflows/i18n/de.json +1083 -24
  1076. package/src/modules/workflows/i18n/en.json +1081 -22
  1077. package/src/modules/workflows/i18n/es.json +1083 -24
  1078. package/src/modules/workflows/i18n/ko.json +1072 -13
  1079. package/src/modules/workflows/i18n/pl.json +1082 -23
  1080. package/src/modules/workflows/lib/activity-executor.ts +855 -186
  1081. package/src/modules/workflows/lib/activity-queue-types.ts +120 -1
  1082. package/src/modules/workflows/lib/activity-registry-bootstrap.ts +7 -0
  1083. package/src/modules/workflows/lib/activity-registry.ts +89 -0
  1084. package/src/modules/workflows/lib/activity-types.ts +415 -0
  1085. package/src/modules/workflows/lib/activity-worker-handler.ts +744 -35
  1086. package/src/modules/workflows/lib/advanced-config.ts +41 -0
  1087. package/src/modules/workflows/lib/agent-disposition-task.ts +343 -0
  1088. package/src/modules/workflows/lib/agent-outcome-paths.ts +153 -0
  1089. package/src/modules/workflows/lib/agent-result-mapping.ts +88 -0
  1090. package/src/modules/workflows/lib/agent-review-inspector.ts +125 -0
  1091. package/src/modules/workflows/lib/agent-review.ts +171 -0
  1092. package/src/modules/workflows/lib/ai-authoring.ts +402 -0
  1093. package/src/modules/workflows/lib/ai-draft-runner.ts +105 -0
  1094. package/src/modules/workflows/lib/annotation-events.ts +15 -0
  1095. package/src/modules/workflows/lib/branching-routes.ts +280 -0
  1096. package/src/modules/workflows/lib/breach-routing.ts +142 -0
  1097. package/src/modules/workflows/lib/bulk-replay.ts +185 -0
  1098. package/src/modules/workflows/lib/business-rule-usage.ts +154 -0
  1099. package/src/modules/workflows/lib/caller-graph.ts +104 -0
  1100. package/src/modules/workflows/lib/code-view-apply.ts +178 -0
  1101. package/src/modules/workflows/lib/collect-validation-issues.ts +239 -0
  1102. package/src/modules/workflows/lib/compensation-ghosts.ts +134 -0
  1103. package/src/modules/workflows/lib/component-guard.ts +13 -0
  1104. package/src/modules/workflows/lib/condition-handler.ts +658 -0
  1105. package/src/modules/workflows/lib/context-ledger.ts +814 -0
  1106. package/src/modules/workflows/lib/crud-form-dialogs-flag.ts +5 -0
  1107. package/src/modules/workflows/lib/data-edge-mapping.ts +112 -0
  1108. package/src/modules/workflows/lib/definition-context-schema.ts +103 -0
  1109. package/src/modules/workflows/lib/definition-edit-safety.ts +228 -0
  1110. package/src/modules/workflows/lib/definition-error-body.ts +43 -0
  1111. package/src/modules/workflows/lib/definition-evaluation.ts +156 -0
  1112. package/src/modules/workflows/lib/definition-grant.ts +211 -0
  1113. package/src/modules/workflows/lib/definition-json-locations.ts +226 -0
  1114. package/src/modules/workflows/lib/definition-payload.ts +81 -0
  1115. package/src/modules/workflows/lib/draft-restore.ts +72 -0
  1116. package/src/modules/workflows/lib/dry-run.ts +203 -0
  1117. package/src/modules/workflows/lib/duration.ts +138 -24
  1118. package/src/modules/workflows/lib/edge-reattachment.ts +186 -0
  1119. package/src/modules/workflows/lib/edgeFormTransforms.ts +15 -14
  1120. package/src/modules/workflows/lib/editor-annotations.ts +301 -0
  1121. package/src/modules/workflows/lib/editor-commands.ts +205 -0
  1122. package/src/modules/workflows/lib/editor-history.ts +151 -0
  1123. package/src/modules/workflows/lib/endpoint-catalog.ts +283 -0
  1124. package/src/modules/workflows/lib/endpoint-path.ts +134 -0
  1125. package/src/modules/workflows/lib/engine-version.ts +67 -0
  1126. package/src/modules/workflows/lib/error-handler.ts +192 -0
  1127. package/src/modules/workflows/lib/error-routing.ts +236 -0
  1128. package/src/modules/workflows/lib/event-logger.ts +27 -0
  1129. package/src/modules/workflows/lib/expression-refs.ts +291 -0
  1130. package/src/modules/workflows/lib/failure-grouping.ts +134 -0
  1131. package/src/modules/workflows/lib/find-definition.ts +4 -0
  1132. package/src/modules/workflows/lib/flow-logic-warnings.ts +591 -0
  1133. package/src/modules/workflows/lib/graph-utils.ts +620 -110
  1134. package/src/modules/workflows/lib/icon-search.ts +65 -0
  1135. package/src/modules/workflows/lib/insert-at-cursor.ts +53 -0
  1136. package/src/modules/workflows/lib/instance-date-filter.ts +56 -0
  1137. package/src/modules/workflows/lib/interpolation-pipeline.ts +351 -0
  1138. package/src/modules/workflows/lib/ledger-drag.ts +61 -0
  1139. package/src/modules/workflows/lib/ledger-entry-display.ts +89 -0
  1140. package/src/modules/workflows/lib/ledger-schema-flatten.ts +137 -0
  1141. package/src/modules/workflows/lib/metrics/definition-metrics.ts +268 -0
  1142. package/src/modules/workflows/lib/metrics/metrics-display.ts +57 -0
  1143. package/src/modules/workflows/lib/metrics/rollup-schedule.ts +26 -0
  1144. package/src/modules/workflows/lib/metrics/rollup-service.ts +292 -0
  1145. package/src/modules/workflows/lib/node-config-summary.ts +235 -0
  1146. package/src/modules/workflows/lib/node-geometry.ts +168 -0
  1147. package/src/modules/workflows/lib/node-nudge.ts +63 -0
  1148. package/src/modules/workflows/lib/node-outcome-rows.ts +195 -0
  1149. package/src/modules/workflows/lib/node-placement.ts +104 -0
  1150. package/src/modules/workflows/lib/node-type-icons.ts +71 -10
  1151. package/src/modules/workflows/lib/nodeFormTransforms.ts +519 -28
  1152. package/src/modules/workflows/lib/outcome-routing.ts +346 -0
  1153. package/src/modules/workflows/lib/owned-definition.ts +188 -0
  1154. package/src/modules/workflows/lib/owned-node-changes.ts +29 -0
  1155. package/src/modules/workflows/lib/palette-drag.ts +68 -0
  1156. package/src/modules/workflows/lib/palette-drop.ts +114 -0
  1157. package/src/modules/workflows/lib/parallel-handler.ts +79 -2
  1158. package/src/modules/workflows/lib/port-contract.ts +107 -0
  1159. package/src/modules/workflows/lib/portal-task-access.ts +220 -0
  1160. package/src/modules/workflows/lib/rerun-from-step.ts +140 -0
  1161. package/src/modules/workflows/lib/route-chip-events.ts +45 -0
  1162. package/src/modules/workflows/lib/route-chips.ts +177 -0
  1163. package/src/modules/workflows/lib/route-edge.ts +57 -0
  1164. package/src/modules/workflows/lib/route-kinds.ts +166 -0
  1165. package/src/modules/workflows/lib/route-priority.ts +197 -0
  1166. package/src/modules/workflows/lib/run-duration.ts +70 -0
  1167. package/src/modules/workflows/lib/run-event-tone.ts +46 -0
  1168. package/src/modules/workflows/lib/run-execution.ts +598 -0
  1169. package/src/modules/workflows/lib/run-gantt.ts +311 -0
  1170. package/src/modules/workflows/lib/run-outcome-evidence.ts +60 -0
  1171. package/src/modules/workflows/lib/run-outcome.ts +142 -0
  1172. package/src/modules/workflows/lib/sample-resolver.ts +113 -0
  1173. package/src/modules/workflows/lib/seeds.ts +3 -1
  1174. package/src/modules/workflows/lib/server-output-contract.ts +120 -0
  1175. package/src/modules/workflows/lib/set-variable.ts +94 -0
  1176. package/src/modules/workflows/lib/signal-handler.ts +134 -4
  1177. package/src/modules/workflows/lib/start-fixtures.ts +93 -0
  1178. package/src/modules/workflows/lib/status-colors.ts +220 -21
  1179. package/src/modules/workflows/lib/step-handler.ts +744 -68
  1180. package/src/modules/workflows/lib/step-presentation.ts +295 -0
  1181. package/src/modules/workflows/lib/step-through.ts +71 -0
  1182. package/src/modules/workflows/lib/step-type-conversion.ts +263 -0
  1183. package/src/modules/workflows/lib/subgraph-clipboard.ts +214 -0
  1184. package/src/modules/workflows/lib/task-decision-context.ts +76 -0
  1185. package/src/modules/workflows/lib/task-decisions.ts +117 -0
  1186. package/src/modules/workflows/lib/task-entity-access.ts +181 -0
  1187. package/src/modules/workflows/lib/task-entity-aliases.ts +77 -0
  1188. package/src/modules/workflows/lib/task-entity-types.ts +66 -0
  1189. package/src/modules/workflows/lib/task-form-registry.ts +123 -0
  1190. package/src/modules/workflows/lib/task-form-schema.ts +129 -0
  1191. package/src/modules/workflows/lib/task-handler.ts +492 -51
  1192. package/src/modules/workflows/lib/task-inspector-config.ts +348 -0
  1193. package/src/modules/workflows/lib/task-list-query.ts +46 -0
  1194. package/src/modules/workflows/lib/task-notifications.ts +218 -0
  1195. package/src/modules/workflows/lib/task-permission-settings.ts +117 -0
  1196. package/src/modules/workflows/lib/task-presets.ts +95 -0
  1197. package/src/modules/workflows/lib/task-quick-action.ts +111 -0
  1198. package/src/modules/workflows/lib/task-resolution.ts +270 -0
  1199. package/src/modules/workflows/lib/task-sla.ts +628 -0
  1200. package/src/modules/workflows/lib/task-visibility-request.ts +668 -0
  1201. package/src/modules/workflows/lib/task-visibility.ts +627 -0
  1202. package/src/modules/workflows/lib/timer-handler.ts +8 -1
  1203. package/src/modules/workflows/lib/transition-handler.ts +228 -20
  1204. package/src/modules/workflows/lib/trigger-node.ts +272 -0
  1205. package/src/modules/workflows/lib/visual-editor-navigation.ts +29 -0
  1206. package/src/modules/workflows/lib/work-inbox/empty-state.ts +150 -0
  1207. package/src/modules/workflows/lib/work-inbox/entity-links.ts +99 -0
  1208. package/src/modules/workflows/lib/work-inbox/navigation.ts +28 -0
  1209. package/src/modules/workflows/lib/work-inbox/presentation.ts +163 -0
  1210. package/src/modules/workflows/lib/work-inbox/provider.ts +390 -0
  1211. package/src/modules/workflows/lib/work-inbox/query.ts +103 -0
  1212. package/src/modules/workflows/lib/work-inbox/service.ts +122 -0
  1213. package/src/modules/workflows/lib/work-inbox/user-task-source.ts +240 -0
  1214. package/src/modules/workflows/lib/workflow-command-enablement.ts +188 -0
  1215. package/src/modules/workflows/lib/workflow-command-settings.ts +124 -0
  1216. package/src/modules/workflows/lib/workflow-executor.ts +1036 -10
  1217. package/src/modules/workflows/lib/workflow-function-registry.ts +44 -0
  1218. package/src/modules/workflows/lib/workflow-safe-commands.ts +42 -1
  1219. package/src/modules/workflows/lib/workflow-templates.ts +91 -0
  1220. package/src/modules/workflows/migrations/.snapshot-open-mercato.json +2321 -698
  1221. package/src/modules/workflows/migrations/Migration20260626214855_workflows.ts +15 -0
  1222. package/src/modules/workflows/migrations/Migration20260626222424_workflows.ts +17 -0
  1223. package/src/modules/workflows/migrations/Migration20260727074335_workflows.ts +15 -0
  1224. package/src/modules/workflows/migrations/Migration20260728104038_workflows.ts +13 -0
  1225. package/src/modules/workflows/migrations/Migration20260728163001_workflows.ts +36 -0
  1226. package/src/modules/workflows/migrations/Migration20260729061736_workflows.ts +13 -0
  1227. package/src/modules/workflows/migrations/Migration20260729192652_workflows.ts +11 -0
  1228. package/src/modules/workflows/migrations/Migration20260730085000_workflows.ts +13 -0
  1229. package/src/modules/workflows/migrations/Migration20260730092706_workflows.ts +13 -0
  1230. package/src/modules/workflows/notifications.ts +40 -10
  1231. package/src/modules/workflows/setup.ts +128 -0
  1232. package/src/modules/workflows/subscribers/task-assigned-notification.ts +36 -45
  1233. package/src/modules/workflows/subscribers/task-deadline-breached-notification.ts +31 -0
  1234. package/src/modules/workflows/subscribers/task-reminder-notification.ts +31 -0
  1235. package/src/modules/workflows/widgets/injection/pending-work/widget.client.tsx +119 -0
  1236. package/src/modules/workflows/widgets/injection/pending-work/widget.ts +27 -0
  1237. package/src/modules/workflows/widgets/injection-table.ts +52 -2
  1238. package/src/modules/workflows/workers/workflow-activities.worker.ts +95 -42
  1239. package/src/modules/workflows/workers/workflow-definition-metric-rollup.worker.ts +71 -0
  1240. package/src/modules/workflows/workers/workflow-instance-bulk-replay.ts +51 -0
  1241. package/src/modules/workflows/workers/workflow-invoke-agent.worker.ts +72 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/workflows/lib/task-sla.ts"],
4
+ "sourcesContent": ["/**\n * Task SLA scheduler \u2014 reminders and deadline breach for USER_TASK steps.\n *\n * `dueDate` has been display-only until now: nothing ever read it back, and the\n * authored `escalationRules` were dead config. This module makes the deadline\n * real, and it does so on the queue rather than with a poller \u2014 reusing the\n * Phase-3a absolute-deadline backstop the WAIT_FOR_CONDITION step already\n * relies on:\n *\n * - every job is enqueued ONCE, at task creation, with a delay;\n * - `deadlineAt` is ABSOLUTE and rides on the payload, so a queue running\n * behind cannot silently extend the deadline the author configured;\n * - the handler is IDEMPOTENT \u2014 a completed, cancelled or already-breached\n * task makes the job a no-op, and the breach is claimed with a conditional\n * UPDATE so at-least-once delivery still fires it exactly once.\n *\n * `computeTaskSlaSchedule` is PURE (no ORM, DI or registry imports) so the\n * scheduling arithmetic is unit-testable without a workflow.\n */\n\nimport type { EntityManager } from '@mikro-orm/core'\nimport type { AwilixContainer } from 'awilix'\nimport { StepInstance, UserTask, WorkflowInstance } from '../data/entities'\nimport type { TaskOnBreach, TaskReminder } from '../data/validators'\nimport { parseDuration } from './duration'\nimport { resolveTaskBreachHandling, type TaskBreachHandling } from './breach-routing'\nimport {\n findAgentReviewConfig,\n resolveAgentReviewBreachHandling,\n INVOKE_AGENT_ACTIVITY_TYPE,\n type AgentReviewBreachHandling,\n type AgentReviewStepLike,\n} from './agent-review'\nimport { findDefinitionForInstance } from './find-definition'\nimport { emitWorkflowsEvent } from '../events'\nimport type * as stepHandlerModule from './step-handler'\nimport type * as transitionHandlerModule from './transition-handler'\nimport type * as workflowExecutorModule from './workflow-executor'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('workflows')\n\nexport type TaskSlaPhase = 'reminder' | 'breach'\n\nexport interface TaskSlaScheduleEntry {\n phase: TaskSlaPhase\n /** Absolute time this job should run. */\n fireAt: string\n /** Delay from `now`; never negative. */\n delayMs: number\n}\n\nexport interface TaskSlaSchedule {\n entries: TaskSlaScheduleEntry[]\n /** Reminder offsets that could not be parsed, so the caller can log them. */\n invalidOffsets: string[]\n}\n\n/** Statuses a task is still workable in \u2014 anything else makes an SLA job moot. */\nconst OPEN_TASK_STATUSES = ['PENDING', 'IN_PROGRESS'] as const\n\n/**\n * Resolve the jobs to enqueue for one task.\n *\n * A task with no deadline schedules NOTHING \u2014 reminders without a deadline have\n * nothing to count back from, so they are silently irrelevant rather than an\n * error. A reminder whose moment has already passed is dropped: firing it at\n * creation time would be noise, not a nudge. A reminder offset at or beyond the\n * whole deadline is likewise dropped \u2014 the breach job already speaks for that\n * moment.\n */\nexport function computeTaskSlaSchedule(options: {\n dueDate: Date | null | undefined\n reminders?: TaskReminder[] | null\n now?: Date\n}): TaskSlaSchedule {\n const { dueDate } = options\n if (!dueDate || Number.isNaN(dueDate.getTime())) return { entries: [], invalidOffsets: [] }\n\n const nowMs = (options.now ?? new Date()).getTime()\n const deadlineMs = dueDate.getTime()\n const entries: TaskSlaScheduleEntry[] = []\n const invalidOffsets: string[] = []\n\n for (const reminder of options.reminders ?? []) {\n const offset = reminder?.offset\n if (typeof offset !== 'string' || !offset.length) continue\n\n let offsetMs: number\n try {\n offsetMs = parseDuration(offset)\n } catch {\n invalidOffsets.push(offset)\n continue\n }\n\n if (offsetMs <= 0) continue\n const remindAtMs = deadlineMs - offsetMs\n if (remindAtMs <= nowMs || remindAtMs >= deadlineMs) continue\n\n entries.push({\n phase: 'reminder',\n fireAt: new Date(remindAtMs).toISOString(),\n delayMs: remindAtMs - nowMs,\n })\n }\n\n entries.push({\n phase: 'breach',\n fireAt: dueDate.toISOString(),\n delayMs: Math.max(0, deadlineMs - nowMs),\n })\n\n entries.sort((left, right) => left.delayMs - right.delayMs)\n\n return { entries, invalidOffsets }\n}\n\nexport interface ScheduleUserTaskSlaOptions {\n workflowInstanceId: string\n stepInstanceId: string\n branchInstanceId?: string | null\n userTaskId: string\n dueDate: Date | null | undefined\n reminders?: TaskReminder[] | null\n tenantId: string\n organizationId: string\n userId?: string\n now?: Date\n}\n\n/**\n * Enqueue every SLA job a freshly created task needs.\n *\n * Best-effort by contract: a queue failure must never break the workflow step\n * that created the task, exactly as the assignment event's emission does not.\n */\nexport async function scheduleUserTaskSla(\n options: ScheduleUserTaskSlaOptions\n): Promise<string[]> {\n const schedule = computeTaskSlaSchedule({\n dueDate: options.dueDate,\n reminders: options.reminders,\n now: options.now,\n })\n\n if (schedule.invalidOffsets.length) {\n logger.warn('Task reminder offsets skipped because they are not valid durations', {\n component: 'task-sla',\n taskId: options.userTaskId,\n invalidOffsets: schedule.invalidOffsets,\n })\n }\n\n if (schedule.entries.length === 0) return []\n\n const deadlineAt = options.dueDate ? options.dueDate.toISOString() : null\n if (!deadlineAt) return []\n\n const jobIds: string[] = []\n try {\n const { enqueueTaskSlaJob } = await import('./activity-executor')\n for (const entry of schedule.entries) {\n const jobId = await enqueueTaskSlaJob({\n workflowInstanceId: options.workflowInstanceId,\n stepInstanceId: options.stepInstanceId,\n branchInstanceId: options.branchInstanceId ?? null,\n userTaskId: options.userTaskId,\n phase: entry.phase,\n deadlineAt,\n fireAt: entry.fireAt,\n delayMs: entry.delayMs,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n userId: options.userId,\n })\n jobIds.push(jobId)\n }\n } catch (error) {\n logger.error('Failed to schedule task SLA jobs', {\n component: 'task-sla',\n taskId: options.userTaskId,\n err: error,\n })\n }\n\n return jobIds\n}\n\nexport type TaskSlaOutcome = 'noop' | 'reminded' | 'breached'\n\nexport interface RunTaskSlaJobOptions {\n userTaskId: string\n stepInstanceId: string\n workflowInstanceId: string\n branchInstanceId?: string | null\n phase: TaskSlaPhase\n deadlineAt: string\n tenantId: string\n organizationId: string\n userId?: string\n}\n\n/**\n * Run one SLA job.\n *\n * Every early return is a deliberate no-op rather than an error: the queue\n * retries, and a task that was completed in the meantime is the ordinary case,\n * not a failure.\n */\nexport async function runTaskSlaJob(\n em: EntityManager,\n container: AwilixContainer,\n options: RunTaskSlaJobOptions\n): Promise<TaskSlaOutcome> {\n const { tenantId, organizationId } = options\n\n const task = await em.findOne(UserTask, {\n id: options.userTaskId,\n tenantId,\n organizationId,\n })\n\n if (!task) return 'noop'\n if (!OPEN_TASK_STATUSES.includes(task.status as (typeof OPEN_TASK_STATUSES)[number])) return 'noop'\n\n const deadlineMs = Date.parse(options.deadlineAt)\n if (Number.isNaN(deadlineMs)) return 'noop'\n\n if (options.phase === 'reminder') {\n // A reminder that arrives after the deadline has nothing left to warn\n // about, and one for an already-breached task is strictly noise.\n if (task.escalatedAt) return 'noop'\n if (Date.now() >= deadlineMs) return 'noop'\n\n await logTaskSlaEvent(em, container, options, 'USER_TASK_REMINDER_DUE', {\n taskId: task.id,\n taskName: task.taskName,\n dueDate: options.deadlineAt,\n })\n\n await emitTaskSlaEvent(em, 'workflows.task.reminder_due', task, options)\n return 'reminded'\n }\n\n // Claim the breach with a conditional UPDATE rather than a read-then-write:\n // the queue delivers at least once, and two deliveries reading `escalated_at\n // IS NULL` would both fire. The loser updates zero rows and no-ops.\n const now = new Date()\n const claimed = await em.nativeUpdate(\n UserTask,\n {\n id: task.id,\n tenantId,\n organizationId,\n status: { $in: [...OPEN_TASK_STATUSES] },\n escalatedAt: null,\n },\n { escalatedAt: now, updatedAt: now }\n )\n\n if (claimed === 0) return 'noop'\n\n task.escalatedAt = now\n task.updatedAt = now\n\n // WHICH path the breach took is part of the audit trail, not an implementation\n // detail: \"the deadline passed\" and \"the deadline passed and the run was\n // routed away from this task\" are different facts about the same instant.\n const handling = await applyBreachHandling(em, container, task, options, now)\n\n await logTaskSlaEvent(em, container, options, 'USER_TASK_DEADLINE_BREACHED', {\n taskId: task.id,\n taskName: task.taskName,\n dueDate: options.deadlineAt,\n breachedAt: now.toISOString(),\n onBreach: handling.outcome,\n ...(handling.detail ?? {}),\n })\n\n await emitTaskSlaEvent(em, 'workflows.task.deadline_breached', task, options)\n\n // A reassignment only means anything once the new owner is told about it, and\n // the assignment event is the one path that already reaches both an individual\n // and a role queue.\n if (handling.outcome === 'reassigned') {\n await emitTaskSlaEvent(em, 'workflows.task.assigned', task, options)\n }\n\n if (handling.resumeInstance) {\n await resumeAfterBreachRoute(em, container, task, options, handling.resumeInstance)\n }\n\n return 'breached'\n}\n\ntype BreachOutcome =\n | 'none'\n | 'notified'\n | 'reassigned'\n | 'routed'\n | 'route_skipped_branch'\n | 'attention'\n\ninterface AppliedBreachHandling {\n outcome: BreachOutcome\n detail?: Record<string, unknown>\n resumeInstance?: { stepId: string; toStepId: string; transitionId?: string }\n}\n\ntype BreachResolution = TaskBreachHandling | AgentReviewBreachHandling\n\n/**\n * A step whose breached task is an agent DISPOSITION task rather than an\n * authored USER_TASK. Recognised structurally from the compiled step (an\n * AUTOMATED step carrying an INVOKE_AGENT activity), which is the same shape\n * `graph-utils` round-trips the node from.\n */\nfunction isInvokeAgentStepDef(step: AgentReviewStepLike | undefined): boolean {\n return (step?.activities ?? []).some(\n (activity) => activity?.activityType === INVOKE_AGENT_ACTIVITY_TYPE\n )\n}\n\n/**\n * Apply the resolver's answer to the task row. Routing itself is deferred to\n * `resumeAfterBreachRoute` so the workflow only advances after the breach has\n * been recorded and announced.\n *\n * Which resolver answers depends on WHAT the task is. An authored USER_TASK\n * keeps the full \u00A76.1 vocabulary, including \"follow a route\". An agent\n * disposition task (\u00A77.5) gets the escalate-only one: notify, reassign, or mark\n * the run for attention. It can reach neither a verdict nor a route, because\n * both would resolve a pending proposal without a human \u2014 routing the run past\n * a proposal nobody answered silently drops the mutation the agent proposed,\n * which is a rejection in everything but name. A hand-authored `kind:'slaBreach'`\n * transition on an agent step therefore cannot fire either: the branch below is\n * taken from the STEP's shape, not from the config the author supplied.\n */\nasync function applyBreachHandling(\n em: EntityManager,\n container: AwilixContainer,\n task: UserTask,\n options: RunTaskSlaJobOptions,\n now: Date\n): Promise<AppliedBreachHandling> {\n let resolution: BreachResolution = { kind: 'none' }\n let stepId: string | null = null\n let instance: WorkflowInstance | null = null\n\n try {\n const stepInstance = await em.findOne(StepInstance, {\n id: options.stepInstanceId,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n })\n stepId = stepInstance?.stepId ?? null\n\n instance = await em.findOne(WorkflowInstance, {\n id: options.workflowInstanceId,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n })\n\n if (stepId && instance) {\n const definition = await findDefinitionForInstance(em, instance)\n const stepDef = (definition?.definition?.steps ?? []).find(\n (step: { stepId?: string }) => step.stepId === stepId\n ) as\n | ({ userTaskConfig?: { onBreach?: TaskOnBreach | null } } & AgentReviewStepLike)\n | undefined\n\n resolution = isInvokeAgentStepDef(stepDef)\n ? resolveAgentReviewBreachHandling(findAgentReviewConfig(stepDef)?.onBreach ?? null)\n : resolveTaskBreachHandling(\n definition?.definition ?? null,\n stepId,\n stepDef?.userTaskConfig?.onBreach ?? null\n )\n }\n } catch (error) {\n // A definition the engine can no longer read must not strand the breach:\n // the task is already marked escalated and the event still fires.\n logger.error('Failed to resolve breach handling; falling back to notify-only', {\n component: 'task-sla',\n taskId: task.id,\n err: error,\n })\n return { outcome: 'none' }\n }\n\n if (resolution.kind === 'notify') return { outcome: 'notified' }\n\n if (resolution.kind === 'attention') {\n if (!instance) return { outcome: 'none' }\n await markInstanceForAttention(em, instance, stepId, task, now)\n return { outcome: 'attention', detail: { stepId } }\n }\n\n if (resolution.kind === 'reassign') {\n task.assignedTo = resolution.assignedTo\n task.assignedToRoles = resolution.assignedToRoles\n task.claimedBy = null\n task.claimedAt = null\n task.status = 'PENDING'\n task.escalatedTo = resolution.assignedTo ?? resolution.assignedToRoles?.[0] ?? null\n task.reassignedAt = now\n task.reassignReason = 'sla_breach'\n task.updatedAt = now\n await em.flush()\n return {\n outcome: 'reassigned',\n detail: {\n reassignedTo: resolution.assignedTo,\n reassignedToRoles: resolution.assignedToRoles,\n },\n }\n }\n\n if (resolution.kind === 'route') {\n const toStepId = resolution.transition.toStepId\n if (!stepId || !toStepId) return { outcome: 'none' }\n\n // A branch-scoped task does NOT follow its breach route, for the same\n // reason a decision button does not select a route inside a branch\n // (`completeUserTask`): a branch advances through `resumeBranch` with its\n // own token, and overriding that is a parallel-execution change rather than\n // a task-surface one.\n if (options.branchInstanceId) {\n return { outcome: 'route_skipped_branch', detail: { transitionId: resolution.transition.transitionId } }\n }\n\n // The task is superseded by the route, not abandoned: `ESCALATED` is an\n // existing `UserTaskStatus`, so no state machine changes.\n task.status = 'ESCALATED'\n task.updatedAt = now\n await em.flush()\n\n return {\n outcome: 'routed',\n detail: { transitionId: resolution.transition.transitionId, toStepId },\n resumeInstance: { stepId, toStepId, transitionId: resolution.transition.transitionId },\n }\n }\n\n return { outcome: 'none' }\n}\n\n/**\n * Mark a run for triage without touching its state machine.\n *\n * The instance is ALREADY paused \u2014 an agent step parks on the proposal-ready\n * signal \u2014 so this writes only the engine-owned `metadata.attention` marker the\n * failure queue already uses (`GET /api/workflows/instances?attention=true`\n * lists it). Deliberately no status write, no `errorMessage`: the run is not\n * failing, it is waiting on a person who is late, and the proposal is still\n * pending for whoever picks it up.\n */\nasync function markInstanceForAttention(\n em: EntityManager,\n instance: WorkflowInstance,\n stepId: string | null,\n task: UserTask,\n now: Date\n): Promise<void> {\n instance.metadata = {\n ...(instance.metadata || {}),\n attention: {\n reason: 'DISPOSITION_SLA_BREACH',\n ...(stepId ? { stepId } : {}),\n at: now.toISOString(),\n },\n }\n instance.updatedAt = now\n await em.flush()\n\n logger.warn('Agent disposition deadline passed; run marked for attention', {\n component: 'task-sla',\n taskId: task.id,\n workflowInstanceId: instance.id,\n stepId,\n })\n}\n\n/**\n * Follow the breach route: exit the task's step and drive the run onward,\n * mirroring how `fireTimer` resumes a run parked on a WAIT_FOR_TIMER step.\n *\n * Best-effort: a routing failure leaves the run exactly where it was, with the\n * breach already recorded, rather than throwing the queue job into a retry loop\n * that would re-announce a breach that has already fired.\n */\nasync function resumeAfterBreachRoute(\n em: EntityManager,\n container: AwilixContainer,\n task: UserTask,\n options: RunTaskSlaJobOptions,\n route: { stepId: string; toStepId: string; transitionId?: string }\n): Promise<void> {\n try {\n const instance = await em.findOne(WorkflowInstance, {\n id: options.workflowInstanceId,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n })\n if (!instance) return\n\n const stepHandler = container.resolve<typeof stepHandlerModule>('stepHandler')\n const transitionHandler = container.resolve<typeof transitionHandlerModule>('transitionHandler')\n const workflowExecutor = container.resolve<typeof workflowExecutorModule>('workflowExecutor')\n\n const stepInstance = await em.findOne(StepInstance, {\n id: options.stepInstanceId,\n status: 'ACTIVE',\n })\n if (stepInstance) {\n await stepHandler.exitStep(em, stepInstance, {\n userTaskId: task.id,\n slaBreached: true,\n })\n }\n\n const transitionResult = await transitionHandler.executeTransition(\n em,\n container,\n instance,\n route.stepId,\n route.toStepId,\n {\n workflowContext: instance.context,\n userId: options.userId,\n transitionId: route.transitionId,\n },\n )\n\n if (!transitionResult.success) {\n logger.error('SLA-breach transition failed', {\n component: 'task-sla',\n taskId: task.id,\n err: transitionResult.error,\n })\n return\n }\n\n await workflowExecutor.executeWorkflow(em, container, instance.id, { userId: options.userId })\n } catch (error) {\n logger.error('Failed to follow the SLA-breach route', {\n component: 'task-sla',\n taskId: task.id,\n err: error,\n })\n }\n}\n\nasync function logTaskSlaEvent(\n em: EntityManager,\n container: AwilixContainer,\n options: RunTaskSlaJobOptions,\n eventType: string,\n eventData: Record<string, unknown>\n): Promise<void> {\n try {\n const eventLogger = container.resolve<{\n logWorkflowEvent: (\n em: EntityManager,\n event: Record<string, unknown>\n ) => Promise<unknown>\n }>('eventLogger')\n\n await eventLogger.logWorkflowEvent(em, {\n workflowInstanceId: options.workflowInstanceId,\n stepInstanceId: options.stepInstanceId,\n ...(options.branchInstanceId ? { branchInstanceId: options.branchInstanceId } : {}),\n eventType,\n eventData,\n userId: options.userId,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n })\n } catch (error) {\n logger.error('Failed to log task SLA workflow event', {\n component: 'task-sla',\n taskId: options.userTaskId,\n eventType,\n err: error,\n })\n }\n}\n\nasync function emitTaskSlaEvent(\n em: EntityManager,\n eventId: 'workflows.task.reminder_due' | 'workflows.task.deadline_breached' | 'workflows.task.assigned',\n task: UserTask,\n options: RunTaskSlaJobOptions\n): Promise<void> {\n try {\n const instance = await em.findOne(WorkflowInstance, {\n id: options.workflowInstanceId,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n })\n\n await emitWorkflowsEvent(\n eventId,\n {\n taskId: task.id,\n taskName: task.taskName,\n workflowInstanceId: options.workflowInstanceId,\n workflowId: instance?.workflowId ?? null,\n workflowName: instance?.workflowId ?? '',\n assignedUserId: task.claimedBy ?? task.assignedTo ?? null,\n assignedToRoles: task.assignedToRoles ?? null,\n dueDate: options.deadlineAt,\n entityBindings: task.entityBindings ?? null,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n },\n { persistent: true }\n )\n } catch (error) {\n logger.error('Failed to emit task SLA event', {\n component: 'task-sla',\n taskId: task.id,\n eventId,\n err: error,\n })\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,266 @@
1
+ import { hasAllFeatures, hasFeature } from "@open-mercato/shared/security/features";
2
+ import { UserTask as UserTaskEntity } from "../data/entities.js";
3
+ import {
4
+ collectTaskEntityTypes,
5
+ resolveTaskEntityAccess
6
+ } from "./task-entity-access.js";
7
+ import {
8
+ buildTaskVisibilityConditions,
9
+ currentTaskOwnerId,
10
+ decideTaskVisibility,
11
+ resolveTaskAffordances,
12
+ TASK_ACTIONABLE_STATUSES,
13
+ WORKFLOWS_TASKS_VIEW_ALL_FEATURE
14
+ } from "./task-visibility.js";
15
+ import {
16
+ resolveTaskVisibilityPolicy
17
+ } from "./task-permission-settings.js";
18
+ async function resolveTaskVisibilityRequestContext(input) {
19
+ const scope = {
20
+ tenantId: input.auth.tenantId,
21
+ organizationId: input.aclOrganizationId
22
+ };
23
+ const scopedEntityTypes = [...new Set(input.entityTypes)];
24
+ const [access, policy] = await Promise.all([
25
+ resolveTaskEntityAccess({
26
+ entityTypes: scopedEntityTypes,
27
+ em: input.em,
28
+ rbac: input.rbac,
29
+ userId: input.auth.userId,
30
+ scope
31
+ }),
32
+ resolveTaskVisibilityPolicy(input.moduleConfigService, input.auth.tenantId)
33
+ ]);
34
+ return {
35
+ principal: {
36
+ kind: "backoffice",
37
+ userId: input.auth.userId,
38
+ tenantId: input.auth.tenantId,
39
+ organizationIds: input.organizationIds ?? null,
40
+ roleNames: input.auth.roleNames,
41
+ grantedFeatures: access.grantedFeatures,
42
+ isSuperAdmin: access.isSuperAdmin
43
+ },
44
+ policy,
45
+ entityAccess: access.map,
46
+ scopedEntityTypes
47
+ };
48
+ }
49
+ const NO_GRANTS_RBAC = { loadAcl: async () => null };
50
+ function resolveOptional(container, name) {
51
+ try {
52
+ return container.resolve(name) ?? null;
53
+ } catch {
54
+ return null;
55
+ }
56
+ }
57
+ async function resolveTaskVisibilityForRequest(input) {
58
+ return resolveTaskVisibilityRequestContext({
59
+ em: input.em,
60
+ rbac: resolveOptional(input.container, "rbacService") ?? NO_GRANTS_RBAC,
61
+ // A config read that cannot happen defaults to the NEW model, never the
62
+ // permissive one — see `lib/task-permission-settings.ts`.
63
+ moduleConfigService: resolveOptional(
64
+ input.container,
65
+ "moduleConfigService"
66
+ ),
67
+ auth: input.auth,
68
+ organizationIds: input.organizationIds,
69
+ aclOrganizationId: input.aclOrganizationId,
70
+ entityTypes: input.entityTypes
71
+ });
72
+ }
73
+ async function collectScopedTaskEntityTypes(em, scope) {
74
+ const params = [scope.tenantId];
75
+ let sql = "SELECT DISTINCT unnest(entity_types) AS entity_type FROM user_tasks WHERE tenant_id = ?";
76
+ if (scope.organizationIds !== null) {
77
+ if (scope.organizationIds.length === 0) return [];
78
+ sql += ` AND organization_id IN (${scope.organizationIds.map(() => "?").join(", ")})`;
79
+ params.push(...scope.organizationIds);
80
+ }
81
+ const rows = await em.getConnection().execute(sql, params);
82
+ const types = /* @__PURE__ */ new Set();
83
+ for (const row of rows) {
84
+ const entityType = row?.entity_type;
85
+ if (typeof entityType === "string" && entityType.length > 0) types.add(entityType);
86
+ }
87
+ return [...types];
88
+ }
89
+ function resolveAllowedTaskEntityTypes(context, candidates = context.scopedEntityTypes) {
90
+ const allowed = [];
91
+ for (const entityType of new Set(candidates)) {
92
+ const decision = context.entityAccess.get(entityType);
93
+ if (!decision || decision.kind !== "requires") continue;
94
+ if (!hasAllFeatures(context.principal.grantedFeatures, decision.features)) continue;
95
+ allowed.push(entityType);
96
+ }
97
+ return allowed;
98
+ }
99
+ function buildTaskEntityGateConditions(context) {
100
+ if (context.principal.isSuperAdmin) return [];
101
+ if (!context.policy.businessContextEnabled) return [];
102
+ if (canDiagnoseTaskRefusal(context.principal)) return [];
103
+ return [
104
+ {
105
+ $or: [
106
+ { entityTypes: null },
107
+ { entityTypes: { $contained: resolveAllowedTaskEntityTypes(context) } }
108
+ ]
109
+ }
110
+ ];
111
+ }
112
+ function buildTaskVisibilityRequestConditions(context, options = {}) {
113
+ return [
114
+ ...buildTaskVisibilityConditions(context.principal, context.policy, options),
115
+ ...buildTaskEntityGateConditions(context)
116
+ ];
117
+ }
118
+ function asBindingFacts(value) {
119
+ if (!Array.isArray(value)) return [];
120
+ const bindings = [];
121
+ for (const item of value) {
122
+ if (!item || typeof item !== "object" || Array.isArray(item)) continue;
123
+ const record = item;
124
+ if (typeof record.entityType !== "string" || typeof record.entityId !== "string") continue;
125
+ bindings.push({ entityType: record.entityType, entityId: record.entityId });
126
+ }
127
+ return bindings;
128
+ }
129
+ function toTaskFacts(task, options = {}) {
130
+ return {
131
+ id: task.id,
132
+ tenantId: task.tenantId,
133
+ organizationId: task.organizationId,
134
+ status: task.status,
135
+ assignedTo: task.assignedTo ?? null,
136
+ assigneeKind: task.assigneeKind ?? "user",
137
+ assignedToRoles: task.assignedToRoles ?? null,
138
+ claimedBy: task.claimedBy ?? null,
139
+ entityBindings: asBindingFacts(task.entityBindings),
140
+ administrativeQueueFeature: options.administrativeQueueFeature ?? null
141
+ };
142
+ }
143
+ function collectTaskEntityTypesFromTasks(tasks) {
144
+ return collectTaskEntityTypes(
145
+ [...tasks].map((task) => ({ entityBindings: asBindingFacts(task.entityBindings) }))
146
+ );
147
+ }
148
+ function decideTaskAccess(context, task, options = {}) {
149
+ return decideTaskVisibility(
150
+ context.principal,
151
+ toTaskFacts(task, options),
152
+ context.entityAccess,
153
+ context.policy
154
+ );
155
+ }
156
+ function resolveTaskAffordancesForRequest(context, task, decision, options = {}) {
157
+ return resolveTaskAffordances(context.principal, toTaskFacts(task, options), decision);
158
+ }
159
+ function filterVisibleTasks(context, tasks, options = {}) {
160
+ return tasks.filter((task) => decideTaskAccess(context, task, options).visible);
161
+ }
162
+ function partitionTaskPage(context, tasks, options = {}) {
163
+ const visible = [];
164
+ const entityHidden = [];
165
+ const diagnosable = canDiagnoseTaskRefusal(context.principal);
166
+ for (const task of tasks) {
167
+ const decision = decideTaskAccess(context, task, options);
168
+ if (decision.visible) {
169
+ visible.push(task);
170
+ continue;
171
+ }
172
+ if (!diagnosable) continue;
173
+ if (decision.reason !== "denied:entity-access" && decision.reason !== "denied:unknown-entity-type") {
174
+ continue;
175
+ }
176
+ entityHidden.push({
177
+ id: task.id,
178
+ reason: decision.reason,
179
+ entityType: decision.blockedEntityType ?? null
180
+ });
181
+ }
182
+ return { visible, entityHidden };
183
+ }
184
+ function canDiagnoseTaskRefusal(principal) {
185
+ return principal.isSuperAdmin || hasFeature(principal.grantedFeatures, WORKFLOWS_TASKS_VIEW_ALL_FEATURE);
186
+ }
187
+ const TASK_NOT_FOUND_BODY = { error: "Task not found" };
188
+ const TASK_ASSIGNED_TO_ANOTHER_USER_BODY = {
189
+ error: "Task is assigned to another user",
190
+ code: "TASK_ASSIGNED_TO_ANOTHER_USER"
191
+ };
192
+ const TASK_NOT_ACTIONABLE_BODY = {
193
+ error: "Task is not assigned to anyone; reassign it before acting on it",
194
+ code: "TASK_NOT_ACTIONABLE"
195
+ };
196
+ function resolveTaskActRefusal(context, decision, task, options = {}) {
197
+ if (!decision.visible) return resolveTaskRefusal(context, decision);
198
+ if (decision.blockedEntityType) return { status: 404, body: TASK_NOT_FOUND_BODY };
199
+ if (!options.requireOwnership || decision.actable) return null;
200
+ const facts = toTaskFacts(task, options);
201
+ if (!TASK_ACTIONABLE_STATUSES.includes(facts.status)) return null;
202
+ return currentTaskOwnerId(facts) !== null ? { status: 409, body: TASK_ASSIGNED_TO_ANOTHER_USER_BODY } : { status: 403, body: TASK_NOT_ACTIONABLE_BODY };
203
+ }
204
+ async function gateTaskAction(input) {
205
+ const task = await input.em.findOne(UserTaskEntity, {
206
+ id: input.taskId,
207
+ tenantId: input.auth.tenantId,
208
+ organizationId: input.organizationId
209
+ });
210
+ if (!task) return { allowed: false, refusal: { status: 404, body: TASK_NOT_FOUND_BODY } };
211
+ const visibility = await resolveTaskVisibilityForRequest({
212
+ container: input.container,
213
+ em: input.em,
214
+ auth: input.auth,
215
+ organizationIds: [input.organizationId],
216
+ aclOrganizationId: input.organizationId,
217
+ entityTypes: collectTaskEntityTypesFromTasks([task])
218
+ });
219
+ const options = {
220
+ administrativeQueueFeature: input.administrativeQueueFeature ?? null,
221
+ requireOwnership: input.requireOwnership ?? false
222
+ };
223
+ const refusal = resolveTaskActRefusal(
224
+ visibility,
225
+ decideTaskAccess(visibility, task, options),
226
+ task,
227
+ options
228
+ );
229
+ return refusal ? { allowed: false, refusal } : { allowed: true, task, visibility };
230
+ }
231
+ function resolveTaskRefusal(context, decision) {
232
+ const isEntityRefusal = decision.reason === "denied:entity-access" || decision.reason === "denied:unknown-entity-type";
233
+ if (isEntityRefusal && canDiagnoseTaskRefusal(context.principal)) {
234
+ return {
235
+ status: 403,
236
+ body: {
237
+ error: "Forbidden",
238
+ reason: decision.reason,
239
+ ...decision.blockedEntityType ? { entityType: decision.blockedEntityType } : {}
240
+ }
241
+ };
242
+ }
243
+ return { status: 404, body: TASK_NOT_FOUND_BODY };
244
+ }
245
+ export {
246
+ TASK_ASSIGNED_TO_ANOTHER_USER_BODY,
247
+ TASK_NOT_ACTIONABLE_BODY,
248
+ TASK_NOT_FOUND_BODY,
249
+ buildTaskEntityGateConditions,
250
+ buildTaskVisibilityRequestConditions,
251
+ canDiagnoseTaskRefusal,
252
+ collectScopedTaskEntityTypes,
253
+ collectTaskEntityTypesFromTasks,
254
+ decideTaskAccess,
255
+ filterVisibleTasks,
256
+ gateTaskAction,
257
+ partitionTaskPage,
258
+ resolveAllowedTaskEntityTypes,
259
+ resolveTaskActRefusal,
260
+ resolveTaskAffordancesForRequest,
261
+ resolveTaskRefusal,
262
+ resolveTaskVisibilityForRequest,
263
+ resolveTaskVisibilityRequestContext,
264
+ toTaskFacts
265
+ };
266
+ //# sourceMappingURL=task-visibility-request.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/workflows/lib/task-visibility-request.ts"],
4
+ "sourcesContent": ["/**\n * Per-request wiring for the \u00A76.4 task visibility rule.\n *\n * The pure predicate (`lib/task-visibility.ts`) decides; this module is what\n * every backoffice surface calls to assemble its inputs ONCE and to turn the\n * rule into a `WHERE`. Nothing here decides anything on its own \u2014 a second copy\n * of the rule anywhere is a review failure.\n *\n * ## One ACL load per request, not per row\n *\n * `resolveTaskVisibilityRequestContext` performs exactly one `loadAcl`, one\n * config read and one entity-classification pass, and hands back the principal,\n * the tenant policy and the entity-access map together. A page of 50 tasks with\n * two bindings each costs the same as a page of one.\n *\n * ## Why the entity gate is a whitelist and not a denylist\n *\n * The SQL form is\n *\n * entity_types IS NULL OR entity_types <@ ARRAY[<types the caller may view>]\n *\n * rather than the superficially cheaper `NOT (entity_types && ARRAY[<denied>])`.\n * The two differ on exactly one row: one carrying a type that was not in the\n * enumerated set \u2014 a task written between the enumeration and the main query, or\n * a type the classifier never answered for. The whitelist EXCLUDES it; the\n * denylist ADMITS it. The predicate treats a missing map key as a resolution\n * failure and denies, so only the whitelist agrees with the predicate, and a\n * disagreement between the SQL gate and the predicate is precisely the state\n * where a row is counted in `pagination.total` and then dropped from the page \u2014\n * the \"short page, lying total\" failure D-2 exists to prevent. Fail-closed wins\n * over an index that neither formulation gets to use anyway (a negation is not\n * GIN-servable either).\n *\n * The `entity_types IS NULL` disjunct is load-bearing and must never be dropped:\n * `NULL <@ ARRAY[\u2026]` is NULL, not true, so without it every row written before\n * the column existed \u2014 the whole pre-Phase-4 corpus \u2014 would vanish from its own\n * assignee's inbox. That is an outage, not a narrowing.\n *\n * ## What the tenant opt-out reaches\n *\n * Only the read filter: `businessContextEnabled: false` drops the relationship\n * clause AND the entity clause from the `WHERE`, and nothing else. `actable` and\n * `claimable` come from the predicate, which computes them by the new rule\n * whatever the flag says.\n */\n\nimport type { EntityManager } from '@mikro-orm/core'\nimport { hasAllFeatures, hasFeature } from '@open-mercato/shared/security/features'\nimport { UserTask as UserTaskEntity, type UserTask } from '../data/entities'\nimport {\n collectTaskEntityTypes,\n resolveTaskEntityAccess,\n type TaskEntityAccessRbacService,\n type TaskEntityAccessScope,\n} from './task-entity-access'\nimport {\n buildTaskVisibilityConditions,\n currentTaskOwnerId,\n decideTaskVisibility,\n resolveTaskAffordances,\n TASK_ACTIONABLE_STATUSES,\n WORKFLOWS_TASKS_VIEW_ALL_FEATURE,\n type BackofficeTaskPrincipal,\n type TaskAffordances,\n type TaskEntityAccessMap,\n type TaskEntityBindingFact,\n type TaskFacts,\n type TaskVisibilityDecision,\n type TaskVisibilityFilterOptions,\n type TaskVisibilityPolicy,\n} from './task-visibility'\nimport {\n resolveTaskVisibilityPolicy,\n type TaskPermissionsConfigService,\n} from './task-permission-settings'\n\n/**\n * Everything the rule needs about this request, resolved once.\n *\n * `scopedEntityTypes` is the universe the entity whitelist is drawn from: for a\n * list it is the distinct authored types present in the caller's tenant and\n * organizations, for a single task it is that task's own binding types.\n */\nexport type TaskVisibilityRequestContext = {\n principal: BackofficeTaskPrincipal\n policy: TaskVisibilityPolicy\n entityAccess: TaskEntityAccessMap\n scopedEntityTypes: readonly string[]\n}\n\nexport type TaskVisibilityAuth = {\n userId: string\n tenantId: string\n roleNames: readonly string[]\n}\n\nexport type ResolveTaskVisibilityRequestContextInput = {\n em: EntityManager\n rbac: TaskEntityAccessRbacService\n moduleConfigService: TaskPermissionsConfigService | null | undefined\n auth: TaskVisibilityAuth\n /**\n * `null`/`undefined` = unrestricted operator, matching what\n * `resolveOrganizationScopeFilter` returns for the wildcard scope.\n */\n organizationIds: readonly string[] | null | undefined\n /** The organization the ACL is loaded against, as every other route does. */\n aclOrganizationId: string | null\n /** Authored binding types the gate must be able to answer for. */\n entityTypes: Iterable<string>\n}\n\n/**\n * Assemble the request context: one ACL load, one classification pass, one\n * tenant-setting read.\n *\n * Nothing is caught. A resolver that throws must fail the whole request rather\n * than degrade to an empty map \u2014 an empty map denies today, but \"swallow and\n * carry on\" is the shape of bug that later becomes \"swallow and pass\".\n */\nexport async function resolveTaskVisibilityRequestContext(\n input: ResolveTaskVisibilityRequestContextInput,\n): Promise<TaskVisibilityRequestContext> {\n const scope: TaskEntityAccessScope = {\n tenantId: input.auth.tenantId,\n organizationId: input.aclOrganizationId,\n }\n const scopedEntityTypes = [...new Set(input.entityTypes)]\n\n const [access, policy] = await Promise.all([\n resolveTaskEntityAccess({\n entityTypes: scopedEntityTypes,\n em: input.em,\n rbac: input.rbac,\n userId: input.auth.userId,\n scope,\n }),\n resolveTaskVisibilityPolicy(input.moduleConfigService, input.auth.tenantId),\n ])\n\n return {\n principal: {\n kind: 'backoffice',\n userId: input.auth.userId,\n tenantId: input.auth.tenantId,\n organizationIds: input.organizationIds ?? null,\n roleNames: input.auth.roleNames,\n grantedFeatures: access.grantedFeatures,\n isSuperAdmin: access.isSuperAdmin,\n },\n policy,\n entityAccess: access.map,\n scopedEntityTypes,\n }\n}\n\n/** The slice of the DI container the route helper below reaches for. */\nexport type TaskVisibilityContainer = { resolve: <T>(name: string) => T }\n\n/**\n * An ACL that grants nothing.\n *\n * Used when `rbacService` cannot be resolved. Deny-everything is the only safe\n * reading of \"the authorization service is missing\", and it is loud \u2014 an empty\n * inbox is noticed immediately, whereas failing the request open would not be\n * noticed at all.\n */\nconst NO_GRANTS_RBAC: TaskEntityAccessRbacService = { loadAcl: async () => null }\n\nfunction resolveOptional<T>(container: TaskVisibilityContainer, name: string): T | null {\n try {\n return container.resolve<T>(name) ?? null\n } catch {\n return null\n }\n}\n\n/** Assemble the context from a request container. */\nexport async function resolveTaskVisibilityForRequest(input: {\n container: TaskVisibilityContainer\n em: EntityManager\n auth: TaskVisibilityAuth\n organizationIds: readonly string[] | null | undefined\n aclOrganizationId: string | null\n entityTypes: Iterable<string>\n}): Promise<TaskVisibilityRequestContext> {\n return resolveTaskVisibilityRequestContext({\n em: input.em,\n rbac: resolveOptional<TaskEntityAccessRbacService>(input.container, 'rbacService') ?? NO_GRANTS_RBAC,\n // A config read that cannot happen defaults to the NEW model, never the\n // permissive one \u2014 see `lib/task-permission-settings.ts`.\n moduleConfigService: resolveOptional<TaskPermissionsConfigService>(\n input.container,\n 'moduleConfigService',\n ),\n auth: input.auth,\n organizationIds: input.organizationIds,\n aclOrganizationId: input.aclOrganizationId,\n entityTypes: input.entityTypes,\n })\n}\n\nexport type ScopedTaskEntityTypeScope = {\n tenantId: string\n organizationIds: readonly string[] | null\n}\n\n/**\n * The distinct authored binding types in the caller's scope.\n *\n * One `SELECT DISTINCT unnest(entity_types)` rather than a whitelist derived\n * from the entity registry: the registry universe is hundreds of ids, each of\n * which would have to be classified (a query apiece for custom entities), while\n * the set a tenant actually binds tasks to is a handful. `unnest` of a NULL\n * array yields no rows, so a tenant whose tasks all predate the column answers\n * with an empty set and the whitelist collapses to \"rows about nothing\", which\n * is every row it has.\n */\nexport async function collectScopedTaskEntityTypes(\n em: EntityManager,\n scope: ScopedTaskEntityTypeScope,\n): Promise<string[]> {\n const params: unknown[] = [scope.tenantId]\n let sql = 'SELECT DISTINCT unnest(entity_types) AS entity_type FROM user_tasks WHERE tenant_id = ?'\n\n if (scope.organizationIds !== null) {\n if (scope.organizationIds.length === 0) return []\n sql += ` AND organization_id IN (${scope.organizationIds.map(() => '?').join(', ')})`\n params.push(...scope.organizationIds)\n }\n\n const rows = await em\n .getConnection()\n .execute<Array<{ entity_type: string | null }>>(sql, params)\n\n const types = new Set<string>()\n for (const row of rows) {\n const entityType = row?.entity_type\n if (typeof entityType === 'string' && entityType.length > 0) types.add(entityType)\n }\n return [...types]\n}\n\n/** The subset of `candidates` this caller may view records of. */\nexport function resolveAllowedTaskEntityTypes(\n context: TaskVisibilityRequestContext,\n candidates: Iterable<string> = context.scopedEntityTypes,\n): string[] {\n const allowed: string[] = []\n for (const entityType of new Set(candidates)) {\n const decision = context.entityAccess.get(entityType)\n // A missing key is a resolution failure, never a pass \u2014 the same rule the\n // predicate applies, so the two cannot disagree about a row.\n if (!decision || decision.kind !== 'requires') continue\n if (!hasAllFeatures(context.principal.grantedFeatures, decision.features)) continue\n allowed.push(entityType)\n }\n return allowed\n}\n\n/**\n * The ENTITY half of the rule as ORM conditions.\n *\n * Empty for a superadmin (who short-circuits the gate in the predicate too),\n * under the tenant opt-out (which skips the entity gate on reads by design),\n * and \u2014 deliberately \u2014 for a principal entitled to a DIAGNOSIS.\n *\n * That last case is the \u00A73.6 rule: a task hidden by the entity gate must never\n * disappear without trace. Excluding the row in SQL is exactly the trace-free\n * disappearance, because an administrator then sees a page that is short by an\n * unexplained number of rows and cannot tell \"no such task\" from \"you cannot see\n * its record\". So the gate is lifted from the `WHERE` for them, the predicate\n * still refuses each row, and the caller reports the refusals as MARKERS \u2014\n * `partitionTaskPage` below. The rows themselves never reach the response body;\n * only their ids and the entity type that blocked them do, which is exactly what\n * \u00A72.7 already entitles a `view_all` holder to on the single-task surface.\n */\nexport function buildTaskEntityGateConditions(\n context: TaskVisibilityRequestContext,\n): Record<string, unknown>[] {\n if (context.principal.isSuperAdmin) return []\n if (!context.policy.businessContextEnabled) return []\n if (canDiagnoseTaskRefusal(context.principal)) return []\n return [\n {\n $or: [\n { entityTypes: null },\n { entityTypes: { $contained: resolveAllowedTaskEntityTypes(context) } },\n ],\n },\n ]\n}\n\n/**\n * RELATIONSHIP \u2228 ADMINISTRATIVE plus ENTITY, as conditions to push onto an\n * existing `$and` array. Tenant and organization scoping stay with the caller,\n * which already applies them on every query.\n */\nexport function buildTaskVisibilityRequestConditions(\n context: TaskVisibilityRequestContext,\n options: TaskVisibilityFilterOptions = {},\n): Record<string, unknown>[] {\n return [\n ...buildTaskVisibilityConditions(context.principal, context.policy, options),\n ...buildTaskEntityGateConditions(context),\n ]\n}\n\nfunction asBindingFacts(value: unknown): TaskEntityBindingFact[] {\n if (!Array.isArray(value)) return []\n const bindings: TaskEntityBindingFact[] = []\n for (const item of value) {\n if (!item || typeof item !== 'object' || Array.isArray(item)) continue\n const record = item as Record<string, unknown>\n if (typeof record.entityType !== 'string' || typeof record.entityId !== 'string') continue\n bindings.push({ entityType: record.entityType, entityId: record.entityId })\n }\n return bindings\n}\n\nexport type TaskFactsOptions = {\n /** Queue feature for the source that produced this row, when it declares one. */\n administrativeQueueFeature?: string | null\n}\n\n/**\n * Project a `UserTask` row onto the facts the predicate reads.\n *\n * `assigneeKind` is defaulted rather than coalesced: the column is NOT NULL, and\n * a row read through a projection that predates it is a backoffice task like\n * every row before it.\n */\nexport function toTaskFacts(task: UserTask, options: TaskFactsOptions = {}): TaskFacts {\n return {\n id: task.id,\n tenantId: task.tenantId,\n organizationId: task.organizationId,\n status: task.status,\n assignedTo: task.assignedTo ?? null,\n assigneeKind: task.assigneeKind ?? 'user',\n assignedToRoles: task.assignedToRoles ?? null,\n claimedBy: task.claimedBy ?? null,\n entityBindings: asBindingFacts(task.entityBindings),\n administrativeQueueFeature: options.administrativeQueueFeature ?? null,\n }\n}\n\n/**\n * The distinct authored binding types a set of already-loaded tasks references \u2014\n * what a single-task surface feeds `resolveTaskVisibilityRequestContext`.\n */\nexport function collectTaskEntityTypesFromTasks(tasks: Iterable<UserTask>): string[] {\n return collectTaskEntityTypes(\n [...tasks].map((task) => ({ entityBindings: asBindingFacts(task.entityBindings) })),\n )\n}\n\n/** The predicate's answer for one already-loaded row. */\nexport function decideTaskAccess(\n context: TaskVisibilityRequestContext,\n task: UserTask,\n options: TaskFactsOptions = {},\n): TaskVisibilityDecision {\n return decideTaskVisibility(\n context.principal,\n toTaskFacts(task, options),\n context.entityAccess,\n context.policy,\n )\n}\n\n/**\n * The act surfaces a detail response advertises for one already-loaded row.\n *\n * The server has always known this \u2014 `decideTaskAccess` returns `actable` and\n * `claimable` on every request \u2014 and until now it threw the answer away, which\n * is why the backoffice task page rendered a Complete button that 409s for a\n * `workflows.tasks.view_all` administrator. Sending the decision is the fix; a\n * client re-deriving it is the bug coming back.\n */\nexport function resolveTaskAffordancesForRequest(\n context: TaskVisibilityRequestContext,\n task: UserTask,\n decision: TaskVisibilityDecision,\n options: TaskFactsOptions = {},\n): TaskAffordances {\n return resolveTaskAffordances(context.principal, toTaskFacts(task, options), decision)\n}\n\n/**\n * The rows of an already-filtered page the predicate agrees are visible.\n *\n * The `WHERE` this module builds IS this rule, so in practice nothing is\n * dropped here and `pagination.total` stays exactly the count of what the caller\n * may see. It runs anyway because the predicate is the single decision point and\n * because the failure direction matters: should the SQL gate and the predicate\n * ever disagree, losing a row from a page is recoverable and leaking one is not.\n */\nexport function filterVisibleTasks(\n context: TaskVisibilityRequestContext,\n tasks: readonly UserTask[],\n options: TaskFactsOptions = {},\n): UserTask[] {\n return tasks.filter((task) => decideTaskAccess(context, task, options).visible)\n}\n\n/**\n * A row an administrator may know EXISTS but may not read.\n *\n * Three fields and no fourth. The id is what makes the marker actionable (it is\n * the argument to reassignment and to a support conversation), the reason\n * separates an author's typo from a policy refusal, and the entity type names\n * the grant that would fix it. Everything that would say what the task is ABOUT\n * \u2014 its name, description, form schema, form data, bindings, assignee \u2014 is\n * absent by construction rather than by redaction, because a redaction is a\n * field somebody later un-redacts.\n */\nexport type TaskEntityHiddenMarker = {\n id: string\n reason: 'denied:entity-access' | 'denied:unknown-entity-type'\n /** The binding type that blocked it, when the predicate identified one. */\n entityType: string | null\n}\n\nexport type TaskPagePartition = {\n /** Rows the caller may read in full. */\n visible: UserTask[]\n /**\n * Rows the entity gate refused to a caller entitled to know they are there.\n * Always empty for everybody else \u2014 the gate excluded those rows in SQL, so\n * there is nothing to report and nothing is disclosed.\n */\n entityHidden: TaskEntityHiddenMarker[]\n}\n\n/**\n * Split an already-filtered page into what the caller may read and what they may\n * only be told about.\n *\n * This is the counterpart to lifting the entity gate for a diagnosable\n * principal: the SQL returns the rows, the predicate refuses them one by one,\n * and the refusals become markers instead of an unexplained gap in the page. For\n * everybody else the `WHERE` already removed them, `entityHidden` is empty, and\n * the result is byte-identical to `filterVisibleTasks`.\n *\n * A refusal that is NOT an entity refusal (a foreign tenant, an organization the\n * caller cannot see, no relationship at all) is dropped silently, exactly as\n * before: those callers have no legitimate knowledge that the row exists, and a\n * marker would be the disclosure the 404 policy exists to prevent.\n */\nexport function partitionTaskPage(\n context: TaskVisibilityRequestContext,\n tasks: readonly UserTask[],\n options: TaskFactsOptions = {},\n): TaskPagePartition {\n const visible: UserTask[] = []\n const entityHidden: TaskEntityHiddenMarker[] = []\n const diagnosable = canDiagnoseTaskRefusal(context.principal)\n\n for (const task of tasks) {\n const decision = decideTaskAccess(context, task, options)\n if (decision.visible) {\n visible.push(task)\n continue\n }\n if (!diagnosable) continue\n if (\n decision.reason !== 'denied:entity-access' &&\n decision.reason !== 'denied:unknown-entity-type'\n ) {\n continue\n }\n entityHidden.push({\n id: task.id,\n reason: decision.reason,\n entityType: decision.blockedEntityType ?? null,\n })\n }\n\n return { visible, entityHidden }\n}\n\n/**\n * Whether this caller is entitled to a diagnosis rather than a bare 404.\n *\n * Only a principal who can already see the row in a list view \u2014 a `view_all`\n * holder or a superadmin \u2014 learns WHICH entity type blocked them. Everybody else\n * gets an answer indistinguishable from \"no such task\", because they have no\n * legitimate knowledge that the row exists at all.\n */\nexport function canDiagnoseTaskRefusal(principal: BackofficeTaskPrincipal): boolean {\n return (\n principal.isSuperAdmin || hasFeature(principal.grantedFeatures, WORKFLOWS_TASKS_VIEW_ALL_FEATURE)\n )\n}\n\nexport type TaskRefusal = {\n /** 404 hides existence, 403 diagnoses, 409 is the act-path conflict. */\n status: 403 | 404 | 409\n body: Record<string, unknown>\n}\n\n/**\n * The generic body every non-diagnosable refusal returns.\n *\n * Byte-identical to the body a genuinely missing id produces \u2014 a cross-tenant\n * id, an organization the caller cannot see, a task they have no relationship\n * to and a random uuid must all be the same answer.\n */\nexport const TASK_NOT_FOUND_BODY: Record<string, unknown> = { error: 'Task not found' }\n\n/**\n * Message and code the task handler already throws when the row belongs to\n * somebody else. Reused verbatim so enforcing ownership one layer earlier does\n * not change what a client sees.\n */\nexport const TASK_ASSIGNED_TO_ANOTHER_USER_BODY: Record<string, unknown> = {\n error: 'Task is assigned to another user',\n code: 'TASK_ASSIGNED_TO_ANOTHER_USER',\n}\n\n/**\n * Refusal for a row \u00A76.4 makes nobody's: no assignee, no claim and no role\n * queue. Administration widens seeing, never acting, so the remedy is\n * `workflows.tasks.reassign` rather than a wider grant.\n */\nexport const TASK_NOT_ACTIONABLE_BODY: Record<string, unknown> = {\n error: 'Task is not assigned to anyone; reassign it before acting on it',\n code: 'TASK_NOT_ACTIONABLE',\n}\n\nexport type TaskActRefusalOptions = TaskFactsOptions & {\n /**\n * Enforce `actable` here rather than leaving it to the task handler.\n *\n * ON for **complete**, which is the whole point of the narrowing: holding\n * `workflows.tasks.complete` must no longer complete anyone else's work, and\n * the handler deliberately leaves an OWNERLESS row open to anyone the feature\n * gate admitted \u2014 the pre-change semantics.\n *\n * OFF for **claim** and **unclaim**, where the handler is already the precise\n * authority and answering here would coarsen its codes: an empty role queue is\n * `TASK_NOT_ROLE_ASSIGNED`, a queue the caller does not belong to is\n * `TASK_NOT_FOUND`, and unclaiming a row nobody holds is `TASK_NOT_FOUND`.\n * Pre-empting those with one generic refusal would lose information the client\n * has always had.\n */\n requireOwnership?: boolean\n}\n\n/**\n * The act gate for claim / unclaim / complete.\n *\n * Deliberately narrow: it answers only what the task handler cannot answer for\n * itself and hands everything else through, so the handler keeps producing the\n * exact error codes it always has (`TASK_NOT_FOUND`, `TASK_ALREADY_ASSIGNED`,\n * `TASK_NOT_ROLE_ASSIGNED`, `TASK_ASSIGNED_TO_ANOTHER_USER`) and keeps taking\n * the row with its own compare-and-set.\n *\n * 1. **Can this caller see the row at all?** Running FIRST is the disclosure fix:\n * `claimUserTask` reports `TASK_ALREADY_ASSIGNED` before it checks queue\n * membership, so without this a caller with no relationship to the task could\n * tell an existing task from a nonexistent one by the status code alone.\n * 2. **Does the entity gate block acting?** Reachable only under the tenant\n * opt-out, which restores the READ and never the act path. Refused as a plain\n * 404 \u2014 a reason here would leak the binding to a principal the gate just\n * refused.\n * 3. **Is the row theirs?** Only when `requireOwnership` is set. The owner is\n * `claimedBy ?? assignedTo`: holding a task's queued role confers the right\n * to CLAIM an open row, never to finish one a colleague already claimed.\n *\n * A row in a terminal status is always passed through: the handler answers\n * `TASK_NOT_FOUND` for it, exactly as before.\n */\nexport function resolveTaskActRefusal(\n context: TaskVisibilityRequestContext,\n decision: TaskVisibilityDecision,\n task: UserTask,\n options: TaskActRefusalOptions = {},\n): TaskRefusal | null {\n if (!decision.visible) return resolveTaskRefusal(context, decision)\n\n if (decision.blockedEntityType) return { status: 404, body: TASK_NOT_FOUND_BODY }\n\n if (!options.requireOwnership || decision.actable) return null\n\n const facts = toTaskFacts(task, options)\n if (!TASK_ACTIONABLE_STATUSES.includes(facts.status)) return null\n\n return currentTaskOwnerId(facts) !== null\n ? { status: 409, body: TASK_ASSIGNED_TO_ANOTHER_USER_BODY }\n : { status: 403, body: TASK_NOT_ACTIONABLE_BODY }\n}\n\nexport type TaskActionGateResult =\n | { allowed: true; task: UserTask; visibility: TaskVisibilityRequestContext }\n | { allowed: false; refusal: TaskRefusal }\n\n/**\n * The whole \u00A76.4 gate for one act route, in the order that keeps existence\n * undisclosed.\n *\n * The lookup carries tenant AND organization, so a foreign id resolves to\n * nothing before the predicate \u2014 and long before any write. That ordering is the\n * point: it is what keeps `claimUserTask`'s conditional `UPDATE` from ever\n * touching another tenant's row.\n */\nexport async function gateTaskAction(input: {\n container: TaskVisibilityContainer\n em: EntityManager\n auth: TaskVisibilityAuth\n taskId: string\n organizationId: string\n administrativeQueueFeature?: string | null\n /** See `TaskActRefusalOptions.requireOwnership` \u2014 ON for complete only. */\n requireOwnership?: boolean\n}): Promise<TaskActionGateResult> {\n const task = await input.em.findOne(UserTaskEntity, {\n id: input.taskId,\n tenantId: input.auth.tenantId,\n organizationId: input.organizationId,\n })\n\n if (!task) return { allowed: false, refusal: { status: 404, body: TASK_NOT_FOUND_BODY } }\n\n const visibility = await resolveTaskVisibilityForRequest({\n container: input.container,\n em: input.em,\n auth: input.auth,\n organizationIds: [input.organizationId],\n aclOrganizationId: input.organizationId,\n entityTypes: collectTaskEntityTypesFromTasks([task]),\n })\n\n const options: TaskActRefusalOptions = {\n administrativeQueueFeature: input.administrativeQueueFeature ?? null,\n requireOwnership: input.requireOwnership ?? false,\n }\n const refusal = resolveTaskActRefusal(\n visibility,\n decideTaskAccess(visibility, task, options),\n task,\n options,\n )\n\n return refusal ? { allowed: false, refusal } : { allowed: true, task, visibility }\n}\n\nexport function resolveTaskRefusal(\n context: TaskVisibilityRequestContext,\n decision: TaskVisibilityDecision,\n): TaskRefusal {\n const isEntityRefusal =\n decision.reason === 'denied:entity-access' || decision.reason === 'denied:unknown-entity-type'\n\n if (isEntityRefusal && canDiagnoseTaskRefusal(context.principal)) {\n return {\n status: 403,\n body: {\n error: 'Forbidden',\n reason: decision.reason,\n ...(decision.blockedEntityType ? { entityType: decision.blockedEntityType } : {}),\n },\n }\n }\n\n return { status: 404, body: TASK_NOT_FOUND_BODY }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,194 @@
1
+ import { isOrganizationAccessAllowed } from "@open-mercato/shared/lib/auth/organizationAccess";
2
+ import { hasAllFeatures, hasFeature } from "@open-mercato/shared/security/features";
3
+ const WORKFLOWS_TASKS_VIEW_FEATURE = "workflows.tasks.view";
4
+ const WORKFLOWS_TASKS_VIEW_ALL_FEATURE = "workflows.tasks.view_all";
5
+ const WORKFLOWS_TASKS_REASSIGN_FEATURE = "workflows.tasks.reassign";
6
+ const TASK_ACTIONABLE_STATUSES = ["PENDING", "IN_PROGRESS"];
7
+ function deny(reason, blockedEntityType) {
8
+ return blockedEntityType ? { visible: false, actable: false, claimable: false, reason, blockedEntityType } : { visible: false, actable: false, claimable: false, reason };
9
+ }
10
+ function hasRoleOverlap(taskRoles, roleNames) {
11
+ if (!taskRoles || taskRoles.length === 0 || roleNames.length === 0) return false;
12
+ const held = new Set(roleNames);
13
+ return taskRoles.some((role) => held.has(role));
14
+ }
15
+ function isUnassignedQueueItem(task) {
16
+ return task.assignedTo === null && task.claimedBy === null && (task.assignedToRoles === null || task.assignedToRoles.length === 0);
17
+ }
18
+ function evaluateEntityClause(principal, task, entityAccess) {
19
+ if (principal.isSuperAdmin) return { ok: true };
20
+ for (const binding of task.entityBindings) {
21
+ const decision = entityAccess.get(binding.entityType);
22
+ if (!decision) {
23
+ return { ok: false, reason: "denied:entity-access", entityType: binding.entityType };
24
+ }
25
+ if (decision.kind === "unknown-entity-type") {
26
+ return { ok: false, reason: "denied:unknown-entity-type", entityType: binding.entityType };
27
+ }
28
+ if (decision.kind === "unavailable") {
29
+ return { ok: false, reason: "denied:entity-access", entityType: binding.entityType };
30
+ }
31
+ if (!hasAllFeatures(principal.grantedFeatures, decision.features)) {
32
+ return { ok: false, reason: "denied:entity-access", entityType: binding.entityType };
33
+ }
34
+ }
35
+ return { ok: true };
36
+ }
37
+ function administrativeQueueFeatureOf(task) {
38
+ return task.administrativeQueueFeature ?? WORKFLOWS_TASKS_VIEW_ALL_FEATURE;
39
+ }
40
+ function resolveRelationshipReason(principal, task) {
41
+ if (task.assigneeKind === "user" && task.assignedTo === principal.userId) return "assignee";
42
+ if (task.claimedBy !== null && task.claimedBy === principal.userId) return "claimant";
43
+ if (hasRoleOverlap(task.assignedToRoles, principal.roleNames)) return "role-queue";
44
+ return null;
45
+ }
46
+ function resolveAdministrativeReason(principal, task) {
47
+ if (principal.isSuperAdmin) return "administrative";
48
+ if (hasFeature(principal.grantedFeatures, WORKFLOWS_TASKS_VIEW_ALL_FEATURE)) return "administrative";
49
+ if (isUnassignedQueueItem(task) && hasFeature(principal.grantedFeatures, administrativeQueueFeatureOf(task))) {
50
+ return "administrative-queue";
51
+ }
52
+ return null;
53
+ }
54
+ function currentTaskOwnerId(task) {
55
+ if (task.claimedBy !== null) return task.claimedBy;
56
+ if (task.assigneeKind === "user") return task.assignedTo;
57
+ return null;
58
+ }
59
+ function decideBackoffice(principal, task, entityAccess, policy) {
60
+ if (task.tenantId !== principal.tenantId) return deny("denied:tenant");
61
+ if (!isOrganizationAccessAllowed({
62
+ isSuperAdmin: principal.isSuperAdmin,
63
+ allowedOrganizationIds: principal.organizationIds,
64
+ targetOrganizationId: task.organizationId
65
+ })) {
66
+ return deny("denied:organization");
67
+ }
68
+ const relationshipReason = resolveRelationshipReason(principal, task);
69
+ const administrativeReason = relationshipReason ? null : resolveAdministrativeReason(principal, task);
70
+ const admitReason = relationshipReason ?? administrativeReason;
71
+ const entity = evaluateEntityClause(principal, task, entityAccess);
72
+ const owner = currentTaskOwnerId(task);
73
+ const ownsTheRow = owner !== null ? owner === principal.userId : hasRoleOverlap(task.assignedToRoles, principal.roleNames);
74
+ const actable = entity.ok && ownsTheRow && task.assigneeKind === "user" && TASK_ACTIONABLE_STATUSES.includes(task.status);
75
+ const claimable = actable && task.assignedTo === null && task.claimedBy === null && task.status === "PENDING" && hasRoleOverlap(task.assignedToRoles, principal.roleNames);
76
+ if (admitReason && entity.ok) {
77
+ return { visible: true, actable, claimable, reason: admitReason };
78
+ }
79
+ if (!policy.businessContextEnabled && hasFeature(principal.grantedFeatures, WORKFLOWS_TASKS_VIEW_FEATURE)) {
80
+ return {
81
+ visible: true,
82
+ actable,
83
+ claimable,
84
+ reason: "legacy-read-filter",
85
+ // Reported even though the row is admitted: the read came back, the entity
86
+ // gate did not, and an act surface must be able to tell the difference.
87
+ ...entity.ok ? {} : { blockedEntityType: entity.entityType }
88
+ };
89
+ }
90
+ if (!admitReason) return deny("denied:no-relationship");
91
+ if (!entity.ok) return deny(entity.reason, entity.entityType);
92
+ return deny("denied:no-relationship");
93
+ }
94
+ function decidePortal(principal, task) {
95
+ if (task.tenantId !== principal.tenantId) return deny("denied:tenant");
96
+ if (task.organizationId !== principal.organizationId) return deny("denied:organization");
97
+ if (task.assigneeKind !== "customer") return deny("denied:portal-wrong-assignee-kind");
98
+ if (task.entityBindings.length === 0) return deny("denied:portal-unbound");
99
+ const ownsEveryBinding = task.entityBindings.every(
100
+ (binding) => principal.ownedRecordIds.has(binding.entityId)
101
+ );
102
+ if (!ownsEveryBinding) return deny("denied:portal-not-owner");
103
+ if (task.assignedTo === principal.principalId) {
104
+ const actable = TASK_ACTIONABLE_STATUSES.includes(task.status);
105
+ return { visible: true, actable, claimable: false, reason: "portal-assignee" };
106
+ }
107
+ if (principal.isPortalAdmin) {
108
+ return { visible: true, actable: false, claimable: false, reason: "portal-company-admin" };
109
+ }
110
+ return deny("denied:portal-not-owner");
111
+ }
112
+ function decideTaskVisibility(principal, task, entityAccess, policy) {
113
+ if (principal.kind === "portal") return decidePortal(principal, task);
114
+ return decideBackoffice(principal, task, entityAccess, policy);
115
+ }
116
+ const TASK_REASSIGNABLE_STATUSES = ["PENDING", "IN_PROGRESS"];
117
+ const TASK_RELEASABLE_STATUS = "IN_PROGRESS";
118
+ function resolveTaskAffordances(principal, task, decision) {
119
+ const entityGateClosed = decision.blockedEntityType !== void 0;
120
+ const actSurfaceOpen = decision.visible && !entityGateClosed;
121
+ const canComplete = decision.visible && decision.actable;
122
+ const canClaim = decision.visible && decision.claimable;
123
+ const canRelease = actSurfaceOpen && task.status === TASK_RELEASABLE_STATUS && task.claimedBy === principal.userId;
124
+ const canReassign = actSurfaceOpen && TASK_REASSIGNABLE_STATUSES.includes(task.status) && (principal.isSuperAdmin || hasFeature(principal.grantedFeatures, WORKFLOWS_TASKS_REASSIGN_FEATURE));
125
+ return {
126
+ canComplete,
127
+ canClaim,
128
+ canRelease,
129
+ canReassign,
130
+ actBlockedReason: resolveActBlockReason(principal, task, decision, {
131
+ canComplete,
132
+ entityGateClosed
133
+ })
134
+ };
135
+ }
136
+ function resolveActBlockReason(principal, task, decision, state) {
137
+ if (state.canComplete) return null;
138
+ if (!decision.visible) return null;
139
+ if (state.entityGateClosed) return "unavailable";
140
+ if (!TASK_ACTIONABLE_STATUSES.includes(task.status)) return "not-workable";
141
+ const owner = currentTaskOwnerId(task);
142
+ if (owner !== null) return owner === principal.userId ? "unavailable" : "owned-by-another";
143
+ if (task.assignedToRoles !== null && task.assignedToRoles.length > 0) return "not-in-your-queue";
144
+ return "unowned";
145
+ }
146
+ function buildTaskVisibilityConditions(principal, policy, options = {}) {
147
+ if (principal.isSuperAdmin) return [];
148
+ if (hasFeature(principal.grantedFeatures, WORKFLOWS_TASKS_VIEW_ALL_FEATURE)) return [];
149
+ if (!policy.businessContextEnabled && hasFeature(principal.grantedFeatures, WORKFLOWS_TASKS_VIEW_FEATURE)) {
150
+ return [];
151
+ }
152
+ const arms = [
153
+ // `assigneeKind` discriminates a backoffice user id from a portal principal
154
+ // id in the same column, so a customer-assigned row can never match a
155
+ // backoffice caller whose user id happens to collide.
156
+ { assignedTo: principal.userId, assigneeKind: "user" },
157
+ { claimedBy: principal.userId }
158
+ ];
159
+ if (principal.roleNames.length > 0) {
160
+ arms.push({ assignedToRoles: { $overlap: [...principal.roleNames] } });
161
+ }
162
+ const queueFeature = options.administrativeQueueFeature;
163
+ if (queueFeature && hasFeature(principal.grantedFeatures, queueFeature)) {
164
+ arms.push({
165
+ assignedTo: null,
166
+ claimedBy: null,
167
+ $or: [{ assignedToRoles: null }, { assignedToRoles: { $eq: [] } }]
168
+ });
169
+ }
170
+ return [{ $or: arms }];
171
+ }
172
+ function buildTaskVisibilityFilter(principal, policy, options = {}) {
173
+ const where = { tenantId: principal.tenantId };
174
+ if (principal.organizationIds !== null) {
175
+ where.organizationId = { $in: [...principal.organizationIds] };
176
+ }
177
+ const conditions = buildTaskVisibilityConditions(principal, policy, options);
178
+ if (conditions.length > 0) where.$and = conditions;
179
+ return where;
180
+ }
181
+ export {
182
+ TASK_ACTIONABLE_STATUSES,
183
+ TASK_REASSIGNABLE_STATUSES,
184
+ TASK_RELEASABLE_STATUS,
185
+ WORKFLOWS_TASKS_REASSIGN_FEATURE,
186
+ WORKFLOWS_TASKS_VIEW_ALL_FEATURE,
187
+ WORKFLOWS_TASKS_VIEW_FEATURE,
188
+ buildTaskVisibilityConditions,
189
+ buildTaskVisibilityFilter,
190
+ currentTaskOwnerId,
191
+ decideTaskVisibility,
192
+ resolveTaskAffordances
193
+ };
194
+ //# sourceMappingURL=task-visibility.js.map