@open-mercato/core 0.7.1-develop.7193.1.910a5b0a1e → 0.7.1-develop.7194.1.ab4fc81f82
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.
- package/.turbo/turbo-build.log +2 -2
- package/AGENTS.md +4 -3
- package/agentic/standalone-guide.md +1 -1
- package/build.mjs +16 -0
- package/dist/generated/entities/action_log/index.js +2 -0
- package/dist/generated/entities/action_log/index.js.map +2 -2
- package/dist/generated/entities/user/index.js +2 -0
- package/dist/generated/entities/user/index.js.map +2 -2
- package/dist/generated/entities/user_task/index.js +14 -0
- package/dist/generated/entities/user_task/index.js.map +2 -2
- package/dist/generated/entities/workflow_definition/index.js +6 -0
- package/dist/generated/entities/workflow_definition/index.js.map +2 -2
- package/dist/generated/entities/workflow_definition_draft/index.js +25 -0
- package/dist/generated/entities/workflow_definition_draft/index.js.map +7 -0
- package/dist/generated/entities/workflow_definition_metric_rollup/index.js +23 -0
- package/dist/generated/entities/workflow_definition_metric_rollup/index.js.map +7 -0
- package/dist/generated/entities/workflow_instance/index.js +4 -0
- package/dist/generated/entities/workflow_instance/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +4 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +39 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/workflowsFixtures.js +477 -2
- package/dist/helpers/integration/workflowsFixtures.js.map +2 -2
- package/dist/helpers/integration/workflowsUi.js +148 -0
- package/dist/helpers/integration/workflowsUi.js.map +7 -0
- package/dist/modules/attachments/lib/createFromBuffer.js +79 -0
- package/dist/modules/attachments/lib/createFromBuffer.js.map +7 -0
- package/dist/modules/audit_logs/data/entities.js +5 -0
- package/dist/modules/audit_logs/data/entities.js.map +2 -2
- package/dist/modules/audit_logs/data/validators.js +1 -0
- package/dist/modules/audit_logs/data/validators.js.map +2 -2
- package/dist/modules/audit_logs/lib/projections.js +2 -1
- package/dist/modules/audit_logs/lib/projections.js.map +2 -2
- package/dist/modules/audit_logs/migrations/Migration20260625120000.js +15 -0
- package/dist/modules/audit_logs/migrations/Migration20260625120000.js.map +7 -0
- package/dist/modules/audit_logs/services/actionLogService.js +3 -0
- package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
- package/dist/modules/auth/data/entities.js +6 -0
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/lib/executionPrincipal.js +140 -0
- package/dist/modules/auth/lib/executionPrincipal.js.map +7 -0
- package/dist/modules/auth/migrations/Migration20260625050000.js +13 -0
- package/dist/modules/auth/migrations/Migration20260625050000.js.map +7 -0
- package/dist/modules/business_rules/components/InlineRuleEditor.js +154 -0
- package/dist/modules/business_rules/components/InlineRuleEditor.js.map +7 -0
- package/dist/modules/business_rules/data/validators.js +6 -0
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +5 -3
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/commands/products.js +5 -0
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/workflows.js +19 -0
- package/dist/modules/catalog/workflows.js.map +7 -0
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/cli.js +80 -0
- package/dist/modules/customer_accounts/cli.js.map +7 -0
- package/dist/modules/customer_accounts/lib/customerRoleAclSync.js +59 -0
- package/dist/modules/customer_accounts/lib/customerRoleAclSync.js.map +7 -0
- package/dist/modules/customer_accounts/setup.js +4 -2
- package/dist/modules/customer_accounts/setup.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +4 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/detail/ChangelogEntryRow.js +1 -1
- package/dist/modules/customers/components/detail/ChangelogEntryRow.js.map +2 -2
- package/dist/modules/customers/components/detail/utils.js +2 -0
- package/dist/modules/customers/components/detail/utils.js.map +2 -2
- package/dist/modules/customers/events.js +13 -2
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/link-workflow-task-handler.js +64 -0
- package/dist/modules/customers/lib/link-workflow-task-handler.js.map +7 -0
- package/dist/modules/customers/lib/todoCompatibility.js +1 -1
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/customers/lib/workflowTaskLink.js +9 -0
- package/dist/modules/customers/lib/workflowTaskLink.js.map +7 -0
- package/dist/modules/customers/subscribers/link-workflow-task.js +12 -0
- package/dist/modules/customers/subscribers/link-workflow-task.js.map +7 -0
- package/dist/modules/customers/workflows.js +29 -0
- package/dist/modules/customers/workflows.js.map +7 -0
- package/dist/modules/entities/api/records.js +13 -33
- package/dist/modules/entities/api/records.js.map +3 -3
- package/dist/modules/entities/lib/entityClassification.js +60 -0
- package/dist/modules/entities/lib/entityClassification.js.map +7 -0
- package/dist/modules/sales/commands/documents.js +31 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/events.js +12 -1
- package/dist/modules/sales/events.js.map +2 -2
- package/dist/modules/sales/workflows.js +12 -1
- package/dist/modules/sales/workflows.js.map +2 -2
- package/dist/modules/seeds/cli.js +199 -0
- package/dist/modules/seeds/cli.js.map +7 -0
- package/dist/modules/seeds/examples/sample-seed.json +26 -0
- package/dist/modules/seeds/index.js +12 -0
- package/dist/modules/seeds/index.js.map +7 -0
- package/dist/modules/workflows/acl.js +96 -0
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/ai-agents.js +50 -0
- package/dist/modules/workflows/ai-agents.js.map +7 -0
- package/dist/modules/workflows/ai-tools/authoring-pack.js +582 -0
- package/dist/modules/workflows/ai-tools/authoring-pack.js.map +7 -0
- package/dist/modules/workflows/ai-tools/types.js +43 -0
- package/dist/modules/workflows/ai-tools/types.js.map +7 -0
- package/dist/modules/workflows/ai-tools.js +10 -0
- package/dist/modules/workflows/ai-tools.js.map +7 -0
- package/dist/modules/workflows/api/command-settings/route.js +137 -0
- package/dist/modules/workflows/api/command-settings/route.js.map +7 -0
- package/dist/modules/workflows/api/commands/route.js +72 -0
- package/dist/modules/workflows/api/commands/route.js.map +7 -0
- package/dist/modules/workflows/api/definitions/[id]/callers/route.js +76 -0
- package/dist/modules/workflows/api/definitions/[id]/callers/route.js.map +7 -0
- package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js +134 -0
- package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js.map +7 -0
- package/dist/modules/workflows/api/definitions/[id]/customize/route.js +5 -1
- package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/draft/route.js +286 -0
- package/dist/modules/workflows/api/definitions/[id]/draft/route.js.map +7 -0
- package/dist/modules/workflows/api/definitions/[id]/publish/route.js +207 -0
- package/dist/modules/workflows/api/definitions/[id]/publish/route.js.map +7 -0
- package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +5 -0
- package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/route.js +93 -9
- package/dist/modules/workflows/api/definitions/[id]/route.js.map +3 -3
- package/dist/modules/workflows/api/definitions/[id]/test-step/route.js +210 -0
- package/dist/modules/workflows/api/definitions/[id]/test-step/route.js.map +7 -0
- package/dist/modules/workflows/api/definitions/generate/route.js +233 -0
- package/dist/modules/workflows/api/definitions/generate/route.js.map +7 -0
- package/dist/modules/workflows/api/definitions/route.js +61 -113
- package/dist/modules/workflows/api/definitions/route.js.map +2 -2
- package/dist/modules/workflows/api/definitions/serialize.js +9 -0
- package/dist/modules/workflows/api/definitions/serialize.js.map +2 -2
- package/dist/modules/workflows/api/endpoints/route.js +69 -0
- package/dist/modules/workflows/api/endpoints/route.js.map +7 -0
- package/dist/modules/workflows/api/functions/route.js +73 -0
- package/dist/modules/workflows/api/functions/route.js.map +7 -0
- package/dist/modules/workflows/api/grantable-features/route.js +75 -0
- package/dist/modules/workflows/api/grantable-features/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/[id]/context/route.js +180 -0
- package/dist/modules/workflows/api/instances/[id]/context/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js +184 -0
- package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/[id]/retry/route.js +12 -2
- package/dist/modules/workflows/api/instances/[id]/retry/route.js.map +2 -2
- package/dist/modules/workflows/api/instances/[id]/step-through/route.js +148 -0
- package/dist/modules/workflows/api/instances/[id]/step-through/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/[id]/steps/route.js +123 -0
- package/dist/modules/workflows/api/instances/[id]/steps/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/[id]/would-do/route.js +172 -0
- package/dist/modules/workflows/api/instances/[id]/would-do/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/bulk-replay/route.js +117 -0
- package/dist/modules/workflows/api/instances/bulk-replay/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/failure-queue/route.js +165 -0
- package/dist/modules/workflows/api/instances/failure-queue/route.js.map +7 -0
- package/dist/modules/workflows/api/instances/route.js +94 -3
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/metrics/definitions/route.js +188 -0
- package/dist/modules/workflows/api/metrics/definitions/route.js.map +7 -0
- package/dist/modules/workflows/api/openapi.js +415 -4
- package/dist/modules/workflows/api/openapi.js.map +2 -2
- package/dist/modules/workflows/api/portal/tasks/[id]/complete/route.js +132 -0
- package/dist/modules/workflows/api/portal/tasks/[id]/complete/route.js.map +7 -0
- package/dist/modules/workflows/api/portal/tasks/[id]/route.js +97 -0
- package/dist/modules/workflows/api/portal/tasks/[id]/route.js.map +7 -0
- package/dist/modules/workflows/api/portal/tasks/route.js +126 -0
- package/dist/modules/workflows/api/portal/tasks/route.js.map +7 -0
- package/dist/modules/workflows/api/rule-usage/route.js +80 -0
- package/dist/modules/workflows/api/rule-usage/route.js.map +7 -0
- package/dist/modules/workflows/api/task-settings/route.js +107 -0
- package/dist/modules/workflows/api/task-settings/route.js.map +7 -0
- package/dist/modules/workflows/api/tasks/[id]/claim/route.js +27 -16
- package/dist/modules/workflows/api/tasks/[id]/claim/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/[id]/complete/route.js +40 -16
- package/dist/modules/workflows/api/tasks/[id]/complete/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/[id]/reassign/route.js +150 -0
- package/dist/modules/workflows/api/tasks/[id]/reassign/route.js.map +7 -0
- package/dist/modules/workflows/api/tasks/[id]/route.js +39 -6
- package/dist/modules/workflows/api/tasks/[id]/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js +100 -0
- package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js.map +7 -0
- package/dist/modules/workflows/api/tasks/route.js +37 -6
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/serialize.js +83 -0
- package/dist/modules/workflows/api/tasks/serialize.js.map +7 -0
- package/dist/modules/workflows/api/templates/route.js +69 -0
- package/dist/modules/workflows/api/templates/route.js.map +7 -0
- package/dist/modules/workflows/api/work-inbox/next/route.js +129 -0
- package/dist/modules/workflows/api/work-inbox/next/route.js.map +7 -0
- package/dist/modules/workflows/api/work-inbox/route.js +119 -0
- package/dist/modules/workflows/api/work-inbox/route.js.map +7 -0
- package/dist/modules/workflows/backend/config/workflows/page.js +10 -0
- package/dist/modules/workflows/backend/config/workflows/page.js.map +7 -0
- package/dist/modules/workflows/backend/config/workflows/page.meta.js +35 -0
- package/dist/modules/workflows/backend/config/workflows/page.meta.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/[id]/page.js +6 -271
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +3 -3
- package/dist/modules/workflows/backend/definitions/create/page.js +7 -56
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +131 -51
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +2606 -677
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +3 -3
- package/dist/modules/workflows/backend/instances/[id]/page.js +532 -421
- package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js +1 -1
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +1 -1
- package/dist/modules/workflows/backend/instances/failure-queue/page.js +211 -0
- package/dist/modules/workflows/backend/instances/failure-queue/page.js.map +7 -0
- package/dist/modules/workflows/backend/instances/failure-queue/page.meta.js +20 -0
- package/dist/modules/workflows/backend/instances/failure-queue/page.meta.js.map +7 -0
- package/dist/modules/workflows/backend/instances/page.js +159 -22
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.meta.js +1 -1
- package/dist/modules/workflows/backend/instances/page.meta.js.map +1 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js +553 -392
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +3 -3
- package/dist/modules/workflows/backend/tasks/page.js +8 -250
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.meta.js +1 -0
- package/dist/modules/workflows/backend/tasks/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/work-inbox/page.js +399 -0
- package/dist/modules/workflows/backend/work-inbox/page.js.map +7 -0
- package/dist/modules/workflows/backend/work-inbox/page.meta.js +19 -0
- package/dist/modules/workflows/backend/work-inbox/page.meta.js.map +7 -0
- package/dist/modules/workflows/cli.js +1 -1
- package/dist/modules/workflows/cli.js.map +2 -2
- package/dist/modules/workflows/commands/tasks.js +81 -0
- package/dist/modules/workflows/commands/tasks.js.map +7 -0
- package/dist/modules/workflows/components/ActivitiesEditor.js +281 -287
- package/dist/modules/workflows/components/ActivitiesEditor.js.map +2 -2
- package/dist/modules/workflows/components/ActivityEditDialog.js +220 -0
- package/dist/modules/workflows/components/ActivityEditDialog.js.map +7 -0
- package/dist/modules/workflows/components/AgentSelector.js +115 -0
- package/dist/modules/workflows/components/AgentSelector.js.map +7 -0
- package/dist/modules/workflows/components/AnnotationEditDialog.js +110 -0
- package/dist/modules/workflows/components/AnnotationEditDialog.js.map +7 -0
- package/dist/modules/workflows/components/BusinessRuleUsagePanel.js +71 -0
- package/dist/modules/workflows/components/BusinessRuleUsagePanel.js.map +7 -0
- package/dist/modules/workflows/components/BusinessRulesSelector.js +151 -93
- package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
- package/dist/modules/workflows/components/ConfigJsonTextarea.js +85 -0
- package/dist/modules/workflows/components/ConfigJsonTextarea.js.map +7 -0
- package/dist/modules/workflows/components/ContextSchemaEditor.js +150 -0
- package/dist/modules/workflows/components/ContextSchemaEditor.js.map +7 -0
- package/dist/modules/workflows/components/DefinitionErrorHandlerField.js +102 -0
- package/dist/modules/workflows/components/DefinitionErrorHandlerField.js.map +7 -0
- package/dist/modules/workflows/components/DefinitionMetadataDrawer.js +377 -0
- package/dist/modules/workflows/components/DefinitionMetadataDrawer.js.map +7 -0
- package/dist/modules/workflows/components/DefinitionMetricsCells.js +132 -0
- package/dist/modules/workflows/components/DefinitionMetricsCells.js.map +7 -0
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +307 -216
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
- package/dist/modules/workflows/components/EdgeEditDialog.js +11 -18
- package/dist/modules/workflows/components/EdgeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js +112 -72
- package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js.map +2 -2
- package/dist/modules/workflows/components/InputDataPanel.js +128 -0
- package/dist/modules/workflows/components/InputDataPanel.js.map +7 -0
- package/dist/modules/workflows/components/InspectorPanel.js +161 -0
- package/dist/modules/workflows/components/InspectorPanel.js.map +7 -0
- package/dist/modules/workflows/components/NodeEditDialog.js +363 -41
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +714 -159
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
- package/dist/modules/workflows/components/StepsEditor.js.map +2 -2
- package/dist/modules/workflows/components/TemplateGalleryDialog.js +148 -0
- package/dist/modules/workflows/components/TemplateGalleryDialog.js.map +7 -0
- package/dist/modules/workflows/components/TransitionsEditor.js +80 -74
- package/dist/modules/workflows/components/TransitionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/TriggersDialog.js +53 -0
- package/dist/modules/workflows/components/TriggersDialog.js.map +7 -0
- package/dist/modules/workflows/components/TriggersEditor.js +331 -0
- package/dist/modules/workflows/components/TriggersEditor.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowAiDraftDialog.js +278 -0
- package/dist/modules/workflows/components/WorkflowAiDraftDialog.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowCodeView.js +173 -0
- package/dist/modules/workflows/components/WorkflowCodeView.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowCommandPalette.js +62 -0
- package/dist/modules/workflows/components/WorkflowCommandPalette.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowCompensationGhostEdge.js +70 -0
- package/dist/modules/workflows/components/WorkflowCompensationGhostEdge.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowDataMappingEdge.js +36 -0
- package/dist/modules/workflows/components/WorkflowDataMappingEdge.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowGraph.js +4 -2
- package/dist/modules/workflows/components/WorkflowGraph.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowGraphImpl.js +324 -86
- package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +3 -3
- package/dist/modules/workflows/components/WorkflowIconPicker.js +109 -0
- package/dist/modules/workflows/components/WorkflowIconPicker.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowLegend.js +45 -29
- package/dist/modules/workflows/components/WorkflowLegend.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowNodeCard.js +221 -22
- package/dist/modules/workflows/components/WorkflowNodeCard.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowRouteChips.js +111 -0
- package/dist/modules/workflows/components/WorkflowRouteChips.js.map +7 -0
- package/dist/modules/workflows/components/WorkflowSelector.js +108 -88
- package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowTransitionEdge.js +61 -11
- package/dist/modules/workflows/components/WorkflowTransitionEdge.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowTransitionLabel.js +15 -5
- package/dist/modules/workflows/components/WorkflowTransitionLabel.js.map +2 -2
- package/dist/modules/workflows/components/fields/ActivityArrayEditor.js +88 -21
- package/dist/modules/workflows/components/fields/ActivityArrayEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/ActivityConfigFields.js +615 -0
- package/dist/modules/workflows/components/fields/ActivityConfigFields.js.map +7 -0
- package/dist/modules/workflows/components/fields/ActivityTestPanel.js +191 -0
- package/dist/modules/workflows/components/fields/ActivityTestPanel.js.map +7 -0
- package/dist/modules/workflows/components/fields/AgentInvokeConfigField.js +488 -0
- package/dist/modules/workflows/components/fields/AgentInvokeConfigField.js.map +7 -0
- package/dist/modules/workflows/components/fields/AgentReviewOnBreachField.js +61 -0
- package/dist/modules/workflows/components/fields/AgentReviewOnBreachField.js.map +7 -0
- package/dist/modules/workflows/components/fields/BranchingRoutesEditor.js +227 -0
- package/dist/modules/workflows/components/fields/BranchingRoutesEditor.js.map +7 -0
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +37 -4
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/CommandPicker.js +111 -0
- package/dist/modules/workflows/components/fields/CommandPicker.js.map +7 -0
- package/dist/modules/workflows/components/fields/EndpointPicker.js +235 -0
- package/dist/modules/workflows/components/fields/EndpointPicker.js.map +7 -0
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/FunctionPicker.js +55 -0
- package/dist/modules/workflows/components/fields/FunctionPicker.js.map +7 -0
- package/dist/modules/workflows/components/fields/MappingArrayEditor.js +38 -15
- package/dist/modules/workflows/components/fields/MappingArrayEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/PortFieldArrayEditor.js +206 -0
- package/dist/modules/workflows/components/fields/PortFieldArrayEditor.js.map +7 -0
- package/dist/modules/workflows/components/fields/RolesMultiSelect.js +53 -0
- package/dist/modules/workflows/components/fields/RolesMultiSelect.js.map +7 -0
- package/dist/modules/workflows/components/fields/RouteOrderEditor.js +130 -0
- package/dist/modules/workflows/components/fields/RouteOrderEditor.js.map +7 -0
- package/dist/modules/workflows/components/fields/SchemaBuilderDialog.js +104 -0
- package/dist/modules/workflows/components/fields/SchemaBuilderDialog.js.map +7 -0
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +2 -2
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/TaskAssignmentField.js +210 -0
- package/dist/modules/workflows/components/fields/TaskAssignmentField.js.map +7 -0
- package/dist/modules/workflows/components/fields/TaskDeadlineFields.js +126 -0
- package/dist/modules/workflows/components/fields/TaskDeadlineFields.js.map +7 -0
- package/dist/modules/workflows/components/fields/TaskDecisionsField.js +218 -0
- package/dist/modules/workflows/components/fields/TaskDecisionsField.js.map +7 -0
- package/dist/modules/workflows/components/fields/TaskEntityBindingsField.js +114 -0
- package/dist/modules/workflows/components/fields/TaskEntityBindingsField.js.map +7 -0
- package/dist/modules/workflows/components/fields/TemplateTextControl.js +64 -0
- package/dist/modules/workflows/components/fields/TemplateTextControl.js.map +7 -0
- package/dist/modules/workflows/components/fields/VariablePickerButton.js +121 -0
- package/dist/modules/workflows/components/fields/VariablePickerButton.js.map +7 -0
- package/dist/modules/workflows/components/fields/ledgerDropTarget.js +35 -0
- package/dist/modules/workflows/components/fields/ledgerDropTarget.js.map +7 -0
- package/dist/modules/workflows/components/fields/useActivityTypeOptions.js +16 -0
- package/dist/modules/workflows/components/fields/useActivityTypeOptions.js.map +7 -0
- package/dist/modules/workflows/components/formConfig.js +39 -10
- package/dist/modules/workflows/components/formConfig.js.map +2 -2
- package/dist/modules/workflows/components/mobile/MobileDefinitionDetail.js.map +2 -2
- package/dist/modules/workflows/components/mobile/MobileMetadataSheet.js.map +2 -2
- package/dist/modules/workflows/components/mobile/MobileTaskForm.js +29 -2
- package/dist/modules/workflows/components/mobile/MobileTaskForm.js.map +2 -2
- package/dist/modules/workflows/components/mobile/MobileVisualEditor.js +64 -65
- package/dist/modules/workflows/components/mobile/MobileVisualEditor.js.map +2 -2
- package/dist/modules/workflows/components/nodes/AnnotationGroupNode.js +64 -0
- package/dist/modules/workflows/components/nodes/AnnotationGroupNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/AutomatedNode.js +24 -16
- package/dist/modules/workflows/components/nodes/AutomatedNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/EndNode.js +13 -12
- package/dist/modules/workflows/components/nodes/EndNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/ErrorOutputHandle.js +29 -0
- package/dist/modules/workflows/components/nodes/ErrorOutputHandle.js.map +7 -0
- package/dist/modules/workflows/components/nodes/IfElseNode.js +51 -0
- package/dist/modules/workflows/components/nodes/IfElseNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/InvokeAgentNode.js +122 -0
- package/dist/modules/workflows/components/nodes/InvokeAgentNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/NodeOutcomeRows.js +100 -0
- package/dist/modules/workflows/components/nodes/NodeOutcomeRows.js.map +7 -0
- package/dist/modules/workflows/components/nodes/ParallelForkNode.js +18 -14
- package/dist/modules/workflows/components/nodes/ParallelForkNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/ParallelJoinNode.js +18 -14
- package/dist/modules/workflows/components/nodes/ParallelJoinNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/StartNode.js +66 -15
- package/dist/modules/workflows/components/nodes/StartNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/StickyNoteNode.js +54 -0
- package/dist/modules/workflows/components/nodes/StickyNoteNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/SubWorkflowNode.js +107 -41
- package/dist/modules/workflows/components/nodes/SubWorkflowNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/SwitchNode.js +51 -0
- package/dist/modules/workflows/components/nodes/SwitchNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/TriggerCap.js +65 -0
- package/dist/modules/workflows/components/nodes/TriggerCap.js.map +7 -0
- package/dist/modules/workflows/components/nodes/TriggerNode.js +111 -0
- package/dist/modules/workflows/components/nodes/TriggerNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/UserTaskNode.js +43 -17
- package/dist/modules/workflows/components/nodes/UserTaskNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/WaitForConditionNode.js +53 -0
- package/dist/modules/workflows/components/nodes/WaitForConditionNode.js.map +7 -0
- package/dist/modules/workflows/components/nodes/WaitForSignalNode.js +21 -15
- package/dist/modules/workflows/components/nodes/WaitForSignalNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/WaitForTimerNode.js +21 -15
- package/dist/modules/workflows/components/nodes/WaitForTimerNode.js.map +2 -2
- package/dist/modules/workflows/components/nodes/index.js +14 -0
- package/dist/modules/workflows/components/nodes/index.js.map +2 -2
- package/dist/modules/workflows/components/portal/PortalTaskForm.js +196 -0
- package/dist/modules/workflows/components/portal/PortalTaskForm.js.map +7 -0
- package/dist/modules/workflows/components/run/AgentActivityPanel.js +22 -0
- package/dist/modules/workflows/components/run/AgentActivityPanel.js.map +7 -0
- package/dist/modules/workflows/components/run/RerunStepDialog.js +106 -0
- package/dist/modules/workflows/components/run/RerunStepDialog.js.map +7 -0
- package/dist/modules/workflows/components/run/RunEventBadge.js +30 -0
- package/dist/modules/workflows/components/run/RunEventBadge.js.map +7 -0
- package/dist/modules/workflows/components/run/RunGantt.js +130 -0
- package/dist/modules/workflows/components/run/RunGantt.js.map +7 -0
- package/dist/modules/workflows/components/run/RunStatusBadge.js +82 -0
- package/dist/modules/workflows/components/run/RunStatusBadge.js.map +7 -0
- package/dist/modules/workflows/components/run/RunStepInspector.js +116 -0
- package/dist/modules/workflows/components/run/RunStepInspector.js.map +7 -0
- package/dist/modules/workflows/components/run/WouldDoReport.js +52 -0
- package/dist/modules/workflows/components/run/WouldDoReport.js.map +7 -0
- package/dist/modules/workflows/components/run/useAgentLabels.js +28 -0
- package/dist/modules/workflows/components/run/useAgentLabels.js.map +7 -0
- package/dist/modules/workflows/components/run/useLastRunOverlay.js +89 -0
- package/dist/modules/workflows/components/run/useLastRunOverlay.js.map +7 -0
- package/dist/modules/workflows/components/run/useLiveAgentActions.js +41 -0
- package/dist/modules/workflows/components/run/useLiveAgentActions.js.map +7 -0
- package/dist/modules/workflows/components/run/useLiveRunUpdates.js +57 -0
- package/dist/modules/workflows/components/run/useLiveRunUpdates.js.map +7 -0
- package/dist/modules/workflows/components/settings/CommandSettingsPageClient.js +156 -0
- package/dist/modules/workflows/components/settings/CommandSettingsPageClient.js.map +7 -0
- package/dist/modules/workflows/components/work-inbox/EntityContextPanel.js +72 -0
- package/dist/modules/workflows/components/work-inbox/EntityContextPanel.js.map +7 -0
- package/dist/modules/workflows/components/work-inbox/ReassignTaskDialog.js +156 -0
- package/dist/modules/workflows/components/work-inbox/ReassignTaskDialog.js.map +7 -0
- package/dist/modules/workflows/components/work-inbox/StatusChip.js +46 -0
- package/dist/modules/workflows/components/work-inbox/StatusChip.js.map +7 -0
- package/dist/modules/workflows/components/work-inbox/TaskActionNotice.js +53 -0
- package/dist/modules/workflows/components/work-inbox/TaskActionNotice.js.map +7 -0
- package/dist/modules/workflows/components/work-inbox/TaskFormFields.js +261 -0
- package/dist/modules/workflows/components/work-inbox/TaskFormFields.js.map +7 -0
- package/dist/modules/workflows/components/work-inbox/WorkInboxEmptyState.js +27 -0
- package/dist/modules/workflows/components/work-inbox/WorkInboxEmptyState.js.map +7 -0
- package/dist/modules/workflows/data/activity-config-schemas.js +191 -0
- package/dist/modules/workflows/data/activity-config-schemas.js.map +7 -0
- package/dist/modules/workflows/data/activity-config-warnings.js +42 -0
- package/dist/modules/workflows/data/activity-config-warnings.js.map +7 -0
- package/dist/modules/workflows/data/branching-route-warnings.js +65 -0
- package/dist/modules/workflows/data/branching-route-warnings.js.map +7 -0
- package/dist/modules/workflows/data/entities.js +144 -4
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/metrics-validators.js +35 -0
- package/dist/modules/workflows/data/metrics-validators.js.map +7 -0
- package/dist/modules/workflows/data/task-primitives.js +14 -0
- package/dist/modules/workflows/data/task-primitives.js.map +7 -0
- package/dist/modules/workflows/data/validators.js +504 -61
- package/dist/modules/workflows/data/validators.js.map +3 -3
- package/dist/modules/workflows/di.js +16 -1
- package/dist/modules/workflows/di.js.map +2 -2
- package/dist/modules/workflows/events.js +66 -8
- package/dist/modules/workflows/events.js.map +2 -2
- package/dist/modules/workflows/examples/oze-residential-install-60-nodes.json +1545 -0
- package/dist/modules/workflows/examples/sales-pipeline-definition.json +35 -35
- package/dist/modules/workflows/examples/templates/lead-to-install.json +160 -0
- package/dist/modules/workflows/examples/templates/order-approval.json +230 -0
- package/dist/modules/workflows/examples/templates/task-escalation.json +110 -0
- package/dist/modules/workflows/examples/templates/webhook-integration.json +113 -0
- package/dist/modules/workflows/extension-points.js +1 -1
- package/dist/modules/workflows/extension-points.js.map +2 -2
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js +144 -0
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.js.map +7 -0
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.meta.js +12 -0
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.meta.js.map +7 -0
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.js +114 -0
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.js.map +7 -0
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.meta.js +18 -0
- package/dist/modules/workflows/frontend/[orgSlug]/portal/tasks/page.meta.js.map +7 -0
- package/dist/modules/workflows/lib/activity-executor.js +505 -137
- package/dist/modules/workflows/lib/activity-executor.js.map +3 -3
- package/dist/modules/workflows/lib/activity-queue-types.js +3 -1
- package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
- package/dist/modules/workflows/lib/activity-registry-bootstrap.js +2 -0
- package/dist/modules/workflows/lib/activity-registry-bootstrap.js.map +7 -0
- package/dist/modules/workflows/lib/activity-registry.js +27 -0
- package/dist/modules/workflows/lib/activity-registry.js.map +7 -0
- package/dist/modules/workflows/lib/activity-types.js +291 -0
- package/dist/modules/workflows/lib/activity-types.js.map +7 -0
- package/dist/modules/workflows/lib/activity-worker-handler.js +456 -32
- package/dist/modules/workflows/lib/activity-worker-handler.js.map +3 -3
- package/dist/modules/workflows/lib/advanced-config.js +31 -0
- package/dist/modules/workflows/lib/advanced-config.js.map +7 -0
- package/dist/modules/workflows/lib/agent-disposition-task.js +198 -0
- package/dist/modules/workflows/lib/agent-disposition-task.js.map +7 -0
- package/dist/modules/workflows/lib/agent-outcome-paths.js +82 -0
- package/dist/modules/workflows/lib/agent-outcome-paths.js.map +7 -0
- package/dist/modules/workflows/lib/agent-result-mapping.js +54 -0
- package/dist/modules/workflows/lib/agent-result-mapping.js.map +7 -0
- package/dist/modules/workflows/lib/agent-review-inspector.js +61 -0
- package/dist/modules/workflows/lib/agent-review-inspector.js.map +7 -0
- package/dist/modules/workflows/lib/agent-review.js +66 -0
- package/dist/modules/workflows/lib/agent-review.js.map +7 -0
- package/dist/modules/workflows/lib/ai-authoring.js +155 -0
- package/dist/modules/workflows/lib/ai-authoring.js.map +7 -0
- package/dist/modules/workflows/lib/ai-draft-runner.js +43 -0
- package/dist/modules/workflows/lib/ai-draft-runner.js.map +7 -0
- package/dist/modules/workflows/lib/annotation-events.js +10 -0
- package/dist/modules/workflows/lib/annotation-events.js.map +7 -0
- package/dist/modules/workflows/lib/branching-routes.js +182 -0
- package/dist/modules/workflows/lib/branching-routes.js.map +7 -0
- package/dist/modules/workflows/lib/breach-routing.js +50 -0
- package/dist/modules/workflows/lib/breach-routing.js.map +7 -0
- package/dist/modules/workflows/lib/bulk-replay.js +101 -0
- package/dist/modules/workflows/lib/bulk-replay.js.map +7 -0
- package/dist/modules/workflows/lib/business-rule-usage.js +91 -0
- package/dist/modules/workflows/lib/business-rule-usage.js.map +7 -0
- package/dist/modules/workflows/lib/caller-graph.js +53 -0
- package/dist/modules/workflows/lib/caller-graph.js.map +7 -0
- package/dist/modules/workflows/lib/code-view-apply.js +86 -0
- package/dist/modules/workflows/lib/code-view-apply.js.map +7 -0
- package/dist/modules/workflows/lib/collect-validation-issues.js +164 -0
- package/dist/modules/workflows/lib/collect-validation-issues.js.map +7 -0
- package/dist/modules/workflows/lib/compensation-ghosts.js +72 -0
- package/dist/modules/workflows/lib/compensation-ghosts.js.map +7 -0
- package/dist/modules/workflows/lib/component-guard.js +7 -0
- package/dist/modules/workflows/lib/component-guard.js.map +7 -0
- package/dist/modules/workflows/lib/condition-handler.js +443 -0
- package/dist/modules/workflows/lib/condition-handler.js.map +7 -0
- package/dist/modules/workflows/lib/context-ledger.js +448 -0
- package/dist/modules/workflows/lib/context-ledger.js.map +7 -0
- package/dist/modules/workflows/lib/crud-form-dialogs-flag.js +8 -0
- package/dist/modules/workflows/lib/crud-form-dialogs-flag.js.map +7 -0
- package/dist/modules/workflows/lib/data-edge-mapping.js +63 -0
- package/dist/modules/workflows/lib/data-edge-mapping.js.map +7 -0
- package/dist/modules/workflows/lib/definition-context-schema.js +56 -0
- package/dist/modules/workflows/lib/definition-context-schema.js.map +7 -0
- package/dist/modules/workflows/lib/definition-edit-safety.js +123 -0
- package/dist/modules/workflows/lib/definition-edit-safety.js.map +7 -0
- package/dist/modules/workflows/lib/definition-error-body.js +33 -0
- package/dist/modules/workflows/lib/definition-error-body.js.map +7 -0
- package/dist/modules/workflows/lib/definition-evaluation.js +79 -0
- package/dist/modules/workflows/lib/definition-evaluation.js.map +7 -0
- package/dist/modules/workflows/lib/definition-grant.js +90 -0
- package/dist/modules/workflows/lib/definition-grant.js.map +7 -0
- package/dist/modules/workflows/lib/definition-json-locations.js +139 -0
- package/dist/modules/workflows/lib/definition-json-locations.js.map +7 -0
- package/dist/modules/workflows/lib/definition-payload.js +31 -0
- package/dist/modules/workflows/lib/definition-payload.js.map +7 -0
- package/dist/modules/workflows/lib/draft-restore.js +49 -0
- package/dist/modules/workflows/lib/draft-restore.js.map +7 -0
- package/dist/modules/workflows/lib/dry-run.js +106 -0
- package/dist/modules/workflows/lib/dry-run.js.map +7 -0
- package/dist/modules/workflows/lib/duration.js +66 -17
- package/dist/modules/workflows/lib/duration.js.map +2 -2
- package/dist/modules/workflows/lib/edge-reattachment.js +79 -0
- package/dist/modules/workflows/lib/edge-reattachment.js.map +7 -0
- package/dist/modules/workflows/lib/edgeFormTransforms.js +7 -11
- package/dist/modules/workflows/lib/edgeFormTransforms.js.map +2 -2
- package/dist/modules/workflows/lib/editor-annotations.js +195 -0
- package/dist/modules/workflows/lib/editor-annotations.js.map +7 -0
- package/dist/modules/workflows/lib/editor-commands.js +103 -0
- package/dist/modules/workflows/lib/editor-commands.js.map +7 -0
- package/dist/modules/workflows/lib/editor-history.js +51 -0
- package/dist/modules/workflows/lib/editor-history.js.map +7 -0
- package/dist/modules/workflows/lib/endpoint-catalog.js +181 -0
- package/dist/modules/workflows/lib/endpoint-catalog.js.map +7 -0
- package/dist/modules/workflows/lib/endpoint-path.js +90 -0
- package/dist/modules/workflows/lib/endpoint-path.js.map +7 -0
- package/dist/modules/workflows/lib/engine-version.js +42 -0
- package/dist/modules/workflows/lib/engine-version.js.map +7 -0
- package/dist/modules/workflows/lib/error-handler.js +132 -0
- package/dist/modules/workflows/lib/error-handler.js.map +7 -0
- package/dist/modules/workflows/lib/error-routing.js +104 -0
- package/dist/modules/workflows/lib/error-routing.js.map +7 -0
- package/dist/modules/workflows/lib/event-logger.js +23 -0
- package/dist/modules/workflows/lib/event-logger.js.map +2 -2
- package/dist/modules/workflows/lib/expression-refs.js +168 -0
- package/dist/modules/workflows/lib/expression-refs.js.map +7 -0
- package/dist/modules/workflows/lib/failure-grouping.js +62 -0
- package/dist/modules/workflows/lib/failure-grouping.js.map +7 -0
- package/dist/modules/workflows/lib/find-definition.js +1 -0
- package/dist/modules/workflows/lib/find-definition.js.map +2 -2
- package/dist/modules/workflows/lib/flow-logic-warnings.js +338 -0
- package/dist/modules/workflows/lib/flow-logic-warnings.js.map +7 -0
- package/dist/modules/workflows/lib/graph-utils.js +328 -77
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/icon-search.js +32 -0
- package/dist/modules/workflows/lib/icon-search.js.map +7 -0
- package/dist/modules/workflows/lib/insert-at-cursor.js +26 -0
- package/dist/modules/workflows/lib/insert-at-cursor.js.map +7 -0
- package/dist/modules/workflows/lib/instance-date-filter.js +28 -0
- package/dist/modules/workflows/lib/instance-date-filter.js.map +7 -0
- package/dist/modules/workflows/lib/interpolation-pipeline.js +271 -0
- package/dist/modules/workflows/lib/interpolation-pipeline.js.map +7 -0
- package/dist/modules/workflows/lib/ledger-drag.js +28 -0
- package/dist/modules/workflows/lib/ledger-drag.js.map +7 -0
- package/dist/modules/workflows/lib/ledger-entry-display.js +66 -0
- package/dist/modules/workflows/lib/ledger-entry-display.js.map +7 -0
- package/dist/modules/workflows/lib/ledger-schema-flatten.js +82 -0
- package/dist/modules/workflows/lib/ledger-schema-flatten.js.map +7 -0
- package/dist/modules/workflows/lib/metrics/definition-metrics.js +110 -0
- package/dist/modules/workflows/lib/metrics/definition-metrics.js.map +7 -0
- package/dist/modules/workflows/lib/metrics/metrics-display.js +26 -0
- package/dist/modules/workflows/lib/metrics/metrics-display.js.map +7 -0
- package/dist/modules/workflows/lib/metrics/rollup-schedule.js +7 -0
- package/dist/modules/workflows/lib/metrics/rollup-schedule.js.map +7 -0
- package/dist/modules/workflows/lib/metrics/rollup-service.js +160 -0
- package/dist/modules/workflows/lib/metrics/rollup-service.js.map +7 -0
- package/dist/modules/workflows/lib/node-config-summary.js +128 -0
- package/dist/modules/workflows/lib/node-config-summary.js.map +7 -0
- package/dist/modules/workflows/lib/node-geometry.js +53 -0
- package/dist/modules/workflows/lib/node-geometry.js.map +7 -0
- package/dist/modules/workflows/lib/node-nudge.js +44 -0
- package/dist/modules/workflows/lib/node-nudge.js.map +7 -0
- package/dist/modules/workflows/lib/node-outcome-rows.js +88 -0
- package/dist/modules/workflows/lib/node-outcome-rows.js.map +7 -0
- package/dist/modules/workflows/lib/node-placement.js +55 -0
- package/dist/modules/workflows/lib/node-placement.js.map +7 -0
- package/dist/modules/workflows/lib/node-type-icons.js +54 -13
- package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
- package/dist/modules/workflows/lib/nodeFormTransforms.js +329 -19
- package/dist/modules/workflows/lib/nodeFormTransforms.js.map +2 -2
- package/dist/modules/workflows/lib/outcome-routing.js +158 -0
- package/dist/modules/workflows/lib/outcome-routing.js.map +7 -0
- package/dist/modules/workflows/lib/owned-definition.js +107 -0
- package/dist/modules/workflows/lib/owned-definition.js.map +7 -0
- package/dist/modules/workflows/lib/owned-node-changes.js +10 -0
- package/dist/modules/workflows/lib/owned-node-changes.js.map +7 -0
- package/dist/modules/workflows/lib/palette-drag.js +36 -0
- package/dist/modules/workflows/lib/palette-drag.js.map +7 -0
- package/dist/modules/workflows/lib/palette-drop.js +45 -0
- package/dist/modules/workflows/lib/palette-drop.js.map +7 -0
- package/dist/modules/workflows/lib/parallel-handler.js +57 -2
- package/dist/modules/workflows/lib/parallel-handler.js.map +2 -2
- package/dist/modules/workflows/lib/port-contract.js +54 -0
- package/dist/modules/workflows/lib/port-contract.js.map +7 -0
- package/dist/modules/workflows/lib/portal-task-access.js +89 -0
- package/dist/modules/workflows/lib/portal-task-access.js.map +7 -0
- package/dist/modules/workflows/lib/rerun-from-step.js +65 -0
- package/dist/modules/workflows/lib/rerun-from-step.js.map +7 -0
- package/dist/modules/workflows/lib/route-chip-events.js +23 -0
- package/dist/modules/workflows/lib/route-chip-events.js.map +7 -0
- package/dist/modules/workflows/lib/route-chips.js +91 -0
- package/dist/modules/workflows/lib/route-chips.js.map +7 -0
- package/dist/modules/workflows/lib/route-edge.js +17 -0
- package/dist/modules/workflows/lib/route-edge.js.map +7 -0
- package/dist/modules/workflows/lib/route-kinds.js +67 -0
- package/dist/modules/workflows/lib/route-kinds.js.map +7 -0
- package/dist/modules/workflows/lib/route-priority.js +104 -0
- package/dist/modules/workflows/lib/route-priority.js.map +7 -0
- package/dist/modules/workflows/lib/run-duration.js +44 -0
- package/dist/modules/workflows/lib/run-duration.js.map +7 -0
- package/dist/modules/workflows/lib/run-event-tone.js +25 -0
- package/dist/modules/workflows/lib/run-event-tone.js.map +7 -0
- package/dist/modules/workflows/lib/run-execution.js +305 -0
- package/dist/modules/workflows/lib/run-execution.js.map +7 -0
- package/dist/modules/workflows/lib/run-gantt.js +180 -0
- package/dist/modules/workflows/lib/run-gantt.js.map +7 -0
- package/dist/modules/workflows/lib/run-outcome-evidence.js +33 -0
- package/dist/modules/workflows/lib/run-outcome-evidence.js.map +7 -0
- package/dist/modules/workflows/lib/run-outcome.js +48 -0
- package/dist/modules/workflows/lib/run-outcome.js.map +7 -0
- package/dist/modules/workflows/lib/sample-resolver.js +71 -0
- package/dist/modules/workflows/lib/sample-resolver.js.map +7 -0
- package/dist/modules/workflows/lib/seeds.js +1 -1
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/server-output-contract.js +65 -0
- package/dist/modules/workflows/lib/server-output-contract.js.map +7 -0
- package/dist/modules/workflows/lib/set-variable.js +47 -0
- package/dist/modules/workflows/lib/set-variable.js.map +7 -0
- package/dist/modules/workflows/lib/signal-handler.js +63 -4
- package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
- package/dist/modules/workflows/lib/start-fixtures.js +42 -0
- package/dist/modules/workflows/lib/start-fixtures.js.map +7 -0
- package/dist/modules/workflows/lib/status-colors.js +153 -22
- package/dist/modules/workflows/lib/status-colors.js.map +2 -2
- package/dist/modules/workflows/lib/step-handler.js +529 -53
- package/dist/modules/workflows/lib/step-handler.js.map +3 -3
- package/dist/modules/workflows/lib/step-presentation.js +147 -0
- package/dist/modules/workflows/lib/step-presentation.js.map +7 -0
- package/dist/modules/workflows/lib/step-through.js +26 -0
- package/dist/modules/workflows/lib/step-through.js.map +7 -0
- package/dist/modules/workflows/lib/step-type-conversion.js +167 -0
- package/dist/modules/workflows/lib/step-type-conversion.js.map +7 -0
- package/dist/modules/workflows/lib/subgraph-clipboard.js +114 -0
- package/dist/modules/workflows/lib/subgraph-clipboard.js.map +7 -0
- package/dist/modules/workflows/lib/task-decision-context.js +38 -0
- package/dist/modules/workflows/lib/task-decision-context.js.map +7 -0
- package/dist/modules/workflows/lib/task-decisions.js +49 -0
- package/dist/modules/workflows/lib/task-decisions.js.map +7 -0
- package/dist/modules/workflows/lib/task-entity-access.js +62 -0
- package/dist/modules/workflows/lib/task-entity-access.js.map +7 -0
- package/dist/modules/workflows/lib/task-entity-aliases.js +39 -0
- package/dist/modules/workflows/lib/task-entity-aliases.js.map +7 -0
- package/dist/modules/workflows/lib/task-entity-types.js +36 -0
- package/dist/modules/workflows/lib/task-entity-types.js.map +7 -0
- package/dist/modules/workflows/lib/task-form-registry.js +33 -0
- package/dist/modules/workflows/lib/task-form-registry.js.map +7 -0
- package/dist/modules/workflows/lib/task-form-schema.js +75 -0
- package/dist/modules/workflows/lib/task-form-schema.js.map +7 -0
- package/dist/modules/workflows/lib/task-handler.js +251 -32
- package/dist/modules/workflows/lib/task-handler.js.map +2 -2
- package/dist/modules/workflows/lib/task-inspector-config.js +182 -0
- package/dist/modules/workflows/lib/task-inspector-config.js.map +7 -0
- package/dist/modules/workflows/lib/task-list-query.js +19 -0
- package/dist/modules/workflows/lib/task-list-query.js.map +7 -0
- package/dist/modules/workflows/lib/task-notifications.js +119 -0
- package/dist/modules/workflows/lib/task-notifications.js.map +7 -0
- package/dist/modules/workflows/lib/task-permission-settings.js +43 -0
- package/dist/modules/workflows/lib/task-permission-settings.js.map +7 -0
- package/dist/modules/workflows/lib/task-presets.js +35 -0
- package/dist/modules/workflows/lib/task-presets.js.map +7 -0
- package/dist/modules/workflows/lib/task-quick-action.js +45 -0
- package/dist/modules/workflows/lib/task-quick-action.js.map +7 -0
- package/dist/modules/workflows/lib/task-resolution.js +120 -0
- package/dist/modules/workflows/lib/task-resolution.js.map +7 -0
- package/dist/modules/workflows/lib/task-sla.js +357 -0
- package/dist/modules/workflows/lib/task-sla.js.map +7 -0
- package/dist/modules/workflows/lib/task-visibility-request.js +266 -0
- package/dist/modules/workflows/lib/task-visibility-request.js.map +7 -0
- package/dist/modules/workflows/lib/task-visibility.js +194 -0
- package/dist/modules/workflows/lib/task-visibility.js.map +7 -0
- package/dist/modules/workflows/lib/timer-handler.js +3 -1
- package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +148 -20
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/dist/modules/workflows/lib/trigger-node.js +121 -0
- package/dist/modules/workflows/lib/trigger-node.js.map +7 -0
- package/dist/modules/workflows/lib/visual-editor-navigation.js +14 -0
- package/dist/modules/workflows/lib/visual-editor-navigation.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/empty-state.js +52 -0
- package/dist/modules/workflows/lib/work-inbox/empty-state.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/entity-links.js +63 -0
- package/dist/modules/workflows/lib/work-inbox/entity-links.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/navigation.js +11 -0
- package/dist/modules/workflows/lib/work-inbox/navigation.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/presentation.js +90 -0
- package/dist/modules/workflows/lib/work-inbox/presentation.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/provider.js +118 -0
- package/dist/modules/workflows/lib/work-inbox/provider.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/query.js +70 -0
- package/dist/modules/workflows/lib/work-inbox/query.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/service.js +56 -0
- package/dist/modules/workflows/lib/work-inbox/service.js.map +7 -0
- package/dist/modules/workflows/lib/work-inbox/user-task-source.js +149 -0
- package/dist/modules/workflows/lib/work-inbox/user-task-source.js.map +7 -0
- package/dist/modules/workflows/lib/workflow-command-enablement.js +57 -0
- package/dist/modules/workflows/lib/workflow-command-enablement.js.map +7 -0
- package/dist/modules/workflows/lib/workflow-command-settings.js +54 -0
- package/dist/modules/workflows/lib/workflow-command-settings.js.map +7 -0
- package/dist/modules/workflows/lib/workflow-executor.js +658 -6
- package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
- package/dist/modules/workflows/lib/workflow-function-registry.js +40 -0
- package/dist/modules/workflows/lib/workflow-function-registry.js.map +7 -0
- package/dist/modules/workflows/lib/workflow-safe-commands.js +11 -1
- package/dist/modules/workflows/lib/workflow-safe-commands.js.map +2 -2
- package/dist/modules/workflows/lib/workflow-templates.js +69 -0
- package/dist/modules/workflows/lib/workflow-templates.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260626214855_workflows.js +15 -0
- package/dist/modules/workflows/migrations/Migration20260626214855_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260626222424_workflows.js +17 -0
- package/dist/modules/workflows/migrations/Migration20260626222424_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260727074335_workflows.js +15 -0
- package/dist/modules/workflows/migrations/Migration20260727074335_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260728104038_workflows.js +13 -0
- package/dist/modules/workflows/migrations/Migration20260728104038_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260728163001_workflows.js +15 -0
- package/dist/modules/workflows/migrations/Migration20260728163001_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260729061736_workflows.js +13 -0
- package/dist/modules/workflows/migrations/Migration20260729061736_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260729192652_workflows.js +12 -0
- package/dist/modules/workflows/migrations/Migration20260729192652_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260730085000_workflows.js +13 -0
- package/dist/modules/workflows/migrations/Migration20260730085000_workflows.js.map +7 -0
- package/dist/modules/workflows/migrations/Migration20260730092706_workflows.js +13 -0
- package/dist/modules/workflows/migrations/Migration20260730092706_workflows.js.map +7 -0
- package/dist/modules/workflows/notifications.js +38 -10
- package/dist/modules/workflows/notifications.js.map +2 -2
- package/dist/modules/workflows/setup.js +81 -1
- package/dist/modules/workflows/setup.js.map +2 -2
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +19 -27
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +2 -2
- package/dist/modules/workflows/subscribers/task-deadline-breached-notification.js +24 -0
- package/dist/modules/workflows/subscribers/task-deadline-breached-notification.js.map +7 -0
- package/dist/modules/workflows/subscribers/task-reminder-notification.js +24 -0
- package/dist/modules/workflows/subscribers/task-reminder-notification.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/pending-work/widget.client.js +73 -0
- package/dist/modules/workflows/widgets/injection/pending-work/widget.client.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/pending-work/widget.js +17 -0
- package/dist/modules/workflows/widgets/injection/pending-work/widget.js.map +7 -0
- package/dist/modules/workflows/widgets/injection-table.js +26 -0
- package/dist/modules/workflows/widgets/injection-table.js.map +2 -2
- package/dist/modules/workflows/workers/workflow-activities.worker.js +61 -39
- package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
- package/dist/modules/workflows/workers/workflow-definition-metric-rollup.worker.js +40 -0
- package/dist/modules/workflows/workers/workflow-definition-metric-rollup.worker.js.map +7 -0
- package/dist/modules/workflows/workers/workflow-instance-bulk-replay.js +43 -0
- package/dist/modules/workflows/workers/workflow-instance-bulk-replay.js.map +7 -0
- package/dist/modules/workflows/workers/workflow-invoke-agent.worker.js +30 -0
- package/dist/modules/workflows/workers/workflow-invoke-agent.worker.js.map +7 -0
- package/generated/entities/action_log/index.ts +1 -0
- package/generated/entities/user/index.ts +1 -0
- package/generated/entities/user_task/index.ts +7 -0
- package/generated/entities/workflow_definition/index.ts +3 -0
- package/generated/entities/workflow_definition_draft/index.ts +11 -0
- package/generated/entities/workflow_definition_metric_rollup/index.ts +10 -0
- package/generated/entities/workflow_instance/index.ts +2 -0
- package/generated/entities.ids.generated.ts +4 -1
- package/generated/entity-fields-registry.ts +39 -0
- package/jest.setup.ts +13 -0
- package/package.json +8 -7
- package/src/helpers/integration/workflowsFixtures.ts +765 -5
- package/src/helpers/integration/workflowsUi.ts +318 -0
- package/src/modules/attachments/lib/createFromBuffer.ts +120 -0
- package/src/modules/audit_logs/data/entities.ts +12 -0
- package/src/modules/audit_logs/data/validators.ts +1 -0
- package/src/modules/audit_logs/lib/projections.ts +5 -1
- package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +26 -0
- package/src/modules/audit_logs/migrations/Migration20260625120000.ts +15 -0
- package/src/modules/audit_logs/services/actionLogService.ts +3 -0
- package/src/modules/auth/data/entities.ts +21 -0
- package/src/modules/auth/i18n/de.json +31 -0
- package/src/modules/auth/i18n/en.json +31 -0
- package/src/modules/auth/i18n/es.json +31 -0
- package/src/modules/auth/i18n/ko.json +31 -0
- package/src/modules/auth/i18n/pl.json +31 -0
- package/src/modules/auth/lib/executionPrincipal.ts +235 -0
- package/src/modules/auth/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/auth/migrations/Migration20260625050000.ts +21 -0
- package/src/modules/business_rules/components/InlineRuleEditor.tsx +231 -0
- package/src/modules/business_rules/data/validators.ts +6 -0
- package/src/modules/business_rules/i18n/de.json +4 -0
- package/src/modules/business_rules/i18n/en.json +4 -0
- package/src/modules/business_rules/i18n/es.json +4 -0
- package/src/modules/business_rules/i18n/ko.json +4 -0
- package/src/modules/business_rules/i18n/pl.json +4 -0
- package/src/modules/business_rules/lib/rule-engine.ts +15 -1
- package/src/modules/catalog/commands/products.ts +12 -0
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/ko.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/catalog/workflows.ts +35 -0
- package/src/modules/customer_accounts/AGENTS.md +11 -0
- package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +2 -0
- package/src/modules/customer_accounts/cli.ts +96 -0
- package/src/modules/customer_accounts/i18n/de.json +5 -0
- package/src/modules/customer_accounts/i18n/en.json +5 -0
- package/src/modules/customer_accounts/i18n/es.json +5 -0
- package/src/modules/customer_accounts/i18n/ko.json +5 -0
- package/src/modules/customer_accounts/i18n/pl.json +5 -0
- package/src/modules/customer_accounts/lib/customerRoleAclSync.ts +92 -0
- package/src/modules/customer_accounts/setup.ts +15 -3
- package/src/modules/customers/commands/deals.ts +5 -0
- package/src/modules/customers/components/detail/ChangelogEntryRow.tsx +4 -2
- package/src/modules/customers/components/detail/utils.ts +2 -0
- package/src/modules/customers/events.ts +21 -3
- package/src/modules/customers/i18n/de.json +4 -0
- package/src/modules/customers/i18n/en.json +4 -0
- package/src/modules/customers/i18n/es.json +4 -0
- package/src/modules/customers/i18n/ko.json +4 -0
- package/src/modules/customers/i18n/pl.json +4 -0
- package/src/modules/customers/lib/link-workflow-task-handler.ts +136 -0
- package/src/modules/customers/lib/todoCompatibility.ts +4 -1
- package/src/modules/customers/lib/workflowTaskLink.ts +23 -0
- package/src/modules/customers/subscribers/link-workflow-task.ts +19 -0
- package/src/modules/customers/workflows.ts +57 -0
- package/src/modules/entities/api/records.ts +18 -62
- package/src/modules/entities/lib/entityClassification.ts +102 -0
- package/src/modules/sales/commands/documents.ts +46 -0
- package/src/modules/sales/events.ts +20 -2
- package/src/modules/sales/i18n/de.json +2 -1
- package/src/modules/sales/i18n/en.json +2 -1
- package/src/modules/sales/i18n/es.json +2 -1
- package/src/modules/sales/i18n/ko.json +2 -1
- package/src/modules/sales/i18n/pl.json +2 -1
- package/src/modules/sales/workflows.ts +12 -1
- package/src/modules/seeds/README.md +86 -0
- package/src/modules/seeds/cli.ts +220 -0
- package/src/modules/seeds/examples/sample-seed.json +26 -0
- package/src/modules/seeds/index.ts +11 -0
- package/src/modules/workflows/AGENTS.md +851 -10
- package/src/modules/workflows/acl.ts +96 -0
- package/src/modules/workflows/ai-agents.ts +80 -0
- package/src/modules/workflows/ai-tools/authoring-pack.ts +798 -0
- package/src/modules/workflows/ai-tools/types.ts +117 -0
- package/src/modules/workflows/ai-tools.ts +20 -0
- package/src/modules/workflows/api/command-settings/route.ts +171 -0
- package/src/modules/workflows/api/commands/route.ts +109 -0
- package/src/modules/workflows/api/definitions/[id]/callers/route.ts +95 -0
- package/src/modules/workflows/api/definitions/[id]/context-schema/route.ts +187 -0
- package/src/modules/workflows/api/definitions/[id]/customize/route.ts +6 -1
- package/src/modules/workflows/api/definitions/[id]/draft/route.ts +395 -0
- package/src/modules/workflows/api/definitions/[id]/publish/route.ts +250 -0
- package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +5 -0
- package/src/modules/workflows/api/definitions/[id]/route.ts +107 -7
- package/src/modules/workflows/api/definitions/[id]/test-step/route.ts +288 -0
- package/src/modules/workflows/api/definitions/generate/route.ts +335 -0
- package/src/modules/workflows/api/definitions/route.ts +88 -113
- package/src/modules/workflows/api/definitions/serialize.ts +9 -0
- package/src/modules/workflows/api/endpoints/route.ts +88 -0
- package/src/modules/workflows/api/functions/route.ts +91 -0
- package/src/modules/workflows/api/grantable-features/route.ts +102 -0
- package/src/modules/workflows/api/instances/[id]/context/route.ts +214 -0
- package/src/modules/workflows/api/instances/[id]/rerun-step/route.ts +226 -0
- package/src/modules/workflows/api/instances/[id]/retry/route.ts +18 -2
- package/src/modules/workflows/api/instances/[id]/step-through/route.ts +195 -0
- package/src/modules/workflows/api/instances/[id]/steps/route.ts +160 -0
- package/src/modules/workflows/api/instances/[id]/would-do/route.ts +216 -0
- package/src/modules/workflows/api/instances/bulk-replay/route.ts +141 -0
- package/src/modules/workflows/api/instances/failure-queue/route.ts +197 -0
- package/src/modules/workflows/api/instances/route.ts +135 -3
- package/src/modules/workflows/api/metrics/definitions/route.ts +262 -0
- package/src/modules/workflows/api/openapi.ts +549 -2
- package/src/modules/workflows/api/portal/tasks/[id]/complete/route.ts +160 -0
- package/src/modules/workflows/api/portal/tasks/[id]/route.ts +124 -0
- package/src/modules/workflows/api/portal/tasks/route.ts +157 -0
- package/src/modules/workflows/api/rule-usage/route.ts +94 -0
- package/src/modules/workflows/api/task-settings/route.ts +138 -0
- package/src/modules/workflows/api/tasks/[id]/claim/route.ts +42 -17
- package/src/modules/workflows/api/tasks/[id]/complete/route.ts +47 -15
- package/src/modules/workflows/api/tasks/[id]/reassign/route.ts +197 -0
- package/src/modules/workflows/api/tasks/[id]/route.ts +57 -6
- package/src/modules/workflows/api/tasks/[id]/unclaim/route.ts +132 -0
- package/src/modules/workflows/api/tasks/route.ts +60 -5
- package/src/modules/workflows/api/tasks/serialize.ts +119 -0
- package/src/modules/workflows/api/templates/route.ts +87 -0
- package/src/modules/workflows/api/work-inbox/next/route.ts +170 -0
- package/src/modules/workflows/api/work-inbox/route.ts +153 -0
- package/src/modules/workflows/backend/config/workflows/page.meta.ts +33 -0
- package/src/modules/workflows/backend/config/workflows/page.tsx +12 -0
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +19 -343
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +19 -59
- package/src/modules/workflows/backend/definitions/page.tsx +156 -76
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3129 -584
- package/src/modules/workflows/backend/instances/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/instances/[id]/page.tsx +711 -539
- package/src/modules/workflows/backend/instances/failure-queue/page.meta.ts +16 -0
- package/src/modules/workflows/backend/instances/failure-queue/page.tsx +311 -0
- package/src/modules/workflows/backend/instances/page.meta.ts +1 -1
- package/src/modules/workflows/backend/instances/page.tsx +218 -38
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +639 -400
- package/src/modules/workflows/backend/tasks/page.meta.ts +7 -0
- package/src/modules/workflows/backend/tasks/page.tsx +20 -333
- package/src/modules/workflows/backend/work-inbox/page.meta.ts +15 -0
- package/src/modules/workflows/backend/work-inbox/page.tsx +506 -0
- package/src/modules/workflows/cli.ts +1 -1
- package/src/modules/workflows/commands/tasks.ts +146 -0
- package/src/modules/workflows/components/ActivitiesEditor.tsx +91 -114
- package/src/modules/workflows/components/ActivityEditDialog.tsx +244 -0
- package/src/modules/workflows/components/AgentSelector.tsx +200 -0
- package/src/modules/workflows/components/AnnotationEditDialog.tsx +157 -0
- package/src/modules/workflows/components/BusinessRuleUsagePanel.tsx +106 -0
- package/src/modules/workflows/components/BusinessRulesSelector.tsx +71 -17
- package/src/modules/workflows/components/ConfigJsonTextarea.tsx +111 -0
- package/src/modules/workflows/components/ContextSchemaEditor.tsx +165 -0
- package/src/modules/workflows/components/DefinitionErrorHandlerField.tsx +133 -0
- package/src/modules/workflows/components/DefinitionMetadataDrawer.tsx +456 -0
- package/src/modules/workflows/components/DefinitionMetricsCells.tsx +212 -0
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +196 -95
- package/src/modules/workflows/components/EdgeEditDialog.tsx +15 -16
- package/src/modules/workflows/components/EdgeEditDialogCrudForm.tsx +130 -80
- package/src/modules/workflows/components/InputDataPanel.tsx +177 -0
- package/src/modules/workflows/components/InspectorPanel.tsx +250 -0
- package/src/modules/workflows/components/NodeEditDialog.tsx +444 -38
- package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +848 -178
- package/src/modules/workflows/components/StepsEditor.tsx +9 -2
- package/src/modules/workflows/components/TemplateGalleryDialog.tsx +205 -0
- package/src/modules/workflows/components/TransitionsEditor.tsx +98 -89
- package/src/modules/workflows/components/TriggersDialog.tsx +83 -0
- package/src/modules/workflows/components/TriggersEditor.tsx +363 -0
- package/src/modules/workflows/components/WorkflowAiDraftDialog.tsx +383 -0
- package/src/modules/workflows/components/WorkflowCodeView.tsx +257 -0
- package/src/modules/workflows/components/WorkflowCommandPalette.tsx +82 -0
- package/src/modules/workflows/components/WorkflowCompensationGhostEdge.tsx +78 -0
- package/src/modules/workflows/components/WorkflowDataMappingEdge.tsx +46 -0
- package/src/modules/workflows/components/WorkflowGraph.tsx +54 -1
- package/src/modules/workflows/components/WorkflowGraphImpl.tsx +463 -37
- package/src/modules/workflows/components/WorkflowIconPicker.tsx +144 -0
- package/src/modules/workflows/components/WorkflowLegend.tsx +59 -33
- package/src/modules/workflows/components/WorkflowNodeCard.tsx +355 -28
- package/src/modules/workflows/components/WorkflowRouteChips.tsx +145 -0
- package/src/modules/workflows/components/WorkflowSelector.tsx +33 -14
- package/src/modules/workflows/components/WorkflowTransitionEdge.tsx +83 -10
- package/src/modules/workflows/components/WorkflowTransitionLabel.tsx +13 -2
- package/src/modules/workflows/components/fields/ActivityArrayEditor.tsx +120 -30
- package/src/modules/workflows/components/fields/ActivityConfigFields.tsx +675 -0
- package/src/modules/workflows/components/fields/ActivityTestPanel.tsx +250 -0
- package/src/modules/workflows/components/fields/AgentInvokeConfigField.tsx +580 -0
- package/src/modules/workflows/components/fields/AgentReviewOnBreachField.tsx +88 -0
- package/src/modules/workflows/components/fields/BranchingRoutesEditor.tsx +323 -0
- package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +36 -4
- package/src/modules/workflows/components/fields/CommandPicker.tsx +158 -0
- package/src/modules/workflows/components/fields/EndpointPicker.tsx +330 -0
- package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +2 -2
- package/src/modules/workflows/components/fields/FunctionPicker.tsx +68 -0
- package/src/modules/workflows/components/fields/MappingArrayEditor.tsx +46 -12
- package/src/modules/workflows/components/fields/PortFieldArrayEditor.tsx +255 -0
- package/src/modules/workflows/components/fields/RolesMultiSelect.tsx +68 -0
- package/src/modules/workflows/components/fields/RouteOrderEditor.tsx +169 -0
- package/src/modules/workflows/components/fields/SchemaBuilderDialog.tsx +139 -0
- package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +2 -2
- package/src/modules/workflows/components/fields/TaskAssignmentField.tsx +355 -0
- package/src/modules/workflows/components/fields/TaskDeadlineFields.tsx +172 -0
- package/src/modules/workflows/components/fields/TaskDecisionsField.tsx +294 -0
- package/src/modules/workflows/components/fields/TaskEntityBindingsField.tsx +156 -0
- package/src/modules/workflows/components/fields/TemplateTextControl.tsx +85 -0
- package/src/modules/workflows/components/fields/VariablePickerButton.tsx +177 -0
- package/src/modules/workflows/components/fields/ledgerDropTarget.ts +55 -0
- package/src/modules/workflows/components/fields/useActivityTypeOptions.ts +19 -0
- package/src/modules/workflows/components/formConfig.tsx +84 -10
- package/src/modules/workflows/components/mobile/MobileDefinitionDetail.tsx +5 -0
- package/src/modules/workflows/components/mobile/MobileMetadataSheet.tsx +10 -0
- package/src/modules/workflows/components/mobile/MobileTaskForm.tsx +55 -19
- package/src/modules/workflows/components/mobile/MobileVisualEditor.tsx +49 -40
- package/src/modules/workflows/components/nodes/AnnotationGroupNode.tsx +81 -0
- package/src/modules/workflows/components/nodes/AutomatedNode.tsx +34 -17
- package/src/modules/workflows/components/nodes/EndNode.tsx +15 -14
- package/src/modules/workflows/components/nodes/ErrorOutputHandle.tsx +32 -0
- package/src/modules/workflows/components/nodes/IfElseNode.tsx +64 -0
- package/src/modules/workflows/components/nodes/InvokeAgentNode.tsx +180 -0
- package/src/modules/workflows/components/nodes/NodeOutcomeRows.tsx +143 -0
- package/src/modules/workflows/components/nodes/ParallelForkNode.tsx +28 -15
- package/src/modules/workflows/components/nodes/ParallelJoinNode.tsx +28 -15
- package/src/modules/workflows/components/nodes/StartNode.tsx +78 -18
- package/src/modules/workflows/components/nodes/StickyNoteNode.tsx +65 -0
- package/src/modules/workflows/components/nodes/SubWorkflowNode.tsx +124 -23
- package/src/modules/workflows/components/nodes/SwitchNode.tsx +64 -0
- package/src/modules/workflows/components/nodes/TriggerCap.tsx +103 -0
- package/src/modules/workflows/components/nodes/TriggerNode.tsx +151 -0
- package/src/modules/workflows/components/nodes/UserTaskNode.tsx +67 -22
- package/src/modules/workflows/components/nodes/WaitForConditionNode.tsx +74 -0
- package/src/modules/workflows/components/nodes/WaitForSignalNode.tsx +31 -17
- package/src/modules/workflows/components/nodes/WaitForTimerNode.tsx +31 -16
- package/src/modules/workflows/components/nodes/index.ts +17 -0
- package/src/modules/workflows/components/portal/PortalTaskForm.tsx +280 -0
- package/src/modules/workflows/components/run/AgentActivityPanel.tsx +48 -0
- package/src/modules/workflows/components/run/RerunStepDialog.tsx +133 -0
- package/src/modules/workflows/components/run/RunEventBadge.tsx +37 -0
- package/src/modules/workflows/components/run/RunGantt.tsx +180 -0
- package/src/modules/workflows/components/run/RunStatusBadge.tsx +112 -0
- package/src/modules/workflows/components/run/RunStepInspector.tsx +176 -0
- package/src/modules/workflows/components/run/WouldDoReport.tsx +93 -0
- package/src/modules/workflows/components/run/useAgentLabels.ts +42 -0
- package/src/modules/workflows/components/run/useLastRunOverlay.ts +150 -0
- package/src/modules/workflows/components/run/useLiveAgentActions.ts +70 -0
- package/src/modules/workflows/components/run/useLiveRunUpdates.ts +89 -0
- package/src/modules/workflows/components/settings/CommandSettingsPageClient.tsx +228 -0
- package/src/modules/workflows/components/work-inbox/EntityContextPanel.tsx +179 -0
- package/src/modules/workflows/components/work-inbox/ReassignTaskDialog.tsx +203 -0
- package/src/modules/workflows/components/work-inbox/StatusChip.tsx +61 -0
- package/src/modules/workflows/components/work-inbox/TaskActionNotice.tsx +77 -0
- package/src/modules/workflows/components/work-inbox/TaskFormFields.tsx +322 -0
- package/src/modules/workflows/components/work-inbox/WorkInboxEmptyState.tsx +43 -0
- package/src/modules/workflows/data/activity-config-schemas.ts +249 -0
- package/src/modules/workflows/data/activity-config-warnings.ts +71 -0
- package/src/modules/workflows/data/branching-route-warnings.ts +129 -0
- package/src/modules/workflows/data/entities.ts +397 -4
- package/src/modules/workflows/data/metrics-validators.ts +51 -0
- package/src/modules/workflows/data/task-primitives.ts +36 -0
- package/src/modules/workflows/data/types.ts +81 -2
- package/src/modules/workflows/data/validators.ts +729 -60
- package/src/modules/workflows/di.ts +22 -0
- package/src/modules/workflows/events.ts +68 -8
- package/src/modules/workflows/examples/oze-residential-install-60-nodes.json +1545 -0
- package/src/modules/workflows/examples/sales-pipeline-definition.json +35 -35
- package/src/modules/workflows/examples/templates/lead-to-install.json +160 -0
- package/src/modules/workflows/examples/templates/order-approval.json +230 -0
- package/src/modules/workflows/examples/templates/task-escalation.json +110 -0
- package/src/modules/workflows/examples/templates/webhook-integration.json +113 -0
- package/src/modules/workflows/extension-points.ts +1 -1
- package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.meta.ts +21 -0
- package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/[id]/page.tsx +212 -0
- package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/page.meta.ts +25 -0
- package/src/modules/workflows/frontend/[orgSlug]/portal/tasks/page.tsx +185 -0
- package/src/modules/workflows/i18n/de.json +1083 -24
- package/src/modules/workflows/i18n/en.json +1081 -22
- package/src/modules/workflows/i18n/es.json +1083 -24
- package/src/modules/workflows/i18n/ko.json +1072 -13
- package/src/modules/workflows/i18n/pl.json +1082 -23
- package/src/modules/workflows/lib/activity-executor.ts +855 -186
- package/src/modules/workflows/lib/activity-queue-types.ts +120 -1
- package/src/modules/workflows/lib/activity-registry-bootstrap.ts +7 -0
- package/src/modules/workflows/lib/activity-registry.ts +89 -0
- package/src/modules/workflows/lib/activity-types.ts +415 -0
- package/src/modules/workflows/lib/activity-worker-handler.ts +744 -35
- package/src/modules/workflows/lib/advanced-config.ts +41 -0
- package/src/modules/workflows/lib/agent-disposition-task.ts +343 -0
- package/src/modules/workflows/lib/agent-outcome-paths.ts +153 -0
- package/src/modules/workflows/lib/agent-result-mapping.ts +88 -0
- package/src/modules/workflows/lib/agent-review-inspector.ts +125 -0
- package/src/modules/workflows/lib/agent-review.ts +171 -0
- package/src/modules/workflows/lib/ai-authoring.ts +402 -0
- package/src/modules/workflows/lib/ai-draft-runner.ts +105 -0
- package/src/modules/workflows/lib/annotation-events.ts +15 -0
- package/src/modules/workflows/lib/branching-routes.ts +280 -0
- package/src/modules/workflows/lib/breach-routing.ts +142 -0
- package/src/modules/workflows/lib/bulk-replay.ts +185 -0
- package/src/modules/workflows/lib/business-rule-usage.ts +154 -0
- package/src/modules/workflows/lib/caller-graph.ts +104 -0
- package/src/modules/workflows/lib/code-view-apply.ts +178 -0
- package/src/modules/workflows/lib/collect-validation-issues.ts +239 -0
- package/src/modules/workflows/lib/compensation-ghosts.ts +134 -0
- package/src/modules/workflows/lib/component-guard.ts +13 -0
- package/src/modules/workflows/lib/condition-handler.ts +658 -0
- package/src/modules/workflows/lib/context-ledger.ts +814 -0
- package/src/modules/workflows/lib/crud-form-dialogs-flag.ts +5 -0
- package/src/modules/workflows/lib/data-edge-mapping.ts +112 -0
- package/src/modules/workflows/lib/definition-context-schema.ts +103 -0
- package/src/modules/workflows/lib/definition-edit-safety.ts +228 -0
- package/src/modules/workflows/lib/definition-error-body.ts +43 -0
- package/src/modules/workflows/lib/definition-evaluation.ts +156 -0
- package/src/modules/workflows/lib/definition-grant.ts +211 -0
- package/src/modules/workflows/lib/definition-json-locations.ts +226 -0
- package/src/modules/workflows/lib/definition-payload.ts +81 -0
- package/src/modules/workflows/lib/draft-restore.ts +72 -0
- package/src/modules/workflows/lib/dry-run.ts +203 -0
- package/src/modules/workflows/lib/duration.ts +138 -24
- package/src/modules/workflows/lib/edge-reattachment.ts +186 -0
- package/src/modules/workflows/lib/edgeFormTransforms.ts +15 -14
- package/src/modules/workflows/lib/editor-annotations.ts +301 -0
- package/src/modules/workflows/lib/editor-commands.ts +205 -0
- package/src/modules/workflows/lib/editor-history.ts +151 -0
- package/src/modules/workflows/lib/endpoint-catalog.ts +283 -0
- package/src/modules/workflows/lib/endpoint-path.ts +134 -0
- package/src/modules/workflows/lib/engine-version.ts +67 -0
- package/src/modules/workflows/lib/error-handler.ts +192 -0
- package/src/modules/workflows/lib/error-routing.ts +236 -0
- package/src/modules/workflows/lib/event-logger.ts +27 -0
- package/src/modules/workflows/lib/expression-refs.ts +291 -0
- package/src/modules/workflows/lib/failure-grouping.ts +134 -0
- package/src/modules/workflows/lib/find-definition.ts +4 -0
- package/src/modules/workflows/lib/flow-logic-warnings.ts +591 -0
- package/src/modules/workflows/lib/graph-utils.ts +620 -110
- package/src/modules/workflows/lib/icon-search.ts +65 -0
- package/src/modules/workflows/lib/insert-at-cursor.ts +53 -0
- package/src/modules/workflows/lib/instance-date-filter.ts +56 -0
- package/src/modules/workflows/lib/interpolation-pipeline.ts +351 -0
- package/src/modules/workflows/lib/ledger-drag.ts +61 -0
- package/src/modules/workflows/lib/ledger-entry-display.ts +89 -0
- package/src/modules/workflows/lib/ledger-schema-flatten.ts +137 -0
- package/src/modules/workflows/lib/metrics/definition-metrics.ts +268 -0
- package/src/modules/workflows/lib/metrics/metrics-display.ts +57 -0
- package/src/modules/workflows/lib/metrics/rollup-schedule.ts +26 -0
- package/src/modules/workflows/lib/metrics/rollup-service.ts +292 -0
- package/src/modules/workflows/lib/node-config-summary.ts +235 -0
- package/src/modules/workflows/lib/node-geometry.ts +168 -0
- package/src/modules/workflows/lib/node-nudge.ts +63 -0
- package/src/modules/workflows/lib/node-outcome-rows.ts +195 -0
- package/src/modules/workflows/lib/node-placement.ts +104 -0
- package/src/modules/workflows/lib/node-type-icons.ts +71 -10
- package/src/modules/workflows/lib/nodeFormTransforms.ts +519 -28
- package/src/modules/workflows/lib/outcome-routing.ts +346 -0
- package/src/modules/workflows/lib/owned-definition.ts +188 -0
- package/src/modules/workflows/lib/owned-node-changes.ts +29 -0
- package/src/modules/workflows/lib/palette-drag.ts +68 -0
- package/src/modules/workflows/lib/palette-drop.ts +114 -0
- package/src/modules/workflows/lib/parallel-handler.ts +79 -2
- package/src/modules/workflows/lib/port-contract.ts +107 -0
- package/src/modules/workflows/lib/portal-task-access.ts +220 -0
- package/src/modules/workflows/lib/rerun-from-step.ts +140 -0
- package/src/modules/workflows/lib/route-chip-events.ts +45 -0
- package/src/modules/workflows/lib/route-chips.ts +177 -0
- package/src/modules/workflows/lib/route-edge.ts +57 -0
- package/src/modules/workflows/lib/route-kinds.ts +166 -0
- package/src/modules/workflows/lib/route-priority.ts +197 -0
- package/src/modules/workflows/lib/run-duration.ts +70 -0
- package/src/modules/workflows/lib/run-event-tone.ts +46 -0
- package/src/modules/workflows/lib/run-execution.ts +598 -0
- package/src/modules/workflows/lib/run-gantt.ts +311 -0
- package/src/modules/workflows/lib/run-outcome-evidence.ts +60 -0
- package/src/modules/workflows/lib/run-outcome.ts +142 -0
- package/src/modules/workflows/lib/sample-resolver.ts +113 -0
- package/src/modules/workflows/lib/seeds.ts +3 -1
- package/src/modules/workflows/lib/server-output-contract.ts +120 -0
- package/src/modules/workflows/lib/set-variable.ts +94 -0
- package/src/modules/workflows/lib/signal-handler.ts +134 -4
- package/src/modules/workflows/lib/start-fixtures.ts +93 -0
- package/src/modules/workflows/lib/status-colors.ts +220 -21
- package/src/modules/workflows/lib/step-handler.ts +744 -68
- package/src/modules/workflows/lib/step-presentation.ts +295 -0
- package/src/modules/workflows/lib/step-through.ts +71 -0
- package/src/modules/workflows/lib/step-type-conversion.ts +263 -0
- package/src/modules/workflows/lib/subgraph-clipboard.ts +214 -0
- package/src/modules/workflows/lib/task-decision-context.ts +76 -0
- package/src/modules/workflows/lib/task-decisions.ts +117 -0
- package/src/modules/workflows/lib/task-entity-access.ts +181 -0
- package/src/modules/workflows/lib/task-entity-aliases.ts +77 -0
- package/src/modules/workflows/lib/task-entity-types.ts +66 -0
- package/src/modules/workflows/lib/task-form-registry.ts +123 -0
- package/src/modules/workflows/lib/task-form-schema.ts +129 -0
- package/src/modules/workflows/lib/task-handler.ts +492 -51
- package/src/modules/workflows/lib/task-inspector-config.ts +348 -0
- package/src/modules/workflows/lib/task-list-query.ts +46 -0
- package/src/modules/workflows/lib/task-notifications.ts +218 -0
- package/src/modules/workflows/lib/task-permission-settings.ts +117 -0
- package/src/modules/workflows/lib/task-presets.ts +95 -0
- package/src/modules/workflows/lib/task-quick-action.ts +111 -0
- package/src/modules/workflows/lib/task-resolution.ts +270 -0
- package/src/modules/workflows/lib/task-sla.ts +628 -0
- package/src/modules/workflows/lib/task-visibility-request.ts +668 -0
- package/src/modules/workflows/lib/task-visibility.ts +627 -0
- package/src/modules/workflows/lib/timer-handler.ts +8 -1
- package/src/modules/workflows/lib/transition-handler.ts +228 -20
- package/src/modules/workflows/lib/trigger-node.ts +272 -0
- package/src/modules/workflows/lib/visual-editor-navigation.ts +29 -0
- package/src/modules/workflows/lib/work-inbox/empty-state.ts +150 -0
- package/src/modules/workflows/lib/work-inbox/entity-links.ts +99 -0
- package/src/modules/workflows/lib/work-inbox/navigation.ts +28 -0
- package/src/modules/workflows/lib/work-inbox/presentation.ts +163 -0
- package/src/modules/workflows/lib/work-inbox/provider.ts +390 -0
- package/src/modules/workflows/lib/work-inbox/query.ts +103 -0
- package/src/modules/workflows/lib/work-inbox/service.ts +122 -0
- package/src/modules/workflows/lib/work-inbox/user-task-source.ts +240 -0
- package/src/modules/workflows/lib/workflow-command-enablement.ts +188 -0
- package/src/modules/workflows/lib/workflow-command-settings.ts +124 -0
- package/src/modules/workflows/lib/workflow-executor.ts +1036 -10
- package/src/modules/workflows/lib/workflow-function-registry.ts +44 -0
- package/src/modules/workflows/lib/workflow-safe-commands.ts +42 -1
- package/src/modules/workflows/lib/workflow-templates.ts +91 -0
- package/src/modules/workflows/migrations/.snapshot-open-mercato.json +2321 -698
- package/src/modules/workflows/migrations/Migration20260626214855_workflows.ts +15 -0
- package/src/modules/workflows/migrations/Migration20260626222424_workflows.ts +17 -0
- package/src/modules/workflows/migrations/Migration20260727074335_workflows.ts +15 -0
- package/src/modules/workflows/migrations/Migration20260728104038_workflows.ts +13 -0
- package/src/modules/workflows/migrations/Migration20260728163001_workflows.ts +36 -0
- package/src/modules/workflows/migrations/Migration20260729061736_workflows.ts +13 -0
- package/src/modules/workflows/migrations/Migration20260729192652_workflows.ts +11 -0
- package/src/modules/workflows/migrations/Migration20260730085000_workflows.ts +13 -0
- package/src/modules/workflows/migrations/Migration20260730092706_workflows.ts +13 -0
- package/src/modules/workflows/notifications.ts +40 -10
- package/src/modules/workflows/setup.ts +128 -0
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +36 -45
- package/src/modules/workflows/subscribers/task-deadline-breached-notification.ts +31 -0
- package/src/modules/workflows/subscribers/task-reminder-notification.ts +31 -0
- package/src/modules/workflows/widgets/injection/pending-work/widget.client.tsx +119 -0
- package/src/modules/workflows/widgets/injection/pending-work/widget.ts +27 -0
- package/src/modules/workflows/widgets/injection-table.ts +52 -2
- package/src/modules/workflows/workers/workflow-activities.worker.ts +95 -42
- package/src/modules/workflows/workers/workflow-definition-metric-rollup.worker.ts +71 -0
- package/src/modules/workflows/workers/workflow-instance-bulk-replay.ts +51 -0
- package/src/modules/workflows/workers/workflow-invoke-agent.worker.ts +72 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/workflows/lib/activity-executor.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Workflows Module - Activity Executor Service\n *\n * Executes workflow activities (send email, call API, emit events, etc.)\n * - Supports multiple activity types\n * - Implements retry logic with exponential backoff\n * - Handles timeouts\n * - Variable interpolation from workflow context\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { EntityManager as PostgreSqlEntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { WorkflowInstance } from '../data/entities'\nimport { createModuleQueue, Queue } from '@open-mercato/queue'\nimport { getRedisUrl } from '@open-mercato/shared/lib/redis/connection'\nimport {\n safeOutboundFetch,\n UnsafeOutboundUrlError,\n type HostLookup,\n} from '@open-mercato/shared/lib/url-safety'\nimport { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\nimport { isPrivateCrossProcessBroadcastEvent } from '@open-mercato/shared/modules/events'\nimport { callWebhookConfigSchema } from '../data/validators'\nimport { WorkflowActivityJob, WORKFLOW_ACTIVITIES_QUEUE_NAME } from './activity-queue-types'\nimport { logWorkflowEvent } from './event-logger'\nimport { parseDuration } from './duration'\nimport { resolveActivityTimeoutMs } from './activityTimeoutFields'\nimport { getWorkflowSafeCommand } from './workflow-safe-commands'\n\nexport { isPrivateUrl } from '@open-mercato/shared/lib/network'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('workflows')\n\nfunction isAllowPrivateWorkflowWebhookUrlsEnabled(): boolean {\n if (parseBooleanWithDefault(process.env.OM_WORKFLOWS_ALLOW_PRIVATE_URLS, false)) {\n if (process.env.NODE_ENV === 'production') {\n logger.warn('OM_WORKFLOWS_ALLOW_PRIVATE_URLS is set but ignored in production. SSRF protection remains enabled.', { component: 'CALL_WEBHOOK' })\n return false\n }\n\n logger.warn('OM_WORKFLOWS_ALLOW_PRIVATE_URLS is enabled. SSRF protection is bypassed for workflow webhooks; use only in development.', { component: 'CALL_WEBHOOK' })\n return true\n }\n\n if (parseBooleanWithDefault(process.env.WORKFLOW_WEBHOOK_ALLOW_PRIVATE_URLS, false)) {\n if (process.env.NODE_ENV === 'production') {\n logger.warn('WORKFLOW_WEBHOOK_ALLOW_PRIVATE_URLS is deprecated and ignored in production. Use OM_WORKFLOWS_ALLOW_PRIVATE_URLS for development only. SSRF protection remains enabled.', { component: 'CALL_WEBHOOK' })\n return false\n }\n\n logger.warn('WORKFLOW_WEBHOOK_ALLOW_PRIVATE_URLS is deprecated. Use OM_WORKFLOWS_ALLOW_PRIVATE_URLS instead. SSRF protection is bypassed.', { component: 'CALL_WEBHOOK' })\n return true\n }\n\n return false\n}\n\nconst DEFAULT_WORKFLOW_ENV_INTERPOLATION_ALLOWLIST = new Set(['APP_URL'])\nconst WORKFLOW_ENV_INTERPOLATION_ALLOWLIST_KEY = 'OM_WORKFLOWS_ENV_INTERPOLATION_ALLOWLIST'\n\nfunction getWorkflowEnvInterpolationAllowlist(): Set<string> {\n const allowlist = new Set(DEFAULT_WORKFLOW_ENV_INTERPOLATION_ALLOWLIST)\n const configuredKeys = process.env[WORKFLOW_ENV_INTERPOLATION_ALLOWLIST_KEY]\n if (!configuredKeys) {\n return allowlist\n }\n\n for (const key of configuredKeys.split(',')) {\n const trimmedKey = key.trim()\n if (trimmedKey) {\n allowlist.add(trimmedKey)\n }\n }\n\n return allowlist\n}\n\nfunction resolveWorkflowEnvInterpolation(envKey: string): string {\n if (!getWorkflowEnvInterpolationAllowlist().has(envKey)) {\n return ''\n }\n\n return process.env[envKey] ?? ''\n}\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport type ActivityType =\n | 'SEND_EMAIL'\n | 'CALL_API'\n | 'EMIT_EVENT'\n | 'UPDATE_ENTITY'\n | 'CALL_WEBHOOK'\n | 'EXECUTE_FUNCTION'\n | 'WAIT'\n\nexport interface ActivityDefinition {\n activityId: string // Unique identifier for activity\n activityName?: string // Optional, for debugging/logging\n activityType: ActivityType\n config: any\n async?: boolean // Flag to execute activity asynchronously via queue\n retryPolicy?: RetryPolicy\n timeoutMs?: number\n /**\n * @deprecated Use `timeoutMs`. Legacy ISO 8601 duration string accepted by\n * the definition schema before #4424; normalized by `resolveActivityTimeoutMs`.\n */\n timeout?: string\n compensate?: boolean // Flag to execute compensation on failure\n}\n\nexport { resolveActivityTimeoutMs }\n\nexport interface RetryPolicy {\n maxAttempts: number\n initialIntervalMs: number\n backoffCoefficient: number\n maxIntervalMs: number\n}\n\nexport interface ActivityContext {\n workflowInstance: WorkflowInstance\n workflowContext: Record<string, any>\n stepContext?: Record<string, any>\n stepInstanceId?: string\n // Set when the activity runs inside a parallel branch; carried on the queue\n // payload so async resume targets the branch rather than the instance.\n branchInstanceId?: string | null\n transitionId?: string\n userId?: string\n}\n\ntype RbacFeatureResolver = {\n userHasAllFeatures: (\n userId: string,\n required: string[],\n opts: { tenantId: string | null; organizationId: string | null }\n ) => Promise<boolean>\n}\n\nasync function workflowUserHasAllFeatures(\n container: AwilixContainer,\n userId: string,\n required: readonly string[],\n tenantId: string | null,\n organizationId: string | null\n): Promise<boolean> {\n try {\n const rbac = container.resolve('rbacService') as RbacFeatureResolver | undefined\n if (rbac?.userHasAllFeatures) {\n return await rbac.userHasAllFeatures(userId, [...required], { tenantId, organizationId })\n }\n } catch {\n // Fail closed below when the workflow executor cannot prove the actor's grants.\n }\n return false\n}\n\nexport interface ActivityExecutionResult {\n activityId: string\n activityName?: string\n activityType: ActivityType\n success: boolean\n output?: any\n error?: string\n retryCount: number\n executionTimeMs: number\n async?: boolean // Marks activity as async (queued)\n jobId?: string // Queue job ID for async activities\n}\n\nexport class ActivityExecutionError extends Error {\n constructor(\n message: string,\n public activityType: ActivityType,\n public activityName?: string,\n public details?: any\n ) {\n super(message)\n this.name = 'ActivityExecutionError'\n }\n}\n\n// ============================================================================\n// Queue Integration for Async Activities\n// ============================================================================\n\nlet activityQueue: Queue<WorkflowActivityJob> | null = null\n\n/**\n * Get or create the activity queue (lazy initialization)\n */\nfunction getActivityQueue(): Queue<WorkflowActivityJob> {\n if (!activityQueue) {\n activityQueue = createModuleQueue<WorkflowActivityJob>(\n WORKFLOW_ACTIVITIES_QUEUE_NAME,\n { concurrency: parseInt(process.env.WORKFLOW_WORKER_CONCURRENCY || '5') },\n )\n }\n\n return activityQueue\n}\n\n/**\n * Enqueue an activity for background execution\n *\n * @param em - Entity manager\n * @param activity - Activity definition\n * @param context - Execution context\n * @returns Job ID\n */\nexport async function enqueueActivity(\n em: EntityManager,\n activity: ActivityDefinition,\n context: ActivityContext\n): Promise<string> {\n const { workflowInstance, workflowContext, stepContext, transitionId, stepInstanceId, branchInstanceId } =\n context\n\n // Interpolate config variables NOW (before queuing)\n const interpolatedConfig = interpolateVariables(activity.config, workflowContext, workflowInstance)\n\n // Create job payload\n const job: WorkflowActivityJob = {\n workflowInstanceId: workflowInstance.id,\n stepInstanceId,\n branchInstanceId: branchInstanceId ?? undefined,\n transitionId,\n activityId: activity.activityId,\n activityName: activity.activityName || activity.activityType,\n activityType: activity.activityType,\n activityConfig: interpolatedConfig,\n workflowContext,\n stepContext,\n retryPolicy: activity.retryPolicy,\n timeoutMs: activity.timeoutMs,\n tenantId: workflowInstance.tenantId,\n organizationId: workflowInstance.organizationId,\n userId: context.userId,\n }\n\n // Enqueue to queue (WAIT activities use delayMs for the actual delay)\n const queue = getActivityQueue()\n const enqueueOptions = activity.activityType === 'WAIT' && (interpolatedConfig.duration || interpolatedConfig.until)\n ? { delayMs: calculateWaitDelayMs(interpolatedConfig) }\n : undefined\n const jobId = await queue.enqueue(job, enqueueOptions)\n\n // Log event\n await logWorkflowEvent(em, {\n workflowInstanceId: workflowInstance.id,\n stepInstanceId,\n eventType: 'ACTIVITY_QUEUED',\n eventData: {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n async: true,\n jobId,\n },\n tenantId: workflowInstance.tenantId,\n organizationId: workflowInstance.organizationId,\n })\n\n return jobId\n}\n\n/**\n * Enqueue a delayed timer job for a WAIT_FOR_TIMER step.\n *\n * The activity worker handles `kind: 'timer'` jobs by calling\n * `timerHandler.fireTimer`, which resumes the paused workflow instance.\n */\nexport async function enqueueTimerJob(params: {\n workflowInstanceId: string\n stepInstanceId: string\n branchInstanceId?: string | null\n tenantId: string\n organizationId: string\n userId?: string\n fireAt: string\n delayMs: number\n}): Promise<string> {\n const { workflowInstanceId, stepInstanceId, branchInstanceId, tenantId, organizationId, userId, fireAt, delayMs } =\n params\n\n const queue = getActivityQueue()\n const jobId = await queue.enqueue(\n {\n kind: 'timer',\n workflowInstanceId,\n stepInstanceId,\n branchInstanceId: branchInstanceId ?? undefined,\n tenantId,\n organizationId,\n userId,\n fireAt,\n },\n { delayMs: delayMs > 0 ? delayMs : undefined }\n )\n\n return jobId\n}\n\n// ============================================================================\n// Main Activity Execution Functions\n// ============================================================================\n\n/**\n * Execute a single activity with retry logic and timeout\n *\n * @param em - Entity manager\n * @param container - DI container\n * @param activity - Activity definition\n * @param context - Execution context\n * @returns Execution result\n */\nexport async function executeActivity(\n em: EntityManager,\n container: AwilixContainer,\n activity: ActivityDefinition,\n context: ActivityContext\n): Promise<ActivityExecutionResult> {\n const retryPolicy = activity.retryPolicy || {\n maxAttempts: 1,\n initialIntervalMs: 0,\n backoffCoefficient: 1,\n maxIntervalMs: 0,\n }\n\n let lastError: any\n let retryCount = 0\n\n for (let attempt = 0; attempt < retryPolicy.maxAttempts; attempt++) {\n try {\n const startTime = Date.now()\n\n // Execute with timeout if specified (timeoutMs, or a legacy ISO 8601\n // `timeout` string normalized to ms \u2014 see resolveActivityTimeoutMs).\n const timeoutMs = resolveActivityTimeoutMs(activity)\n const result = timeoutMs\n ? await executeWithTimeout(\n (signal) => executeActivityByType(em, container, activity, context, signal),\n timeoutMs\n )\n : await executeActivityByType(em, container, activity, context)\n\n const executionTimeMs = Date.now() - startTime\n\n return {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n success: true,\n output: result,\n retryCount: attempt,\n executionTimeMs,\n async: activity.async || false,\n }\n } catch (error) {\n lastError = error\n retryCount = attempt + 1\n\n // Log activity retry attempt with context\n if (attempt < retryPolicy.maxAttempts - 1) {\n logger.error('Activity failed; will retry', {\n activityId: activity.activityId,\n activityType: activity.activityType,\n attempt: attempt + 1,\n maxAttempts: retryPolicy.maxAttempts,\n instanceId: context.workflowInstance.id,\n err: error,\n })\n }\n\n // If not the last attempt, apply backoff and retry\n if (attempt < retryPolicy.maxAttempts - 1) {\n const backoff = calculateBackoff(\n retryPolicy.initialIntervalMs,\n retryPolicy.backoffCoefficient,\n attempt,\n retryPolicy.maxIntervalMs\n )\n\n await sleep(backoff)\n }\n }\n }\n\n // All retries exhausted\n const errorMessage = lastError instanceof Error ? lastError.message : String(lastError)\n logger.error('Activity failed after all attempts', {\n activityId: activity.activityId,\n activityType: activity.activityType,\n attempts: retryCount,\n instanceId: context.workflowInstance.id,\n err: lastError,\n })\n\n return {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n success: false,\n error: `Activity failed after ${retryCount} attempts: ${errorMessage}`,\n retryCount,\n executionTimeMs: 0,\n async: activity.async || false,\n }\n}\n\n/**\n * Execute multiple activities in sequence\n * Supports both synchronous and asynchronous (queued) execution\n *\n * @param em - Entity manager\n * @param container - DI container\n * @param activities - Array of activity definitions\n * @param context - Execution context\n * @returns Array of execution results\n */\nexport async function executeActivities(\n em: EntityManager,\n container: AwilixContainer,\n activities: ActivityDefinition[],\n context: ActivityContext\n): Promise<ActivityExecutionResult[]> {\n const results: ActivityExecutionResult[] = []\n\n for (let i = 0; i < activities.length; i++) {\n const activity = activities[i]\n\n // Check if activity should run async\n if (activity.async) {\n // Enqueue for background execution\n const jobId = await enqueueActivity(em, activity, context)\n\n results.push({\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n success: true, // Queued successfully\n async: true,\n jobId,\n retryCount: 0,\n executionTimeMs: 0,\n })\n } else {\n // Execute synchronously (existing logic)\n const result = await executeActivity(em, container, activity, context)\n results.push(result)\n\n // Stop execution if activity fails (fail-fast)\n if (!result.success) {\n break\n }\n\n // Update workflow context with activity output\n if (result.output && typeof result.output === 'object') {\n const key = activity.activityName || activity.activityType\n context.workflowContext = {\n ...context.workflowContext,\n [key]: result.output,\n }\n }\n }\n }\n\n return results\n}\n\n// ============================================================================\n// Activity Type Handlers\n// ============================================================================\n\n/**\n * Execute activity based on its type\n */\nasync function executeActivityByType(\n em: EntityManager,\n container: AwilixContainer,\n activity: ActivityDefinition,\n context: ActivityContext,\n signal?: AbortSignal\n): Promise<any> {\n // Interpolate config variables from context (including workflow metadata)\n const interpolatedConfig = interpolateVariables(activity.config, context.workflowContext, context.workflowInstance)\n\n switch (activity.activityType) {\n case 'SEND_EMAIL':\n return await executeSendEmail(interpolatedConfig, context, container)\n\n case 'CALL_API':\n return await executeCallApi(em, interpolatedConfig, context, container, signal)\n\n case 'EMIT_EVENT':\n return await executeEmitEvent(interpolatedConfig, context, container)\n\n case 'UPDATE_ENTITY':\n return await executeUpdateEntity(em, interpolatedConfig, context, container)\n\n case 'CALL_WEBHOOK':\n return await executeCallWebhook(interpolatedConfig, context, { signal })\n\n case 'EXECUTE_FUNCTION':\n return await executeFunction(interpolatedConfig, context, container)\n\n case 'WAIT':\n return await executeWait(interpolatedConfig)\n\n default:\n throw new ActivityExecutionError(\n `Unknown activity type: ${activity.activityType}`,\n activity.activityType,\n activity.activityName\n )\n }\n}\n\n/**\n * SEND_EMAIL activity handler\n *\n * For MVP, this logs the email (actual email sending can be added later)\n */\nexport async function executeSendEmail(\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { to, subject, template, templateData, body } = config\n\n if (!to || !subject) {\n throw new Error('SEND_EMAIL requires \"to\" and \"subject\" fields')\n }\n\n // For MVP: Log the email (actual email service integration can be added later)\n logger.info('Send email activity invoked', { component: 'SEND_EMAIL', subject })\n\n // Check if email service is available in container\n try {\n const emailService = container.resolve<{ send: (input: unknown) => Promise<unknown> | unknown }>('emailService')\n if (emailService && typeof emailService.send === 'function') {\n await emailService.send({\n to,\n subject,\n template,\n templateData,\n body,\n })\n return { sent: true, to, subject, via: 'emailService' }\n }\n } catch (error) {\n // Email service not available, just log\n }\n\n return { sent: true, to, subject, via: 'console' }\n}\n\n/**\n * EMIT_EVENT activity handler\n *\n * Publishes a domain event to the event bus\n */\nexport async function executeEmitEvent(\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { eventName, payload } = config\n\n if (!eventName) {\n throw new Error('EMIT_EVENT requires \"eventName\" field')\n }\n\n // Workflow definitions are tenant-managed input. Private cross-process\n // events coordinate trusted server state (for example closing an in-memory\n // collaboration room), so allowing a workflow to name one would turn a\n // regular event activity into a cross-process invalidation primitive.\n if (isPrivateCrossProcessBroadcastEvent(eventName)) {\n throw new Error(`EMIT_EVENT cannot emit private cross-process event \"${eventName}\"`)\n }\n\n // Emissions are fire-and-forget and no subscriber validates the payload shape,\n // so an unresolved `{{context.x}}` here is even quieter than on the command\n // path \u2014 it ships the literal template to every consumer. Fail loudly instead.\n const unresolvedPayloadKeys = findUnresolvedTemplateKeys(payload)\n if (unresolvedPayloadKeys.length > 0) {\n throw new Error(\n `EMIT_EVENT payload contains unresolved template variables for: ${unresolvedPayloadKeys.join(', ')}. ` +\n `Check that the workflow context provides these keys.`\n )\n }\n\n // Get event bus from container\n const eventBus = container.resolve<{ emitEvent: (event: string, payload: unknown, options?: unknown) => Promise<unknown> | unknown }>('eventBus')\n\n if (!eventBus || typeof eventBus.emitEvent !== 'function') {\n throw new Error('Event bus not available in container')\n }\n\n // Publish event with workflow metadata\n const enrichedPayload = {\n ...payload,\n _workflow: {\n workflowInstanceId: context.workflowInstance.id,\n workflowId: context.workflowInstance.workflowId,\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n },\n }\n\n await eventBus.emitEvent(eventName, enrichedPayload, {\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n })\n\n return { emitted: true, eventName, payload: enrichedPayload }\n}\n\nconst UNRESOLVED_TEMPLATE_PATTERN = /\\{\\{[^}]+\\}\\}/\n\nfunction findUnresolvedTemplateKeys(value: unknown, path = ''): string[] {\n if (typeof value === 'string') {\n return UNRESOLVED_TEMPLATE_PATTERN.test(value) ? [path] : []\n }\n if (Array.isArray(value)) {\n return value.flatMap((item, index) => findUnresolvedTemplateKeys(item, `${path}[${index}]`))\n }\n if (value && typeof value === 'object') {\n return Object.entries(value).flatMap(([key, nested]) =>\n findUnresolvedTemplateKeys(nested, path ? `${path}.${key}` : key)\n )\n }\n return []\n}\n\n/**\n * UPDATE_ENTITY activity handler\n *\n * Updates an entity via CommandBus for proper audit logging, undo support, and side effects.\n *\n * Config format:\n * ```json\n * {\n * \"commandId\": \"sales.documents.update\",\n * \"input\": {\n * \"id\": \"{{context.orderId}}\",\n * \"statusEntryId\": \"{{context.approvedStatusId}}\"\n * }\n * }\n * ```\n *\n * Alternative format with statusValue (auto-resolves to statusEntryId):\n * ```json\n * {\n * \"commandId\": \"sales.orders.update\",\n * \"statusDictionary\": \"sales.order_status\",\n * \"input\": {\n * \"id\": \"{{context.orderId}}\",\n * \"statusValue\": \"pending_approval\"\n * }\n * }\n * ```\n *\n * Every `{{...}}` reference in `input` must resolve against the workflow context \u2014\n * an unresolved reference is rejected rather than forwarded to the command bus.\n */\nexport async function executeUpdateEntity(\n em: EntityManager,\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { commandId, input, statusDictionary } = config\n\n if (!commandId) {\n throw new Error('UPDATE_ENTITY requires \"commandId\" field (e.g., \"sales.documents.update\")')\n }\n\n const workflowSafeCommand = getWorkflowSafeCommand(commandId)\n if (!workflowSafeCommand) {\n throw new Error('UPDATE_ENTITY command is not allowed')\n }\n\n if (!input || typeof input !== 'object') {\n throw new Error('UPDATE_ENTITY requires \"input\" object with entity data')\n }\n\n const actorUserId = typeof context.userId === 'string' ? context.userId.trim() : ''\n if (!actorUserId) {\n throw new Error('UPDATE_ENTITY requires an authenticated workflow user')\n }\n\n const authorized = await workflowUserHasAllFeatures(\n container,\n actorUserId,\n workflowSafeCommand.requiredFeatures,\n context.workflowInstance.tenantId,\n context.workflowInstance.organizationId\n )\n if (!authorized) {\n throw new Error('UPDATE_ENTITY command is not authorized')\n }\n\n // Resolve CommandBus from container\n const commandBus = container.resolve('commandBus') as any\n\n if (!commandBus || typeof commandBus.execute !== 'function') {\n throw new Error('CommandBus not available in container')\n }\n\n const unresolvedKeys = findUnresolvedTemplateKeys(input)\n if (unresolvedKeys.length > 0) {\n throw new Error(\n `UPDATE_ENTITY input contains unresolved template variables for: ${unresolvedKeys.join(', ')}. ` +\n `Check that the workflow context provides these keys.`\n )\n }\n\n // Prepare final input, resolving statusValue if provided\n let finalInput = { ...input }\n\n // If statusValue is provided with a statusDictionary, resolve it to statusEntryId\n if (finalInput.statusValue && statusDictionary) {\n const statusEntryId = await resolveDictionaryEntryId(\n em,\n statusDictionary,\n finalInput.statusValue,\n context.workflowInstance.tenantId,\n context.workflowInstance.organizationId\n )\n if (statusEntryId) {\n finalInput.statusEntryId = statusEntryId\n }\n delete finalInput.statusValue\n }\n\n // Build synthetic CommandRuntimeContext for workflow execution\n const ctx = {\n container,\n auth: {\n sub: actorUserId,\n tenantId: context.workflowInstance.tenantId,\n orgId: context.workflowInstance.organizationId,\n isSuperAdmin: false,\n },\n organizationScope: null,\n selectedOrganizationId: context.workflowInstance.organizationId,\n organizationIds: context.workflowInstance.organizationId\n ? [context.workflowInstance.organizationId]\n : null,\n }\n\n // Execute the command\n const { result, logEntry } = await commandBus.execute(commandId, {\n input: finalInput,\n ctx,\n })\n\n return {\n executed: true,\n commandId,\n result,\n logEntryId: logEntry?.id,\n }\n}\n\n/**\n * Helper to resolve dictionary entry ID by value\n */\nasync function resolveDictionaryEntryId(\n em: EntityManager,\n dictionaryKey: string,\n value: string,\n tenantId: string,\n organizationId: string\n): Promise<string | null> {\n try {\n // Import here to avoid circular dependencies\n const { Dictionary, DictionaryEntry } = await import('@open-mercato/core/modules/dictionaries/data/entities')\n\n // Find the dictionary\n const dictionary = await em.findOne(Dictionary, {\n key: dictionaryKey,\n tenantId,\n organizationId,\n deletedAt: null,\n })\n\n if (!dictionary) {\n logger.warn('Dictionary not found', { component: 'UPDATE_ENTITY', dictionaryKey })\n return null\n }\n\n // Find the entry by normalized value\n const normalizedValue = value.toLowerCase().trim()\n const entry = await em.findOne(DictionaryEntry, {\n dictionary: dictionary.id,\n tenantId,\n organizationId,\n normalizedValue,\n })\n\n if (!entry) {\n logger.warn('Dictionary entry not found', { component: 'UPDATE_ENTITY', dictionaryKey, value })\n return null\n }\n\n return entry.id\n } catch (error) {\n logger.error('Error resolving dictionary entry', { component: 'UPDATE_ENTITY', err: error })\n return null\n }\n}\n\n/**\n * CALL_WEBHOOK activity handler\n *\n * Makes HTTP request to an external URL. Applies shared SSRF guard\n * (protocol / credentials / blocked host / private IP literal / DNS rebinding)\n * before issuing the request and rejects any 3xx redirect rather than following.\n */\nexport type CallWebhookDeps = {\n lookupHost?: HostLookup\n allowPrivate?: boolean\n fetchImpl?: typeof fetch\n signal?: AbortSignal\n}\n\nexport async function executeCallWebhook(\n config: unknown,\n context: ActivityContext,\n deps: CallWebhookDeps = {}\n): Promise<any> {\n const parsed = callWebhookConfigSchema.safeParse(config)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => `${issue.path.join('.') || 'config'}: ${issue.message}`)\n .join('; ')\n throw new Error(`CALL_WEBHOOK config invalid: ${issues}`)\n }\n const { url, method, headers: rawHeaders, body } = parsed.data\n const headers = rawHeaders ?? {}\n\n const allowPrivate = deps.allowPrivate ?? isAllowPrivateWorkflowWebhookUrlsEnabled()\n\n let response: Response\n try {\n response = await safeOutboundFetch(\n url,\n {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body !== undefined && body !== null ? JSON.stringify(body) : undefined,\n redirect: 'manual',\n signal: deps.signal,\n },\n {\n subject: 'Workflow webhook URL',\n allowPrivate,\n lookupHost: deps.lookupHost,\n fetchImpl: deps.fetchImpl,\n },\n )\n } catch (error) {\n if (error instanceof UnsafeOutboundUrlError) {\n throw new Error(\n `CALL_WEBHOOK rejected unsafe URL (reason=${error.reason}): ${error.message}`\n )\n }\n throw error\n }\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get('location')\n throw new Error(\n `CALL_WEBHOOK refused to follow redirect ${response.status} to ${\n location ?? '(no Location header)'\n }`\n )\n }\n\n // Parse response\n let result: any\n const contentType = response.headers.get('content-type')\n\n if (contentType && contentType.includes('application/json')) {\n result = await response.json()\n } else {\n result = await response.text()\n }\n\n // Check for HTTP errors\n if (!response.ok) {\n throw new Error(\n `Webhook request failed with status ${response.status}: ${JSON.stringify(result)}`\n )\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n result,\n }\n}\n\n/**\n * EXECUTE_FUNCTION activity handler\n *\n * Calls a registered function from DI container\n */\nexport async function executeFunction(\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { functionName, args = {} } = config\n\n if (!functionName) {\n throw new Error('EXECUTE_FUNCTION requires \"functionName\" field')\n }\n\n // Look up function in container\n const fnKey = `workflowFunction:${functionName}`\n\n try {\n const fn = container.resolve(fnKey)\n\n if (typeof fn !== 'function') {\n throw new Error(`Registered workflow function \"${functionName}\" is not a function`)\n }\n\n // Call function with args and context\n const result = await fn(args, context)\n\n return { executed: true, functionName, result }\n } catch (error) {\n if (error instanceof Error && error.message.includes('not registered')) {\n throw new Error(\n `Workflow function \"${functionName}\" not registered in DI container (key: ${fnKey})`\n )\n }\n throw error\n }\n}\n\n/**\n * Calculate delay in milliseconds from a WAIT activity config.\n * Supports either `duration` (relative, e.g. \"PT5M\") or `until` (absolute ISO 8601 datetime).\n */\nfunction calculateWaitDelayMs(config: { duration?: string; until?: string }): number {\n if (config.until) {\n const targetDate = new Date(config.until)\n if (isNaN(targetDate.getTime())) {\n throw new Error(`WAIT activity: invalid \"until\" datetime: ${config.until}`)\n }\n const delayMs = targetDate.getTime() - Date.now()\n return Math.max(0, delayMs)\n }\n\n if (config.duration) {\n return parseDuration(config.duration)\n }\n\n throw new Error('WAIT activity requires \"duration\" (e.g., \"PT5M\", \"1h\") or \"until\" (ISO 8601 datetime)')\n}\n\n/**\n * WAIT activity handler\n *\n * Delays workflow execution for a configured duration or until a specific datetime.\n * - `duration`: relative delay (e.g. \"PT5M\", \"1h\", \"30s\")\n * - `until`: absolute datetime (e.g. \"2026-04-15T10:00:00Z\")\n * - Sync mode: blocks via sleep (suitable for short delays)\n * - Async mode: delay is handled by the queue's delayMs option;\n * this handler returns immediately when called from the worker\n */\nasync function executeWait(config: any): Promise<any> {\n const durationMs = calculateWaitDelayMs(config)\n\n // In sync mode, actually sleep for the duration\n // In async mode (called from worker), the delay already happened via queue scheduling\n await sleep(durationMs)\n\n return { waited: true, durationMs }\n}\n\n/**\n * CALL_API activity handler\n *\n * Makes authenticated HTTP request to internal Open Mercato APIs\n * - Automatically creates one-time API key for authentication\n * - Injects tenant/organization context headers\n * - Validates URL security (SSRF prevention)\n * - Classifies errors (retriable vs non-retriable)\n * - Deletes API key after request (no stored credentials!)\n */\nexport async function executeCallApi(\n em: EntityManager,\n config: any,\n context: ActivityContext,\n container: AwilixContainer,\n signal?: AbortSignal\n): Promise<any> {\n // 1. Interpolate variables in config (including {{workflow.*}}, {{context.*}}, allowlisted {{env.*}}, {{now}})\n const interpolatedConfig = interpolateVariables(config, context.workflowContext, context.workflowInstance)\n\n const {\n endpoint,\n method = 'GET',\n headers = {},\n body,\n validateTenantMatch = true,\n } = interpolatedConfig\n\n\n if (!endpoint) {\n throw new Error('CALL_API requires \"endpoint\" field')\n }\n\n // 2. Build full URL (prepend APP_URL for relative paths)\n const fullUrl = buildApiUrl(endpoint)\n\n // 3. Import the one-time API key helper\n const { withOnetimeApiKey } = await import('../../api_keys/services/apiKeyService')\n\n // 4. Create the one-time API key on an EntityManager that is fully detached\n // from the surrounding request/transaction context.\n //\n // CALL_API runs inside `workflowExecutor.executeWorkflow()`, which wraps\n // the whole execution in `em.transactional(...)`. The request EM is forked\n // with `useContext: true`, so while that transaction is open, EVERY\n // operation on the container's `em` \u2014 including this API key's\n // persist/flush \u2014 is transparently redirected to the uncommitted\n // transaction fork (MikroORM `getContext()` \u2192 `TransactionContext`). The\n // key would therefore stay invisible until the transaction commits, but\n // the commit cannot happen until this activity returns. The outbound\n // self-authenticated `fetch` below opens a SEPARATE DB connection that\n // cannot see the uncommitted row, so the internal API responds `401` and\n // the activity fails (issue #4202).\n //\n // Forking with `useContext: false` (matching the query_index/webhooks\n // isolated-EM convention) gives the key its own pooled connection with\n // autocommit, so it is committed and visible to the internal request\n // immediately.\n const apiKeyEm = container\n .resolve<PostgreSqlEntityManager>('em')\n .fork({ clear: true, freshEventManager: true, useContext: false }) as PostgreSqlEntityManager\n\n // 5. Resolve the roles that the one-time API key will inherit.\n //\n // SECURITY: The key must never exceed the permissions of the human who\n // triggered (or authored) this workflow. Previously this code looked up\n // a role named \"admin\"/\"superadmin\" for the tenant and assigned it to\n // the key \u2014 which allowed any non-admin workflow author with\n // `workflows.definitions.edit` + `workflows.instances.create` to issue\n // arbitrary administrative API calls via a CALL_API activity. See the\n // SECURITY.md changelog entry for this fix.\n //\n // The resolution strategy is:\n // 1. Use the workflow instance's `metadata.initiatedBy` user (whoever\n // manually started the instance), when available. Only this user's\n // current active roles are used \u2014 we never fall back to the author\n // when the initiator is known, because that would escalate the\n // initiator's privileges.\n // 2. Fall back to the workflow definition's `createdBy` (author) only\n // when the instance was started by an event trigger with no user.\n // 3. If no traceable principal exists, the activity refuses to run \u2014\n // there is no \"system\" fallback that bypasses RBAC.\n const resolvedRoleIds = await resolveCallApiRoleIds(apiKeyEm, context.workflowInstance)\n\n if (resolvedRoleIds.length === 0) {\n throw new Error(\n `[CALL_API] Refusing to execute CALL_API for workflow instance ${context.workflowInstance.id}: ` +\n `no traceable user roles could be resolved from the workflow instance or definition. ` +\n `CALL_API activities must run under the identity of the user who triggered them.`\n )\n }\n\n // 6. Execute request with one-time API key scoped to the resolved user's roles\n return await withOnetimeApiKey(\n apiKeyEm,\n {\n name: `__workflow_${context.workflowInstance.id}__`,\n description: `One-time key for workflow ${context.workflowInstance.workflowId} instance ${context.workflowInstance.id}`,\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n roles: resolvedRoleIds,\n expiresAt: null,\n },\n async (apiKeySecret) => {\n // Build request headers (auth + context + custom)\n const requestHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `apikey ${apiKeySecret}`,\n 'X-Tenant-Id': context.workflowInstance.tenantId,\n 'X-Organization-Id': context.workflowInstance.organizationId,\n 'X-Workflow-Instance-Id': context.workflowInstance.id,\n ...headers,\n }\n\n // Make HTTP request\n const response = await fetch(fullUrl, {\n method,\n headers: requestHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal,\n })\n\n // Parse response body (JSON-safe)\n let responseBody: any\n const contentType = response.headers.get('content-type')\n\n try {\n if (contentType && contentType.includes('application/json')) {\n responseBody = await response.json()\n } else {\n responseBody = await response.text()\n }\n } catch (error) {\n responseBody = null\n }\n\n // Check for HTTP errors and classify\n if (!response.ok) {\n classifyAndThrowError(response.status, responseBody, fullUrl)\n }\n\n // Validate tenant match (security check)\n if (validateTenantMatch && responseBody && typeof responseBody === 'object') {\n if (responseBody.tenantId && responseBody.tenantId !== context.workflowInstance.tenantId) {\n throw new Error(\n `Tenant ID mismatch: workflow expects ${context.workflowInstance.tenantId} but API returned ${responseBody.tenantId}`\n )\n }\n }\n\n // Return structured result\n return {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n body: responseBody,\n authenticated: true,\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n }\n }\n )\n}\n\n// ============================================================================\n// CALL_API Helper Functions\n// ============================================================================\n\nexport type CallApiInstanceLike = {\n id: string\n tenantId: string\n organizationId: string\n definitionId: string\n metadata?: { initiatedBy?: string | null } | null\n}\n\nasync function resolveActiveRoleIdsForUser(\n em: any,\n userId: string,\n scope: { tenantId: string; organizationId: string },\n): Promise<string[]> {\n const { findOneWithDecryption, findWithDecryption } = await import('@open-mercato/shared/lib/encryption/find')\n const { User, UserRole, Role } = await import('../../auth/data/entities')\n\n const user = await findOneWithDecryption(em, User, {\n id: userId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, {}, scope)\n if (!user) return []\n\n const userRoles = await findWithDecryption(\n em,\n UserRole,\n { user: user.id, deletedAt: null },\n { populate: ['role'] },\n scope,\n )\n const roleIds = userRoles\n .map((ur: any) => (typeof ur.role === 'string' ? ur.role : ur.role?.id))\n .filter((id: unknown): id is string => typeof id === 'string' && id.length > 0)\n\n if (roleIds.length === 0) return []\n\n const scopedRoles = await findWithDecryption(em, Role, {\n id: { $in: roleIds },\n tenantId: scope.tenantId,\n deletedAt: null,\n }, {}, scope)\n return scopedRoles.map((r: any) => r.id as string)\n}\n\nexport async function resolveCallApiRoleIds(\n em: any,\n instance: CallApiInstanceLike\n): Promise<string[]> {\n if (!instance.definitionId) return []\n\n const { findOneWithDecryption } = await import('@open-mercato/shared/lib/encryption/find')\n const { WorkflowDefinition } = await import('../data/entities')\n\n const scope = { tenantId: instance.tenantId, organizationId: instance.organizationId }\n\n // 1. Prefer the triggering user (whoever manually started this instance).\n // WorkflowInstance.metadata.initiatedBy is the canonical record of that\n // principal for user-started instances; use their current role set so\n // CALL_API never exceeds the initiator's permissions. Refuse if the\n // initiator has no active scoped roles \u2014 do not fall back to the\n // definition author, which would escalate the initiator's privileges.\n const initiatorUserId = instance.metadata?.initiatedBy ?? null\n if (initiatorUserId) {\n return resolveActiveRoleIdsForUser(em, initiatorUserId, scope)\n }\n\n // 2. Event-triggered instance with no human initiator: fall back to the\n // definition author. Soft-deleted definitions must not mint keys.\n const definition = await findOneWithDecryption(em, WorkflowDefinition, {\n id: instance.definitionId,\n tenantId: instance.tenantId,\n deletedAt: null,\n }, {}, scope)\n const authorUserId = definition?.createdBy\n if (!authorUserId) return []\n\n return resolveActiveRoleIdsForUser(em, authorUserId, scope)\n}\n\n/**\n * Build full API URL from endpoint\n * - Relative paths (/api/...) \u2192 prepend APP_URL\n * - Absolute URLs \u2192 validate domain matches APP_URL (SSRF prevention)\n */\nfunction buildApiUrl(endpoint: string): string {\n const appUrl = process.env.APP_URL || 'http://localhost:3000'\n\n // Relative path - prepend APP_URL\n if (endpoint.startsWith('/')) {\n // Security: Only allow /api/* paths\n if (!endpoint.startsWith('/api/')) {\n throw new Error(`CALL_API only supports /api/* paths, got: ${endpoint}`)\n }\n return `${appUrl}${endpoint}`\n }\n\n // Absolute URL - validate domain matches APP_URL (SSRF prevention)\n try {\n const endpointUrl = new URL(endpoint)\n const appUrlObj = new URL(appUrl)\n\n if (endpointUrl.host !== appUrlObj.host) {\n throw new Error(\n `SSRF Prevention: CALL_API endpoint domain (${endpointUrl.host}) does not match APP_URL (${appUrlObj.host})`\n )\n }\n\n return endpoint\n } catch (error) {\n if (error instanceof TypeError) {\n throw new Error(`Invalid endpoint URL: ${endpoint}`)\n }\n throw error\n }\n}\n\n/**\n * Classify HTTP error and throw appropriate error\n * - 400-499: Non-retriable (client error - validation/auth)\n * - 500-599: Retriable (server error)\n */\nfunction classifyAndThrowError(status: number, body: any, url: string): never {\n const bodyStr = typeof body === 'string' ? body : JSON.stringify(body)\n\n if (status >= 400 && status < 500) {\n // Client errors - non-retriable\n throw new Error(\n `CALL_API request failed with status ${status} (non-retriable): ${bodyStr}`\n )\n }\n\n if (status >= 500) {\n // Server errors - retriable\n const error: any = new Error(\n `CALL_API request failed with status ${status} (retriable): ${bodyStr}`\n )\n error.retriable = true\n throw error\n }\n\n // Other errors\n throw new Error(`CALL_API request failed with status ${status}: ${bodyStr}`)\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Interpolate variables in config from workflow context\n *\n * Supports syntax:\n * - {{context.field}} or {{context.nested.field}} - from workflow context\n * - {{workflow.instanceId}} - workflow instance ID\n * - {{workflow.tenantId}} - tenant ID\n * - {{workflow.organizationId}} - organization ID\n * - {{workflow.currentStepId}} - current step ID\n * - {{env.VAR_NAME}} - server-allowlisted environment variables\n * - {{now}} - current ISO timestamp\n */\nfunction interpolateVariables(\n config: any,\n context: Record<string, any>,\n workflowInstance?: WorkflowInstance\n): any {\n if (typeof config === 'string') {\n // Check if this is a single variable reference (e.g., \"{{context.cart.items}}\")\n // This preserves the original type (array, object, number, boolean)\n const singleVarMatch = config.match(/^\\{\\{([^}]+)\\}\\}$/)\n\n if (singleVarMatch) {\n const trimmedPath = singleVarMatch[1].trim()\n\n // Handle {{workflow.*}} variables\n if (trimmedPath.startsWith('workflow.') && workflowInstance) {\n const workflowKey = trimmedPath.substring('workflow.'.length)\n switch (workflowKey) {\n case 'instanceId':\n return workflowInstance.id\n case 'tenantId':\n return workflowInstance.tenantId\n case 'organizationId':\n return workflowInstance.organizationId\n case 'currentStepId':\n return workflowInstance.currentStepId\n case 'workflowId':\n return workflowInstance.workflowId\n case 'version':\n return workflowInstance.version // Return as number\n default:\n return config // Return original if unknown\n }\n }\n\n // Handle {{env.*}} variables\n if (trimmedPath.startsWith('env.')) {\n const envKey = trimmedPath.substring('env.'.length)\n return resolveWorkflowEnvInterpolation(envKey)\n }\n\n // Handle {{now}} - current timestamp\n if (trimmedPath === 'now') {\n return new Date().toISOString()\n }\n\n // Handle {{context.*}} variables (default behavior)\n const contextPath = trimmedPath.startsWith('context.')\n ? trimmedPath.substring('context.'.length)\n : trimmedPath\n\n const value = getNestedValue(context, contextPath)\n return value !== undefined ? value : config // Return raw value to preserve type\n }\n\n // Multiple interpolations or mixed text - return string\n return config.replace(/\\{\\{([^}]+)\\}\\}/g, (match, path) => {\n const trimmedPath = path.trim()\n\n // Handle {{workflow.*}} variables\n if (trimmedPath.startsWith('workflow.') && workflowInstance) {\n const workflowKey = trimmedPath.substring('workflow.'.length)\n switch (workflowKey) {\n case 'instanceId':\n return workflowInstance.id\n case 'tenantId':\n return workflowInstance.tenantId\n case 'organizationId':\n return workflowInstance.organizationId\n case 'currentStepId':\n return workflowInstance.currentStepId\n case 'workflowId':\n return workflowInstance.workflowId\n case 'version':\n return String(workflowInstance.version)\n default:\n return match // Unknown workflow key\n }\n }\n\n // Handle {{env.*}} variables\n if (trimmedPath.startsWith('env.')) {\n const envKey = trimmedPath.substring('env.'.length)\n return resolveWorkflowEnvInterpolation(envKey)\n }\n\n // Handle {{now}} - current timestamp\n if (trimmedPath === 'now') {\n return new Date().toISOString()\n }\n\n // Handle {{context.*}} variables (default behavior)\n const contextPath = trimmedPath.startsWith('context.')\n ? trimmedPath.substring('context.'.length)\n : trimmedPath\n\n const value = getNestedValue(context, contextPath)\n return value !== undefined ? String(value) : match\n })\n }\n\n if (Array.isArray(config)) {\n return config.map((item) => interpolateVariables(item, context, workflowInstance))\n }\n\n if (config && typeof config === 'object') {\n const result: Record<string, any> = {}\n for (const [key, value] of Object.entries(config)) {\n result[key] = interpolateVariables(value, context, workflowInstance)\n }\n return result\n }\n\n return config\n}\n\n/**\n * Get nested value from object by path (e.g., \"user.email\")\n */\nfunction getNestedValue(obj: any, path: string): any {\n const parts = path.split('.')\n let value = obj\n\n for (const part of parts) {\n if (value && typeof value === 'object' && part in value) {\n value = value[part]\n } else {\n return undefined\n }\n }\n\n return value\n}\n\n/**\n * Calculate exponential backoff delay\n */\nfunction calculateBackoff(\n initialIntervalMs: number,\n backoffCoefficient: number,\n attempt: number,\n maxIntervalMs: number\n): number {\n const backoff = initialIntervalMs * Math.pow(backoffCoefficient, attempt)\n return Math.min(backoff, maxIntervalMs || Infinity)\n}\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Execute a promise with timeout\n *\n * Only CALL_API and CALL_WEBHOOK honour the abort signal today \u2014 they forward\n * it to `fetch`. SEND_EMAIL, EMIT_EVENT, UPDATE_ENTITY and EXECUTE_FUNCTION\n * still run to completion after the timeout has been recorded. Tracked in\n * #5148.\n */\nasync function executeWithTimeout<T>(\n executor: (signal: AbortSignal) => Promise<T>,\n timeoutMs: number\n): Promise<T> {\n let timeoutId: NodeJS.Timeout\n const abortController = new AbortController()\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n abortController.abort()\n reject(new Error(`Activity execution timeout after ${timeoutMs}ms`))\n }, timeoutMs)\n })\n\n try {\n return await Promise.race([executor(abortController.signal), timeoutPromise])\n } finally {\n clearTimeout(timeoutId!)\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["/**\n * Workflows Module - Activity Executor Service\n *\n * Executes workflow activities (send email, call API, emit events, etc.)\n * - Supports multiple activity types\n * - Implements retry logic with exponential backoff\n * - Handles timeouts\n * - Variable interpolation from workflow context\n *\n * Functional API (no classes) following Open Mercato conventions.\n */\n\nimport { EntityManager } from '@mikro-orm/core'\nimport type { EntityManager as PostgreSqlEntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport { WorkflowInstance } from '../data/entities'\nimport { createModuleQueue, Queue } from '@open-mercato/queue'\nimport { getRedisUrl } from '@open-mercato/shared/lib/redis/connection'\nimport {\n safeOutboundFetch,\n UnsafeOutboundUrlError,\n type HostLookup,\n} from '@open-mercato/shared/lib/url-safety'\nimport { parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'\nimport { isPrivateCrossProcessBroadcastEvent } from '@open-mercato/shared/modules/events'\nimport { hasAllFeatures } from '@open-mercato/shared/security/features'\nimport {\n definitionDeclaresGrant,\n resolveWorkflowDefinitionExecutionUserId,\n} from './definition-grant'\nimport {\n callWebhookConfigSchema,\n invokeAgentConfigSchema,\n setVariableConfigSchema,\n} from '../data/activity-config-schemas'\nimport {\n buildSetVariableContextPatch,\n isSetVariableOutput,\n splitAssignmentPath,\n type SetVariableOutput,\n} from './set-variable'\nimport {\n DRY_RUN_EVENT_TYPES,\n WorkflowDryRunRefusalError,\n isDryRunInstance,\n isDryRunRefusal,\n} from './dry-run'\nimport {\n applyTransforms,\n parseInterpolationToken,\n type WorkflowInterpolationMode,\n} from './interpolation-pipeline'\n\nexport { resolveDefinitionInterpolationMode, type WorkflowInterpolationMode } from './interpolation-pipeline'\nimport {\n WorkflowActivityJob,\n WorkflowActivityJobInvokeAgent,\n WORKFLOW_ACTIVITIES_QUEUE_NAME,\n WORKFLOW_INVOKE_AGENT_QUEUE_NAME,\n} from './activity-queue-types'\nimport './activity-registry-bootstrap'\nimport { bindActivityExecutor } from './activity-types'\nimport { getActivityType } from './activity-registry'\nimport { logWorkflowEvent } from './event-logger'\nimport { calculateWaitDelayMs, parseDuration } from './duration'\n\nexport { calculateWaitDelayMs } from './duration'\nimport { resolveActivityTimeoutMs } from './activityTimeoutFields'\nimport { getWorkflowSafeCommand } from './workflow-safe-commands'\nimport { isWorkflowCommandEnabled } from './workflow-command-enablement'\nimport { resolveWorkflowCommandPolicyForContainer } from './workflow-command-settings'\nimport { resolveAgentReview, toAgentDispositionReview } from './agent-review'\nimport type { AgentDispositionReview } from './agent-disposition-task'\n\nexport { isPrivateUrl } from '@open-mercato/shared/lib/network'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('workflows')\n\nfunction isAllowPrivateWorkflowWebhookUrlsEnabled(): boolean {\n if (parseBooleanWithDefault(process.env.OM_WORKFLOWS_ALLOW_PRIVATE_URLS, false)) {\n if (process.env.NODE_ENV === 'production') {\n logger.warn('OM_WORKFLOWS_ALLOW_PRIVATE_URLS is set but ignored in production. SSRF protection remains enabled.', { component: 'CALL_WEBHOOK' })\n return false\n }\n\n logger.warn('OM_WORKFLOWS_ALLOW_PRIVATE_URLS is enabled. SSRF protection is bypassed for workflow webhooks; use only in development.', { component: 'CALL_WEBHOOK' })\n return true\n }\n\n if (parseBooleanWithDefault(process.env.WORKFLOW_WEBHOOK_ALLOW_PRIVATE_URLS, false)) {\n if (process.env.NODE_ENV === 'production') {\n logger.warn('WORKFLOW_WEBHOOK_ALLOW_PRIVATE_URLS is deprecated and ignored in production. Use OM_WORKFLOWS_ALLOW_PRIVATE_URLS for development only. SSRF protection remains enabled.', { component: 'CALL_WEBHOOK' })\n return false\n }\n\n logger.warn('WORKFLOW_WEBHOOK_ALLOW_PRIVATE_URLS is deprecated. Use OM_WORKFLOWS_ALLOW_PRIVATE_URLS instead. SSRF protection is bypassed.', { component: 'CALL_WEBHOOK' })\n return true\n }\n\n return false\n}\n\nconst DEFAULT_WORKFLOW_ENV_INTERPOLATION_ALLOWLIST = new Set(['APP_URL'])\nconst WORKFLOW_ENV_INTERPOLATION_ALLOWLIST_KEY = 'OM_WORKFLOWS_ENV_INTERPOLATION_ALLOWLIST'\n\nfunction getWorkflowEnvInterpolationAllowlist(): Set<string> {\n const allowlist = new Set(DEFAULT_WORKFLOW_ENV_INTERPOLATION_ALLOWLIST)\n const configuredKeys = process.env[WORKFLOW_ENV_INTERPOLATION_ALLOWLIST_KEY]\n if (!configuredKeys) {\n return allowlist\n }\n\n for (const key of configuredKeys.split(',')) {\n const trimmedKey = key.trim()\n if (trimmedKey) {\n allowlist.add(trimmedKey)\n }\n }\n\n return allowlist\n}\n\n// ============================================================================\n// Types and Interfaces\n// ============================================================================\n\nexport type ActivityType =\n | 'SEND_EMAIL'\n | 'CALL_API'\n | 'EMIT_EVENT'\n | 'UPDATE_ENTITY'\n | 'CALL_WEBHOOK'\n | 'EXECUTE_FUNCTION'\n | 'WAIT'\n | 'SET_VARIABLE'\n | 'INVOKE_AGENT'\n\n/**\n * Signal name the INVOKE_AGENT step parks on when a proposal is routed to a\n * human. agent_orchestrator's proposal-dispose path emits\n * `agent_orchestrator.proposal.ready` and calls workflows `sendSignal` with this\n * name to resume the parked step.\n */\nexport const INVOKE_AGENT_SIGNAL_NAME = 'agent_orchestrator.proposal.ready'\n\n/**\n * Signal name a parked SUB_WORKFLOW step resumes on once its child instance\n * reaches a terminal state. `completeWorkflow` enqueues a resume job when the\n * child carries a parent linkage; the worker resumes the parent step via\n * `sendSignal` with this name.\n */\nexport const SUB_WORKFLOW_SIGNAL_NAME = 'workflows.sub_workflow.completed'\n\n/**\n * Small enqueue delay for the INVOKE_AGENT job so the workflow transaction that\n * parked the step commits before the worker picks the job up. The worker also\n * guards against the race (it requires the instance to be PAUSED at the step\n * before running the agent), so this only trims needless retries.\n */\nexport const INVOKE_AGENT_ENQUEUE_DELAY_MS = 1000\n\n/**\n * Marker carried on an activity result's output when the step must park and wait\n * for a signal (INVOKE_AGENT routed a proposal to a human). The step handler\n * inspects activity outputs for this marker and parks the instance accordingly.\n * researcher / auto_approved outcomes do NOT carry it and proceed inline.\n */\nexport type ActivityParkMarker = { signalName: string }\n\nexport function getActivityParkMarker(output: unknown): ActivityParkMarker | null {\n if (output && typeof output === 'object' && '__park' in output) {\n const park = (output as { __park?: unknown }).__park\n if (park && typeof park === 'object' && typeof (park as { signalName?: unknown }).signalName === 'string') {\n return { signalName: (park as { signalName: string }).signalName }\n }\n }\n return null\n}\n\nexport interface ActivityDefinition {\n activityId: string // Unique identifier for activity\n activityName?: string // Optional, for debugging/logging\n activityType: ActivityType\n config: any\n async?: boolean // Flag to execute activity asynchronously via queue\n retryPolicy?: RetryPolicy\n timeoutMs?: number\n /**\n * @deprecated Use `timeoutMs`. Legacy ISO 8601 duration string accepted by\n * the definition schema before #4424; normalized by `resolveActivityTimeoutMs`.\n */\n timeout?: string\n compensate?: boolean // Flag to execute compensation on failure\n}\n\nexport { resolveActivityTimeoutMs }\n\nexport interface RetryPolicy {\n maxAttempts: number\n initialIntervalMs: number\n backoffCoefficient: number\n maxIntervalMs: number\n}\n\nexport interface ActivityContext {\n workflowInstance: WorkflowInstance\n workflowContext: Record<string, any>\n stepContext?: Record<string, any>\n stepInstanceId?: string\n // Set when the activity runs inside a parallel branch; carried on the queue\n // payload so async resume targets the branch rather than the instance.\n branchInstanceId?: string | null\n transitionId?: string\n userId?: string\n // The owning definition's `interpolation` mode; absent means lenient.\n // Async activities enforce strict mode at enqueue-time, so the worker-side\n // context deliberately leaves this unset.\n interpolationMode?: WorkflowInterpolationMode\n}\n\ntype RbacFeatureResolver = {\n userHasAllFeatures: (\n userId: string,\n required: string[],\n opts: { tenantId: string | null; organizationId: string | null }\n ) => Promise<boolean>\n}\n\nasync function workflowUserHasAllFeatures(\n container: AwilixContainer,\n userId: string,\n required: readonly string[],\n tenantId: string | null,\n organizationId: string | null\n): Promise<boolean> {\n try {\n const rbac = container.resolve('rbacService') as RbacFeatureResolver | undefined\n if (rbac?.userHasAllFeatures) {\n return await rbac.userHasAllFeatures(userId, [...required], { tenantId, organizationId })\n }\n } catch {\n // Fail closed below when the workflow executor cannot prove the actor's grants.\n }\n return false\n}\n\nexport interface ActivityExecutionResult {\n activityId: string\n activityName?: string\n activityType: ActivityType\n success: boolean\n output?: any\n error?: string\n retryCount: number\n executionTimeMs: number\n async?: boolean // Marks activity as async (queued)\n jobId?: string // Queue job ID for async activities\n /**\n * The activity was not attempted because a dry run cannot simulate its type\n * (spec section 8.2). Callers MUST treat it as a stop, never as a failure:\n * error routes and error directives describe what to do when an effector\n * fails, and no effector ran.\n */\n dryRunRefused?: boolean\n}\n\nexport class ActivityExecutionError extends Error {\n constructor(\n message: string,\n public activityType: ActivityType,\n public activityName?: string,\n public details?: any\n ) {\n super(message)\n this.name = 'ActivityExecutionError'\n }\n}\n\n/**\n * Thrown by `interpolateVariables` in strict mode when a token cannot be\n * resolved (unresolved context path, env-allowlist miss, unknown workflow.*\n * key, failed or unparseable transform pipeline). Activity call sites rethrow\n * it as `ActivityExecutionError` so it flows through the normal retry/failure\n * machinery.\n */\nexport class WorkflowInterpolationError extends Error {\n constructor(\n message: string,\n public token: string\n ) {\n super(message)\n this.name = 'WorkflowInterpolationError'\n }\n}\n\n// ============================================================================\n// Queue Integration for Async Activities\n// ============================================================================\n\nlet activityQueue: Queue<WorkflowActivityJob> | null = null\nlet invokeAgentQueue: Queue<WorkflowActivityJob> | null = null\n\n/**\n * Get or create the activity queue (lazy initialization)\n */\nfunction getActivityQueue(): Queue<WorkflowActivityJob> {\n if (!activityQueue) {\n activityQueue = createModuleQueue<WorkflowActivityJob>(\n WORKFLOW_ACTIVITIES_QUEUE_NAME,\n { concurrency: parseInt(process.env.WORKFLOW_WORKER_CONCURRENCY || '5') },\n )\n }\n\n return activityQueue\n}\n\n/**\n * Get or create the dedicated invoke-agent queue (lazy initialization).\n *\n * Minute-long agent runs get their own queue so they never starve the fast\n * activities sharing 'workflow-activities'. Consumer-side concurrency is\n * governed by the workflow-invoke-agent worker's metadata.\n */\nfunction getInvokeAgentQueue(): Queue<WorkflowActivityJob> {\n if (!invokeAgentQueue) {\n invokeAgentQueue = createModuleQueue<WorkflowActivityJob>(\n WORKFLOW_INVOKE_AGENT_QUEUE_NAME,\n { concurrency: parseInt(process.env.WORKERS_WORKFLOW_INVOKE_AGENT_CONCURRENCY || '5', 10) },\n )\n }\n\n return invokeAgentQueue\n}\n\n/**\n * Enqueue an activity for background execution\n *\n * @param em - Entity manager\n * @param activity - Activity definition\n * @param context - Execution context\n * @returns Job ID\n */\nexport async function enqueueActivity(\n em: EntityManager,\n activity: ActivityDefinition,\n context: ActivityContext\n): Promise<string> {\n const { workflowInstance, workflowContext, stepContext, transitionId, stepInstanceId, branchInstanceId } =\n context\n\n const registryEntry = getActivityType(activity.activityType)\n if (registryEntry && registryEntry.async.capable === false) {\n throw new ActivityExecutionError(\n `[internal] Activity type ${activity.activityType} cannot run asynchronously (${registryEntry.async.reason})`,\n activity.activityType,\n activity.activityName\n )\n }\n\n // Interpolate config variables NOW (before queuing) \u2014 strict mode is\n // enforced here, at enqueue-time, before the job serializes frozen config.\n const interpolatedConfig = interpolateActivityConfig(\n activity.config,\n context,\n activity.activityType,\n activity.activityName\n )\n\n // Create job payload\n const job: WorkflowActivityJob = {\n workflowInstanceId: workflowInstance.id,\n stepInstanceId,\n branchInstanceId: branchInstanceId ?? undefined,\n transitionId,\n activityId: activity.activityId,\n activityName: activity.activityName || activity.activityType,\n activityType: activity.activityType,\n activityConfig: interpolatedConfig,\n workflowContext,\n stepContext,\n retryPolicy: activity.retryPolicy,\n timeoutMs: activity.timeoutMs,\n tenantId: workflowInstance.tenantId,\n organizationId: workflowInstance.organizationId,\n userId: context.userId,\n }\n\n // Enqueue to queue (entries with enqueueDelayMs, e.g. WAIT, use delayMs for the actual delay)\n const queue = getActivityQueue()\n const registryDelayMs = registryEntry?.enqueueDelayMs\n ? registryEntry.enqueueDelayMs(interpolatedConfig)\n : null\n const enqueueOptions = registryDelayMs !== null ? { delayMs: registryDelayMs } : undefined\n const jobId = await queue.enqueue(job, enqueueOptions)\n\n // Log event\n await logWorkflowEvent(em, {\n workflowInstanceId: workflowInstance.id,\n stepInstanceId,\n eventType: 'ACTIVITY_QUEUED',\n eventData: {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n async: true,\n jobId,\n },\n tenantId: workflowInstance.tenantId,\n organizationId: workflowInstance.organizationId,\n })\n\n return jobId\n}\n\n/**\n * Enqueue a delayed timer job for a WAIT_FOR_TIMER step.\n *\n * The activity worker handles `kind: 'timer'` jobs by calling\n * `timerHandler.fireTimer`, which resumes the paused workflow instance.\n */\nexport async function enqueueTimerJob(params: {\n workflowInstanceId: string\n stepInstanceId: string\n branchInstanceId?: string | null\n tenantId: string\n organizationId: string\n userId?: string\n fireAt: string\n delayMs: number\n}): Promise<string> {\n const { workflowInstanceId, stepInstanceId, branchInstanceId, tenantId, organizationId, userId, fireAt, delayMs } =\n params\n\n const queue = getActivityQueue()\n const jobId = await queue.enqueue(\n {\n kind: 'timer',\n workflowInstanceId,\n stepInstanceId,\n branchInstanceId: branchInstanceId ?? undefined,\n tenantId,\n organizationId,\n userId,\n fireAt,\n },\n { delayMs: delayMs > 0 ? delayMs : undefined }\n )\n\n return jobId\n}\n\n/**\n * Enqueue a delayed SLA job for a USER_TASK (one reminder offset, or the\n * deadline itself).\n *\n * The activity worker handles `kind: 'task_sla'` jobs by calling\n * `taskSla.runTaskSlaJob`. `deadlineAt` is absolute and carried on the payload\n * rather than recomputed at run time, so a queue running behind can never\n * extend the configured deadline \u2014 the same guarantee the WAIT_FOR_CONDITION\n * backstop gives.\n */\nexport async function enqueueTaskSlaJob(params: {\n workflowInstanceId: string\n stepInstanceId: string\n branchInstanceId?: string | null\n userTaskId: string\n phase: 'reminder' | 'breach'\n deadlineAt: string\n fireAt: string\n delayMs: number\n tenantId: string\n organizationId: string\n userId?: string\n}): Promise<string> {\n const {\n workflowInstanceId,\n stepInstanceId,\n branchInstanceId,\n userTaskId,\n phase,\n deadlineAt,\n fireAt,\n delayMs,\n tenantId,\n organizationId,\n userId,\n } = params\n\n const queue = getActivityQueue()\n return await queue.enqueue(\n {\n kind: 'task_sla',\n workflowInstanceId,\n stepInstanceId,\n branchInstanceId: branchInstanceId ?? undefined,\n userTaskId,\n phase,\n deadlineAt,\n fireAt,\n tenantId,\n organizationId,\n userId,\n },\n { delayMs: delayMs > 0 ? delayMs : undefined }\n )\n}\n\n/**\n * Enqueue a delayed poll job for a WAIT_FOR_CONDITION step.\n *\n * The activity worker handles `kind: 'condition'` jobs by calling\n * `conditionHandler.evaluateWaitCondition`. This job is the durability\n * backstop behind the event-driven wake: `deadlineAt` travels unchanged across\n * every re-enqueue so the timeout stays anchored to the original step entry.\n */\nexport async function enqueueConditionCheckJob(params: {\n workflowInstanceId: string\n stepInstanceId: string\n branchInstanceId?: string | null\n tenantId: string\n organizationId: string\n userId?: string\n deadlineAt: string\n attempt: number\n delayMs: number\n}): Promise<string> {\n const {\n workflowInstanceId,\n stepInstanceId,\n branchInstanceId,\n tenantId,\n organizationId,\n userId,\n deadlineAt,\n attempt,\n delayMs,\n } = params\n\n const queue = getActivityQueue()\n const jobId = await queue.enqueue(\n {\n kind: 'condition',\n workflowInstanceId,\n stepInstanceId,\n branchInstanceId: branchInstanceId ?? undefined,\n tenantId,\n organizationId,\n userId,\n deadlineAt,\n attempt,\n },\n { delayMs: delayMs > 0 ? delayMs : undefined }\n )\n\n return jobId\n}\n\n// ============================================================================\n// Main Activity Execution Functions\n// ============================================================================\n\n/**\n * Execute a single activity with retry logic and timeout\n *\n * @param em - Entity manager\n * @param container - DI container\n * @param activity - Activity definition\n * @param context - Execution context\n * @returns Execution result\n */\nexport async function executeActivity(\n em: EntityManager,\n container: AwilixContainer,\n activity: ActivityDefinition,\n context: ActivityContext\n): Promise<ActivityExecutionResult> {\n const retryPolicy = activity.retryPolicy || {\n maxAttempts: 1,\n initialIntervalMs: 0,\n backoffCoefficient: 1,\n maxIntervalMs: 0,\n }\n\n let lastError: any\n let retryCount = 0\n\n for (let attempt = 0; attempt < retryPolicy.maxAttempts; attempt++) {\n try {\n const startTime = Date.now()\n\n // Execute with timeout if specified (timeoutMs, or a legacy ISO 8601\n // `timeout` string normalized to ms \u2014 see resolveActivityTimeoutMs).\n const timeoutMs = resolveActivityTimeoutMs(activity)\n const result = timeoutMs\n ? await executeWithTimeout(\n (signal) => executeActivityByType(em, container, activity, context, signal),\n timeoutMs\n )\n : await executeActivityByType(em, container, activity, context)\n\n const executionTimeMs = Date.now() - startTime\n\n return {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n success: true,\n output: result,\n retryCount: attempt,\n executionTimeMs,\n async: activity.async || false,\n }\n } catch (error) {\n lastError = error\n retryCount = attempt + 1\n\n // A dry-run refusal is not a failure \u2014 nothing was attempted \u2014 so retrying\n // it would only re-log the same refusal N times before reaching the same\n // answer.\n if (isDryRunRefusal(error)) break\n\n // Log activity retry attempt with context\n if (attempt < retryPolicy.maxAttempts - 1) {\n logger.error('Activity failed; will retry', {\n activityId: activity.activityId,\n activityType: activity.activityType,\n attempt: attempt + 1,\n maxAttempts: retryPolicy.maxAttempts,\n instanceId: context.workflowInstance.id,\n err: error,\n })\n }\n\n // If not the last attempt, apply backoff and retry\n if (attempt < retryPolicy.maxAttempts - 1) {\n const backoff = calculateBackoff(\n retryPolicy.initialIntervalMs,\n retryPolicy.backoffCoefficient,\n attempt,\n retryPolicy.maxIntervalMs\n )\n\n await sleep(backoff)\n }\n }\n }\n\n // All retries exhausted\n const errorMessage = lastError instanceof Error ? lastError.message : String(lastError)\n if (isDryRunRefusal(lastError)) {\n return {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n success: false,\n dryRunRefused: true,\n error: `Dry run stopped: activity type ${lastError.activityType} cannot be simulated (${lastError.reason})`,\n retryCount: 0,\n executionTimeMs: 0,\n async: activity.async || false,\n }\n }\n logger.error('Activity failed after all attempts', {\n activityId: activity.activityId,\n activityType: activity.activityType,\n attempts: retryCount,\n instanceId: context.workflowInstance.id,\n err: lastError,\n })\n\n return {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n success: false,\n error: `Activity failed after ${retryCount} attempts: ${errorMessage}`,\n retryCount,\n executionTimeMs: 0,\n async: activity.async || false,\n }\n}\n\n/**\n * Execute multiple activities in sequence\n * Supports both synchronous and asynchronous (queued) execution\n *\n * @param em - Entity manager\n * @param container - DI container\n * @param activities - Array of activity definitions\n * @param context - Execution context\n * @returns Array of execution results\n */\nexport async function executeActivities(\n em: EntityManager,\n container: AwilixContainer,\n activities: ActivityDefinition[],\n context: ActivityContext\n): Promise<ActivityExecutionResult[]> {\n const results: ActivityExecutionResult[] = []\n\n // A dry run never enqueues. The queue job would carry no `isDryRun` of its\n // own, so a worker picking it up would execute the real effector on its own\n // connection \u2014 the isolation would leak out of the request that opted in.\n // Mocks are pure and synchronous, so running them inline loses nothing.\n const forceSynchronous = isDryRunInstance(context.workflowInstance)\n\n for (let i = 0; i < activities.length; i++) {\n const activity = activities[i]\n\n // Check if activity should run async\n if (activity.async && !forceSynchronous) {\n // Enqueue for background execution\n const jobId = await enqueueActivity(em, activity, context)\n\n results.push({\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n success: true, // Queued successfully\n async: true,\n jobId,\n retryCount: 0,\n executionTimeMs: 0,\n })\n } else {\n // Execute synchronously (existing logic)\n const executed = await executeActivity(em, container, activity, context)\n // `executeActivity` echoes the AUTHORED `async` flag, which is what the\n // transition handler reads to decide whether to park the token in\n // WAITING_FOR_ACTIVITIES. A dry run that ran an authored-async activity\n // inline must therefore correct the flag, or the run would park waiting\n // for a queue job that was deliberately never enqueued \u2014 a deadlock, and\n // the step handler would also misclassify a refusal as \"still pending\"\n // instead of a failure.\n const result = forceSynchronous && activity.async\n ? { ...executed, async: false }\n : executed\n results.push(result)\n\n // Stop execution if activity fails (fail-fast)\n if (!result.success) {\n break\n }\n\n // Update workflow context with activity output. SET_VARIABLE outputs\n // land at their assignment paths in top-level context; every other\n // output merges under the activity name/type key.\n if (result.output && typeof result.output === 'object') {\n if (activity.activityType === 'SET_VARIABLE' && isSetVariableOutput(result.output)) {\n context.workflowContext = {\n ...context.workflowContext,\n ...buildSetVariableContextPatch(context.workflowContext, result.output.assignments),\n }\n } else {\n const key = activity.activityName || activity.activityType\n context.workflowContext = {\n ...context.workflowContext,\n [key]: result.output,\n }\n }\n }\n }\n }\n\n return results\n}\n\n// ============================================================================\n// Activity Type Handlers\n// ============================================================================\n\n/**\n * Execute activity based on its type\n */\nasync function executeActivityByType(\n em: EntityManager,\n container: AwilixContainer,\n activity: ActivityDefinition,\n context: ActivityContext,\n signal?: AbortSignal\n): Promise<any> {\n // Interpolate config variables from context (including workflow metadata)\n const interpolatedConfig = interpolateActivityConfig(\n activity.config,\n context,\n activity.activityType,\n activity.activityName\n )\n\n const entry = getActivityType(activity.activityType)\n if (!entry) {\n throw new ActivityExecutionError(\n `Unknown activity type: ${activity.activityType}`,\n activity.activityType,\n activity.activityName\n )\n }\n\n // Dry run (spec section 8.2): the ONE place `entry.execute` is reached, so it\n // is the one place the swap has to happen. Everything side-effecting in the\n // engine ends up here \u2014 the command bus, the event bus, the mailer, the\n // webhook fetch and the agent bridge \u2014 which is what makes \"no effector runs\"\n // a property of a single branch rather than a checklist.\n if (isDryRunInstance(context.workflowInstance)) {\n if (entry.mock === 'refuse' || entry.mock === undefined) {\n const refusal = new WorkflowDryRunRefusalError(\n activity.activityType,\n entry.mock === 'refuse' ? 'refused' : 'noMock',\n activity.activityName,\n )\n await logWorkflowEvent(em, {\n workflowInstanceId: context.workflowInstance.id,\n stepInstanceId: context.stepInstanceId,\n eventType: DRY_RUN_EVENT_TYPES.activityRefused,\n eventData: {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n reason: refusal.reason,\n },\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n })\n throw refusal\n }\n\n const simulated = entry.mock(interpolatedConfig, context)\n await logWorkflowEvent(em, {\n workflowInstanceId: context.workflowInstance.id,\n stepInstanceId: context.stepInstanceId,\n eventType: DRY_RUN_EVENT_TYPES.activitySimulated,\n eventData: {\n activityId: activity.activityId,\n activityName: activity.activityName,\n activityType: activity.activityType,\n output: simulated ?? null,\n },\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n })\n return simulated\n }\n\n // `signal` MUST reach the registry entry: CALL_API / CALL_WEBHOOK thread it\n // into fetch, and without it a per-activity timeout rejects the promise while\n // the HTTP request stays in flight \u2014 the phantom-execution bug from #4918.\n return await entry.execute(interpolatedConfig, context, {\n em: em as PostgreSqlEntityManager,\n container,\n signal,\n })\n}\n\n/**\n * SEND_EMAIL activity handler\n *\n * Sends via the DI-registered emailService when available; without one it\n * reports an honest stub result ({ sent: false, simulated: true, reason: 'no-email-service' }).\n * A real send() failure propagates so the activity retry loop handles it.\n */\nexport async function executeSendEmail(\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { to, subject, template, templateData, body } = config\n\n if (!to || !subject) {\n throw new Error('SEND_EMAIL requires \"to\" and \"subject\" fields')\n }\n\n logger.info('Send email activity invoked', { component: 'SEND_EMAIL', subject })\n\n let emailService: { send: (input: unknown) => Promise<unknown> | unknown } | undefined\n try {\n emailService = container.resolve<{ send: (input: unknown) => Promise<unknown> | unknown }>('emailService')\n } catch {\n emailService = undefined\n }\n\n if (emailService && typeof emailService.send === 'function') {\n await emailService.send({\n to,\n subject,\n template,\n templateData,\n body,\n })\n return { sent: true, to, subject, via: 'emailService' }\n }\n\n logger.warn('SEND_EMAIL has no registered email service; email was not sent', { component: 'SEND_EMAIL', subject })\n return { sent: false, simulated: true, to, subject, via: 'console', reason: 'no-email-service' }\n}\n\n/**\n * EMIT_EVENT activity handler\n *\n * Publishes a domain event to the event bus\n */\nexport async function executeEmitEvent(\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { eventName, payload } = config\n\n if (!eventName) {\n throw new Error('EMIT_EVENT requires \"eventName\" field')\n }\n\n // Workflow definitions are tenant-managed input. Private cross-process\n // events coordinate trusted server state (for example closing an in-memory\n // collaboration room), so allowing a workflow to name one would turn a\n // regular event activity into a cross-process invalidation primitive.\n if (isPrivateCrossProcessBroadcastEvent(eventName)) {\n throw new Error(`EMIT_EVENT cannot emit private cross-process event \"${eventName}\"`)\n }\n\n // Emissions are fire-and-forget and no subscriber validates the payload shape,\n // so an unresolved `{{context.x}}` here is even quieter than on the command\n // path \u2014 it ships the literal template to every consumer. Fail loudly instead.\n const unresolvedPayloadKeys = findUnresolvedTemplateKeys(payload)\n if (unresolvedPayloadKeys.length > 0) {\n throw new Error(\n `EMIT_EVENT payload contains unresolved template variables for: ${unresolvedPayloadKeys.join(', ')}. ` +\n `Check that the workflow context provides these keys.`\n )\n }\n\n // Get event bus from container\n const eventBus = container.resolve<{ emitEvent: (event: string, payload: unknown, options?: unknown) => Promise<unknown> | unknown }>('eventBus')\n\n if (!eventBus || typeof eventBus.emitEvent !== 'function') {\n throw new Error('Event bus not available in container')\n }\n\n // Publish event with workflow metadata\n const enrichedPayload = {\n ...payload,\n _workflow: {\n workflowInstanceId: context.workflowInstance.id,\n workflowId: context.workflowInstance.workflowId,\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n },\n }\n\n await eventBus.emitEvent(eventName, enrichedPayload, {\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n })\n\n return { emitted: true, eventName, payload: enrichedPayload }\n}\n\nconst UNRESOLVED_TEMPLATE_PATTERN = /\\{\\{[^}]+\\}\\}/\n\nfunction findUnresolvedTemplateKeys(value: unknown, path = ''): string[] {\n if (typeof value === 'string') {\n return UNRESOLVED_TEMPLATE_PATTERN.test(value) ? [path] : []\n }\n if (Array.isArray(value)) {\n return value.flatMap((item, index) => findUnresolvedTemplateKeys(item, `${path}[${index}]`))\n }\n if (value && typeof value === 'object') {\n return Object.entries(value).flatMap(([key, nested]) =>\n findUnresolvedTemplateKeys(nested, path ? `${path}.${key}` : key)\n )\n }\n return []\n}\n\n/**\n * UPDATE_ENTITY activity handler\n *\n * Updates an entity via CommandBus for proper audit logging, undo support, and side effects.\n *\n * Config format:\n * ```json\n * {\n * \"commandId\": \"sales.documents.update\",\n * \"input\": {\n * \"id\": \"{{context.orderId}}\",\n * \"statusEntryId\": \"{{context.approvedStatusId}}\"\n * }\n * }\n * ```\n *\n * Alternative format with statusValue (auto-resolves to statusEntryId):\n * ```json\n * {\n * \"commandId\": \"sales.orders.update\",\n * \"statusDictionary\": \"sales.order_status\",\n * \"input\": {\n * \"id\": \"{{context.orderId}}\",\n * \"statusValue\": \"pending_approval\"\n * }\n * }\n * ```\n *\n * Every `{{...}}` reference in `input` must resolve against the workflow context \u2014\n * an unresolved reference is rejected rather than forwarded to the command bus.\n */\nexport async function executeUpdateEntity(\n em: EntityManager,\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { commandId, input, statusDictionary } = config\n\n if (!commandId) {\n throw new Error('UPDATE_ENTITY requires \"commandId\" field (e.g., \"sales.documents.update\")')\n }\n\n // Gate 1 \u2014 the CODE declares this command possible.\n const workflowSafeCommand = getWorkflowSafeCommand(commandId)\n if (!workflowSafeCommand) {\n throw new Error('UPDATE_ENTITY command is not allowed')\n }\n\n // Gate 2 \u2014 this TENANT switched it on. A tenant that never saved the setting\n // resolves to the grandfathered set, so this is byte-identical to the\n // pre-setting behaviour for every existing tenant.\n const commandPolicy = await resolveWorkflowCommandPolicyForContainer(\n container,\n context.workflowInstance.tenantId,\n )\n if (!isWorkflowCommandEnabled(workflowSafeCommand, commandPolicy)) {\n throw new Error('UPDATE_ENTITY command is not enabled for this tenant')\n }\n\n if (!input || typeof input !== 'object') {\n throw new Error('UPDATE_ENTITY requires \"input\" object with entity data')\n }\n\n const actorUserId = typeof context.userId === 'string' ? context.userId.trim() : ''\n if (!actorUserId) {\n throw new Error('UPDATE_ENTITY requires an authenticated workflow user')\n }\n\n const authorized = await workflowUserHasAllFeatures(\n container,\n actorUserId,\n workflowSafeCommand.requiredFeatures,\n context.workflowInstance.tenantId,\n context.workflowInstance.organizationId\n )\n if (!authorized) {\n throw new Error('UPDATE_ENTITY command is not authorized')\n }\n\n // Resolve CommandBus from container\n const commandBus = container.resolve('commandBus') as any\n\n if (!commandBus || typeof commandBus.execute !== 'function') {\n throw new Error('CommandBus not available in container')\n }\n\n const unresolvedKeys = findUnresolvedTemplateKeys(input)\n if (unresolvedKeys.length > 0) {\n throw new Error(\n `UPDATE_ENTITY input contains unresolved template variables for: ${unresolvedKeys.join(', ')}. ` +\n `Check that the workflow context provides these keys.`\n )\n }\n\n // Prepare final input, resolving statusValue if provided\n let finalInput = { ...input }\n\n // If statusValue is provided with a statusDictionary, resolve it to statusEntryId\n if (finalInput.statusValue && statusDictionary) {\n const statusEntryId = await resolveDictionaryEntryId(\n em,\n statusDictionary,\n finalInput.statusValue,\n context.workflowInstance.tenantId,\n context.workflowInstance.organizationId\n )\n if (statusEntryId) {\n finalInput.statusEntryId = statusEntryId\n }\n delete finalInput.statusValue\n }\n\n // Build synthetic CommandRuntimeContext for workflow execution\n const ctx = {\n container,\n auth: {\n sub: actorUserId,\n tenantId: context.workflowInstance.tenantId,\n orgId: context.workflowInstance.organizationId,\n isSuperAdmin: false,\n },\n organizationScope: null,\n selectedOrganizationId: context.workflowInstance.organizationId,\n organizationIds: context.workflowInstance.organizationId\n ? [context.workflowInstance.organizationId]\n : null,\n }\n\n // Execute the command\n const { result, logEntry } = await commandBus.execute(commandId, {\n input: finalInput,\n ctx,\n })\n\n return {\n executed: true,\n commandId,\n result,\n logEntryId: logEntry?.id,\n }\n}\n\n/**\n * Helper to resolve dictionary entry ID by value\n */\nasync function resolveDictionaryEntryId(\n em: EntityManager,\n dictionaryKey: string,\n value: string,\n tenantId: string,\n organizationId: string\n): Promise<string | null> {\n try {\n // Import here to avoid circular dependencies\n const { Dictionary, DictionaryEntry } = await import('@open-mercato/core/modules/dictionaries/data/entities')\n\n // Find the dictionary\n const dictionary = await em.findOne(Dictionary, {\n key: dictionaryKey,\n tenantId,\n organizationId,\n deletedAt: null,\n })\n\n if (!dictionary) {\n logger.warn('Dictionary not found', { component: 'UPDATE_ENTITY', dictionaryKey })\n return null\n }\n\n // Find the entry by normalized value\n const normalizedValue = value.toLowerCase().trim()\n const entry = await em.findOne(DictionaryEntry, {\n dictionary: dictionary.id,\n tenantId,\n organizationId,\n normalizedValue,\n })\n\n if (!entry) {\n logger.warn('Dictionary entry not found', { component: 'UPDATE_ENTITY', dictionaryKey, value })\n return null\n }\n\n return entry.id\n } catch (error) {\n logger.error('Error resolving dictionary entry', { component: 'UPDATE_ENTITY', err: error })\n return null\n }\n}\n\n/**\n * CALL_WEBHOOK activity handler\n *\n * Makes HTTP request to an external URL. Applies shared SSRF guard\n * (protocol / credentials / blocked host / private IP literal / DNS rebinding)\n * before issuing the request and rejects any 3xx redirect rather than following.\n */\nexport type CallWebhookDeps = {\n lookupHost?: HostLookup\n allowPrivate?: boolean\n fetchImpl?: typeof fetch\n signal?: AbortSignal\n}\n\nexport async function executeCallWebhook(\n config: unknown,\n context: ActivityContext,\n deps: CallWebhookDeps = {}\n): Promise<any> {\n const parsed = callWebhookConfigSchema.safeParse(config)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => `${issue.path.join('.') || 'config'}: ${issue.message}`)\n .join('; ')\n throw new Error(`CALL_WEBHOOK config invalid: ${issues}`)\n }\n const { url, method, headers: rawHeaders, body } = parsed.data\n const headers = rawHeaders ?? {}\n\n const allowPrivate = deps.allowPrivate ?? isAllowPrivateWorkflowWebhookUrlsEnabled()\n\n let response: Response\n try {\n response = await safeOutboundFetch(\n url,\n {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...headers,\n },\n body: body !== undefined && body !== null ? JSON.stringify(body) : undefined,\n redirect: 'manual',\n signal: deps.signal,\n },\n {\n subject: 'Workflow webhook URL',\n allowPrivate,\n lookupHost: deps.lookupHost,\n fetchImpl: deps.fetchImpl,\n },\n )\n } catch (error) {\n if (error instanceof UnsafeOutboundUrlError) {\n throw new Error(\n `CALL_WEBHOOK rejected unsafe URL (reason=${error.reason}): ${error.message}`\n )\n }\n throw error\n }\n\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get('location')\n throw new Error(\n `CALL_WEBHOOK refused to follow redirect ${response.status} to ${\n location ?? '(no Location header)'\n }`\n )\n }\n\n // Parse response\n let result: any\n const contentType = response.headers.get('content-type')\n\n if (contentType && contentType.includes('application/json')) {\n result = await response.json()\n } else {\n result = await response.text()\n }\n\n // Check for HTTP errors\n if (!response.ok) {\n throw new Error(\n `Webhook request failed with status ${response.status}: ${JSON.stringify(result)}`\n )\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n result,\n }\n}\n\n/**\n * EXECUTE_FUNCTION activity handler\n *\n * Calls a registered function from DI container\n */\nexport async function executeFunction(\n config: any,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const { functionName, args = {} } = config\n\n if (!functionName) {\n throw new Error('EXECUTE_FUNCTION requires \"functionName\" field')\n }\n\n // Look up function in container\n const fnKey = `workflowFunction:${functionName}`\n\n try {\n const fn = container.resolve(fnKey)\n\n if (typeof fn !== 'function') {\n throw new Error(`Registered workflow function \"${functionName}\" is not a function`)\n }\n\n // Call function with args and context\n const result = await fn(args, context)\n\n return { executed: true, functionName, result }\n } catch (error) {\n if (error instanceof Error && error.message.includes('not registered')) {\n throw new Error(\n `Workflow function \"${functionName}\" not registered in DI container (key: ${fnKey})`\n )\n }\n throw error\n }\n}\n\n/**\n * WAIT activity handler\n *\n * Delays workflow execution for a configured duration or until a specific datetime.\n * - `duration`: relative delay (e.g. \"PT5M\", \"1h\", \"30s\")\n * - `until`: absolute datetime (e.g. \"2026-04-15T10:00:00Z\")\n * - Sync mode: blocks via sleep (suitable for short delays)\n * - Async mode: delay is handled by the queue's delayMs option;\n * this handler returns immediately when called from the worker\n */\nexport async function executeWait(config: any): Promise<any> {\n const durationMs = calculateWaitDelayMs(config)\n\n // In sync mode, actually sleep for the duration\n // In async mode (called from worker), the delay already happened via queue scheduling\n await sleep(durationMs)\n\n return { waited: true, durationMs }\n}\n\n/**\n * SET_VARIABLE activity handler\n *\n * Validates the (already interpolated) assignments and echoes them back as\n * `{ assignments }`. The sync merge points detect this output shape via\n * `isSetVariableOutput` and apply each assignment at its dot path in\n * top-level workflow context (see lib/set-variable.ts) instead of\n * namespacing the output under the activity name/type key.\n */\nexport async function executeSetVariable(\n config: unknown,\n context: ActivityContext\n): Promise<SetVariableOutput> {\n const parsed = setVariableConfigSchema.safeParse(config)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => `${issue.path.join('.') || 'config'}: ${issue.message}`)\n .join('; ')\n throw new Error(`SET_VARIABLE config invalid: ${issues}`)\n }\n\n for (const assignment of parsed.data.assignments) {\n const segments = splitAssignmentPath(assignment.path)\n if (segments === null) {\n throw new Error(\n `SET_VARIABLE assignment path contains a forbidden segment (__proto__, constructor, prototype): \"${assignment.path}\"`\n )\n }\n if (segments.length === 0) {\n throw new Error(`SET_VARIABLE assignment path is blank: \"${assignment.path}\"`)\n }\n }\n\n return { assignments: parsed.data.assignments }\n}\n\n/**\n * INVOKE_AGENT activity handler\n *\n * Runs a callable agent via the agent_orchestrator DI bridge (`agentWorkflowBridge`,\n * an optional peer) and dispositions any proposal:\n * - researcher \u2192 returns the agent data; the step proceeds inline (no park).\n * - auto_approved \u2192 returns the proposalId; the step proceeds inline (no park).\n * - user_task \u2192 returns a result carrying a `__park` marker so the step handler\n * parks the instance on `INVOKE_AGENT_SIGNAL_NAME`; agent_orchestrator's\n * dispose path later signals it to resume.\n *\n * `config` is the already-interpolated INVOKE_AGENT config.\n */\ntype AgentWorkflowBridgeLike = {\n invokeAgentForWorkflow: (args: {\n agentId: string\n input: unknown\n onResult: { autoApproveThreshold: number; autoApproveMargin?: number } | { alwaysAsk: true }\n ctx: {\n tenantId: string\n organizationId: string\n userId?: string\n workflowInstanceId: string\n stepId: string\n /**\n * The step-attempt id. With the instance and the step it IS this\n * invocation's identity, so the run it produces can be correlated by name\n * rather than by \"the newest run for this agent since now\".\n */\n invocationId?: string\n // Optional interpolated business-record descriptor (invokeAgentConfigSchema.subject).\n subject?: unknown\n // Optional already-resolved Review section (spec 7.5) \u2014 who reviews the\n // proposal this step raises, and by when. Absent means the unassigned\n // task the disposition service raised before the section existed.\n review?: AgentDispositionReview\n }\n }) => Promise<\n | { kind: 'research'; data: unknown }\n | { kind: 'auto_approved'; proposalId: string; payload: unknown }\n | { kind: 'user_task'; proposalId: string }\n // The agent proposed nothing: terminal like `researcher`, never parked.\n | { kind: 'none_proposed'; proposalId: string; payload: unknown }\n // The agent PRODUCED files. Terminal and non-mutating, so it routes onto the\n // same governance handle as a research result: the five outcome handles are a\n // vocabulary of DECISIONS, and \"it made a document\" is not one of them.\n | { kind: 'artifact'; artifacts: unknown[]; summary?: string }\n >\n}\n\nfunction tryResolveAgentWorkflowBridge(\n container: AwilixContainer,\n): AgentWorkflowBridgeLike | undefined {\n try {\n return container.resolve<AgentWorkflowBridgeLike>('agentWorkflowBridge')\n } catch {\n return undefined\n }\n}\n\nexport async function executeInvokeAgent(\n config: unknown,\n context: ActivityContext,\n container: AwilixContainer\n): Promise<any> {\n const parsed = invokeAgentConfigSchema.safeParse(config)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => `${issue.path.join('.') || 'config'}: ${issue.message}`)\n .join('; ')\n throw new Error(`INVOKE_AGENT config invalid: ${issues}`)\n }\n const { agentId, input, onResult, outputMapping, subject, review } = parsed.data\n\n // The Review section is resolved HERE, against the context the step ran with,\n // for the same reason a USER_TASK's assignment is resolved at creation rather\n // than at read time: a definition edit while the agent is running must not\n // retro-change who the resulting review task belongs to. `config` reaches this\n // function already interpolated, so a dynamic assignee is either a resolved id\n // or an untouched `{{\u2026}}` token \u2014 which `resolveTaskAssignment` reads as the\n // fallback-to-the-role-queue case.\n const dispositionReview = toAgentDispositionReview(resolveAgentReview(review, (value) => value))\n\n // Fail fast when the optional agent_orchestrator peer is absent \u2014 the worker\n // would otherwise enqueue a job that can never run.\n const bridge = tryResolveAgentWorkflowBridge(container)\n if (!bridge) {\n throw new Error('[internal] agent_orchestrator not installed')\n }\n\n const stepId =\n context.stepContext?.stepId ||\n context.workflowInstance.currentStepId\n\n // Resolve the traceable principal this agent run executes as, from the\n // workflow instance (NOT the unreliable execution `context.userId`, which is\n // empty for event/sub-workflow paths). Same security model as CALL_API: the\n // run must never exceed the permissions of the human who triggered (or\n // authored) the workflow, and there is no anonymous \"system\" fallback \u2014\n // passing an empty user id downstream both poisons the DB transaction\n // (invalid uuid `\"\"`) and would mint a session token attributed to no one.\n const principalEm = container.resolve<PostgreSqlEntityManager>('em')\n const effectiveUserId = await resolveWorkflowPrincipalUserId(principalEm, context.workflowInstance)\n if (!effectiveUserId) {\n throw new Error(\n `[INVOKE_AGENT] Refusing to execute for workflow instance ${context.workflowInstance.id}: ` +\n `no traceable user (instance initiatedBy or definition author) could be resolved. ` +\n `Agent runs must execute under the identity of the user who triggered them.`\n )\n }\n\n // Parallel-branch agent steps keep the legacy inline path. The async fix below\n // parks and resumes at the INSTANCE level, and sendSignal's FORKED branch\n // resume only matches WAIT_FOR_SIGNAL steps \u2014 so an instance-level resume would\n // not reach a parked branch. The claims blueprints (and the common case) run\n // agents sequentially at the instance level; only rarely-used parallel branches\n // hit this fallback, where behavior is unchanged from before.\n if (context.branchInstanceId) {\n const outcome = await bridge.invokeAgentForWorkflow({\n agentId,\n input,\n onResult,\n ctx: {\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n userId: effectiveUserId,\n workflowInstanceId: context.workflowInstance.id,\n stepId,\n // The step-attempt row id: a retry enters the step again and mints a new\n // one, so it names THIS attempt and no other.\n ...(context.stepInstanceId ? { invocationId: context.stepInstanceId } : {}),\n ...(subject ? { subject } : {}),\n ...(dispositionReview ? { review: dispositionReview } : {}),\n },\n })\n if (outcome.kind === 'research') {\n return { kind: 'research', agentId, data: outcome.data }\n }\n if (outcome.kind === 'artifact') {\n return { kind: 'artifact', agentId, artifacts: outcome.artifacts, summary: outcome.summary }\n }\n if (outcome.kind === 'auto_approved' || outcome.kind === 'none_proposed') {\n return { kind: outcome.kind, agentId, proposalId: outcome.proposalId, proposalPayload: outcome.payload }\n }\n return {\n kind: 'user_task',\n agentId,\n proposalId: outcome.proposalId,\n __park: { signalName: INVOKE_AGENT_SIGNAL_NAME },\n }\n }\n\n if (!context.stepInstanceId) {\n throw new Error('[internal] INVOKE_AGENT requires a step instance to park on')\n }\n\n // Run the agent OUTSIDE the workflow transaction. Previously the agent ran\n // inline here, on the workflow's transactional EM: a failing statement aborted\n // the whole workflow transaction (\"current transaction is aborted, \u2026\") and,\n // for cross-process OpenCode agents, the per-run api_key / session rows were\n // written into the still-open transaction so the separate mcp:serve-http\n // process could not see them to authenticate submit_outcome. Instead we enqueue\n // a dedicated job and PARK the step on the proposal-ready signal: the\n // workflow-invoke-agent worker runs the agent on its own connection (committed,\n // cross-process visible) and resumes the parked step via sendSignal. user_task\n // outcomes stay parked until agent_orchestrator's human dispose fires the same\n // signal \u2014 identical to the prior park behavior.\n const queue = getInvokeAgentQueue()\n const job: WorkflowActivityJobInvokeAgent = {\n kind: 'invoke_agent',\n workflowInstanceId: context.workflowInstance.id,\n branchInstanceId: context.branchInstanceId ?? undefined,\n stepInstanceId: context.stepInstanceId,\n stepId,\n signalName: INVOKE_AGENT_SIGNAL_NAME,\n agentId,\n input: (input ?? {}) as Record<string, any>,\n onResult,\n ...(outputMapping ? { outputMapping } : {}),\n ...(subject ? { subject } : {}),\n ...(dispositionReview ? { review: dispositionReview } : {}),\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n userId: effectiveUserId,\n }\n const jobId = await queue.enqueue(job, { delayMs: INVOKE_AGENT_ENQUEUE_DELAY_MS })\n\n return {\n kind: 'pending_agent',\n agentId,\n jobId,\n __park: { signalName: INVOKE_AGENT_SIGNAL_NAME },\n }\n}\n\n/**\n * CALL_API activity handler\n *\n * Makes authenticated HTTP request to internal Open Mercato APIs\n * - Automatically creates one-time API key for authentication\n * - Injects tenant/organization context headers\n * - Validates URL security (SSRF prevention)\n * - Classifies errors (retriable vs non-retriable)\n * - Deletes API key after request (no stored credentials!)\n */\nexport async function executeCallApi(\n em: EntityManager,\n config: any,\n context: ActivityContext,\n container: AwilixContainer,\n signal?: AbortSignal\n): Promise<any> {\n // 1. Interpolate variables in config (including {{workflow.*}}, {{context.*}}, allowlisted {{env.*}}, {{now}})\n const interpolatedConfig = interpolateActivityConfig(config, context, 'CALL_API')\n\n const {\n endpoint,\n method = 'GET',\n headers = {},\n body,\n validateTenantMatch = true,\n } = interpolatedConfig\n\n\n if (!endpoint) {\n throw new Error('CALL_API requires \"endpoint\" field')\n }\n\n // 2. Build full URL (prepend APP_URL for relative paths)\n const fullUrl = buildApiUrl(endpoint)\n\n // 3. Import the one-time API key helper\n const { withOnetimeApiKey } = await import('../../api_keys/services/apiKeyService')\n\n // 4. Create the one-time API key on an EntityManager that is fully detached\n // from the surrounding request/transaction context.\n //\n // CALL_API runs inside `workflowExecutor.executeWorkflow()`, which wraps\n // the whole execution in `em.transactional(...)`. The request EM is forked\n // with `useContext: true`, so while that transaction is open, EVERY\n // operation on the container's `em` \u2014 including this API key's\n // persist/flush \u2014 is transparently redirected to the uncommitted\n // transaction fork (MikroORM `getContext()` \u2192 `TransactionContext`). The\n // key would therefore stay invisible until the transaction commits, but\n // the commit cannot happen until this activity returns. The outbound\n // self-authenticated `fetch` below opens a SEPARATE DB connection that\n // cannot see the uncommitted row, so the internal API responds `401` and\n // the activity fails (issue #4202).\n //\n // Forking with `useContext: false` (matching the query_index/webhooks\n // isolated-EM convention) gives the key its own pooled connection with\n // autocommit, so it is committed and visible to the internal request\n // immediately.\n const apiKeyEm = container\n .resolve<PostgreSqlEntityManager>('em')\n .fork({ clear: true, freshEventManager: true, useContext: false }) as PostgreSqlEntityManager\n\n // 5. Resolve the roles that the one-time API key will inherit.\n //\n // SECURITY: The key must never exceed the permissions of the human who\n // triggered (or authored) this workflow. Previously this code looked up\n // a role named \"admin\"/\"superadmin\" for the tenant and assigned it to\n // the key \u2014 which allowed any non-admin workflow author with\n // `workflows.definitions.edit` + `workflows.instances.create` to issue\n // arbitrary administrative API calls via a CALL_API activity. See the\n // SECURITY.md changelog entry for this fix.\n //\n // The resolution strategy is:\n // 1. Use the workflow instance's `metadata.initiatedBy` user (whoever\n // manually started the instance), when available. Only this user's\n // current active roles are used \u2014 we never fall back to the author\n // when the initiator is known, because that would escalate the\n // initiator's privileges.\n // 2. Fall back to the workflow definition's `createdBy` (author) only\n // when the instance was started by an event trigger with no user.\n // 3. If no traceable principal exists, the activity refuses to run \u2014\n // there is no \"system\" fallback that bypasses RBAC.\n const resolvedRoleIds = await resolveCallApiRoleIds(apiKeyEm, context.workflowInstance)\n\n if (resolvedRoleIds.length === 0) {\n throw new Error(\n `[CALL_API] Refusing to execute CALL_API for workflow instance ${context.workflowInstance.id}: ` +\n `no traceable user roles could be resolved from the workflow instance or definition. ` +\n `CALL_API activities must run under the identity of the user who triggered them.`\n )\n }\n\n // 6. Execute request with one-time API key scoped to the resolved user's roles\n return await withOnetimeApiKey(\n apiKeyEm,\n {\n name: `__workflow_${context.workflowInstance.id}__`,\n description: `One-time key for workflow ${context.workflowInstance.workflowId} instance ${context.workflowInstance.id}`,\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n roles: resolvedRoleIds,\n expiresAt: null,\n },\n async (apiKeySecret) => {\n // Build request headers (auth + context + custom)\n const requestHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `apikey ${apiKeySecret}`,\n 'X-Tenant-Id': context.workflowInstance.tenantId,\n 'X-Organization-Id': context.workflowInstance.organizationId,\n 'X-Workflow-Instance-Id': context.workflowInstance.id,\n ...headers,\n }\n\n // Make HTTP request\n const response = await fetch(fullUrl, {\n method,\n headers: requestHeaders,\n body: body ? JSON.stringify(body) : undefined,\n signal,\n })\n\n // Parse response body (JSON-safe)\n let responseBody: any\n const contentType = response.headers.get('content-type')\n\n try {\n if (contentType && contentType.includes('application/json')) {\n responseBody = await response.json()\n } else {\n responseBody = await response.text()\n }\n } catch (error) {\n responseBody = null\n }\n\n // Check for HTTP errors and classify\n if (!response.ok) {\n classifyAndThrowError(response.status, responseBody, fullUrl)\n }\n\n // Validate tenant match (security check)\n if (validateTenantMatch && responseBody && typeof responseBody === 'object') {\n if (responseBody.tenantId && responseBody.tenantId !== context.workflowInstance.tenantId) {\n throw new Error(\n `Tenant ID mismatch: workflow expects ${context.workflowInstance.tenantId} but API returned ${responseBody.tenantId}`\n )\n }\n }\n\n // Return structured result\n return {\n status: response.status,\n statusText: response.statusText,\n headers: Object.fromEntries(response.headers.entries()),\n body: responseBody,\n authenticated: true,\n tenantId: context.workflowInstance.tenantId,\n organizationId: context.workflowInstance.organizationId,\n }\n }\n )\n}\n\n// ============================================================================\n// CALL_API Helper Functions\n// ============================================================================\n\nexport type CallApiInstanceLike = {\n id: string\n tenantId: string\n organizationId: string\n definitionId: string\n metadata?: { initiatedBy?: string | null } | null\n}\n\nasync function resolveActiveRoleIdsForUser(\n em: any,\n userId: string,\n scope: { tenantId: string; organizationId: string },\n): Promise<string[]> {\n const { findOneWithDecryption, findWithDecryption } = await import('@open-mercato/shared/lib/encryption/find')\n const { User, UserRole, Role } = await import('../../auth/data/entities')\n\n const user = await findOneWithDecryption(em, User, {\n id: userId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }, {}, scope)\n if (!user) return []\n\n const userRoles = await findWithDecryption(\n em,\n UserRole,\n { user: user.id, deletedAt: null },\n { populate: ['role'] },\n scope,\n )\n const roleIds = userRoles\n .map((ur: any) => (typeof ur.role === 'string' ? ur.role : ur.role?.id))\n .filter((id: unknown): id is string => typeof id === 'string' && id.length > 0)\n\n if (roleIds.length === 0) return []\n\n const scopedRoles = await findWithDecryption(em, Role, {\n id: { $in: roleIds },\n tenantId: scope.tenantId,\n deletedAt: null,\n }, {}, scope)\n return scopedRoles.map((r: any) => r.id as string)\n}\n\n/**\n * Loads the instance's definition (including soft-deleted rows, so an execution\n * grant on a deleted definition still binds a run that is still executing).\n */\nasync function loadInstanceDefinition(em: any, instance: CallApiInstanceLike) {\n if (!instance.definitionId) return null\n const { findOneWithDecryption } = await import('@open-mercato/shared/lib/encryption/find')\n const { WorkflowDefinition } = await import('../data/entities')\n return findOneWithDecryption(\n em,\n WorkflowDefinition,\n { id: instance.definitionId, tenantId: instance.tenantId },\n {},\n { tenantId: instance.tenantId, organizationId: instance.organizationId },\n )\n}\n\nexport async function resolveCallApiRoleIds(\n em: any,\n instance: CallApiInstanceLike\n): Promise<string[]> {\n if (!instance.definitionId) return []\n\n const scope = { tenantId: instance.tenantId, organizationId: instance.organizationId }\n const definition = await loadInstanceDefinition(em, instance)\n\n // 0. A definition that declares its own execution grant ALWAYS acts as its\n // own least-privilege principal, whoever started the run \u2014 otherwise a\n // CALL_API activity would mint a key carrying the starting admin's roles\n // and route straight around the grant.\n if (definitionDeclaresGrant(definition)) {\n const principalUserId = await resolveWorkflowDefinitionExecutionUserId(em, definition, null)\n return principalUserId ? resolveActiveRoleIdsForUser(em, principalUserId, scope) : []\n }\n\n // 1. Prefer the triggering user (whoever manually started this instance).\n // WorkflowInstance.metadata.initiatedBy is the canonical record of that\n // principal for user-started instances; use their current role set so\n // CALL_API never exceeds the initiator's permissions. Refuse if the\n // initiator has no active scoped roles \u2014 do not fall back to the\n // definition author, which would escalate the initiator's privileges.\n const initiatorUserId = instance.metadata?.initiatedBy ?? null\n if (initiatorUserId) {\n return resolveActiveRoleIdsForUser(em, initiatorUserId, scope)\n }\n\n // 2. Event-triggered instance with no human initiator: fall back to the\n // definition author. Soft-deleted definitions must not mint keys.\n const authorUserId = definition?.deletedAt ? null : definition?.createdBy\n if (!authorUserId) return []\n\n return resolveActiveRoleIdsForUser(em, authorUserId, scope)\n}\n\n/**\n * Resolve the traceable principal user id an INVOKE_AGENT run executes as.\n *\n * Mirrors `resolveCallApiRoleIds`' principal chain so workflow-originated agent\n * runs carry the same audited identity as CALL_API:\n * 1. The instance's `metadata.initiatedBy` (whoever started it; inherited by\n * sub-workflows from the parent instance).\n * 2. The definition's `createdBy` (author) for event-triggered instances with\n * no human initiator. Soft-deleted definitions resolve to no principal.\n *\n * Both are outranked by the definition's own `grantedFeatures` execution\n * principal when it declares one (see `lib/definition-grant.ts`).\n *\n * Returns `null` when no traceable principal exists \u2014 callers MUST refuse rather\n * than fall back to an empty/anonymous user id (which breaks uuid columns and\n * bypasses RBAC attribution).\n */\nexport async function resolveWorkflowPrincipalUserId(\n em: any,\n instance: CallApiInstanceLike\n): Promise<string | null> {\n const definition = await loadInstanceDefinition(em, instance)\n\n // 0. A declared execution grant outranks both \u2014 the run acts as its own\n // principal regardless of who started it.\n if (definitionDeclaresGrant(definition)) {\n return resolveWorkflowDefinitionExecutionUserId(em, definition, null)\n }\n\n const initiatorUserId = instance.metadata?.initiatedBy ?? null\n if (initiatorUserId) return initiatorUserId\n\n if (definition?.deletedAt) return null\n return definition?.createdBy ?? null\n}\n\n/**\n * Build full API URL from endpoint\n * - Relative paths (/api/...) \u2192 prepend APP_URL\n * - Absolute URLs \u2192 validate domain matches APP_URL (SSRF prevention)\n */\nfunction buildApiUrl(endpoint: string): string {\n const appUrl = process.env.APP_URL || 'http://localhost:3000'\n\n // Relative path - prepend APP_URL\n if (endpoint.startsWith('/')) {\n // Security: Only allow /api/* paths\n if (!endpoint.startsWith('/api/')) {\n throw new Error(`CALL_API only supports /api/* paths, got: ${endpoint}`)\n }\n return `${appUrl}${endpoint}`\n }\n\n // Absolute URL - validate domain matches APP_URL (SSRF prevention)\n try {\n const endpointUrl = new URL(endpoint)\n const appUrlObj = new URL(appUrl)\n\n if (endpointUrl.host !== appUrlObj.host) {\n throw new Error(\n `SSRF Prevention: CALL_API endpoint domain (${endpointUrl.host}) does not match APP_URL (${appUrlObj.host})`\n )\n }\n\n return endpoint\n } catch (error) {\n if (error instanceof TypeError) {\n throw new Error(`Invalid endpoint URL: ${endpoint}`)\n }\n throw error\n }\n}\n\n/**\n * Classify HTTP error and throw appropriate error\n * - 400-499: Non-retriable (client error - validation/auth)\n * - 500-599: Retriable (server error)\n */\nfunction classifyAndThrowError(status: number, body: any, url: string): never {\n const bodyStr = typeof body === 'string' ? body : JSON.stringify(body)\n\n if (status >= 400 && status < 500) {\n // Client errors - non-retriable\n throw new Error(\n `CALL_API request failed with status ${status} (non-retriable): ${bodyStr}`\n )\n }\n\n if (status >= 500) {\n // Server errors - retriable\n const error: any = new Error(\n `CALL_API request failed with status ${status} (retriable): ${bodyStr}`\n )\n error.retriable = true\n throw error\n }\n\n // Other errors\n throw new Error(`CALL_API request failed with status ${status}: ${bodyStr}`)\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\ntype InterpolationBaseResolution =\n | { status: 'resolved'; value: unknown }\n | { status: 'unresolved-context'; contextPath: string }\n | { status: 'unknown-workflow-key'; workflowKey: string }\n | { status: 'env-not-allowlisted'; envKey: string }\n\nfunction resolveInterpolationBaseValue(\n path: string,\n context: Record<string, any>,\n workflowInstance?: WorkflowInstance\n): InterpolationBaseResolution {\n if (path.startsWith('workflow.') && workflowInstance) {\n const workflowKey = path.substring('workflow.'.length)\n switch (workflowKey) {\n case 'instanceId':\n return { status: 'resolved', value: workflowInstance.id }\n case 'tenantId':\n return { status: 'resolved', value: workflowInstance.tenantId }\n case 'organizationId':\n return { status: 'resolved', value: workflowInstance.organizationId }\n case 'currentStepId':\n return { status: 'resolved', value: workflowInstance.currentStepId }\n case 'workflowId':\n return { status: 'resolved', value: workflowInstance.workflowId }\n case 'version':\n return { status: 'resolved', value: workflowInstance.version }\n default:\n return { status: 'unknown-workflow-key', workflowKey }\n }\n }\n\n if (path.startsWith('env.')) {\n const envKey = path.substring('env.'.length)\n if (!getWorkflowEnvInterpolationAllowlist().has(envKey)) {\n return { status: 'env-not-allowlisted', envKey }\n }\n return { status: 'resolved', value: process.env[envKey] ?? '' }\n }\n\n if (path === 'now') {\n return { status: 'resolved', value: new Date().toISOString() }\n }\n\n const contextPath = path.startsWith('context.') ? path.substring('context.'.length) : path\n const value = getNestedValue(context, contextPath)\n if (value !== undefined) return { status: 'resolved', value }\n return { status: 'unresolved-context', contextPath }\n}\n\nfunction strictInterpolationError(rawToken: string, reason: string): WorkflowInterpolationError {\n return new WorkflowInterpolationError(\n `Cannot interpolate {{${rawToken}}}: ${reason}`,\n rawToken\n )\n}\n\nfunction interpolateToken(\n rawToken: string,\n context: Record<string, any>,\n workflowInstance: WorkflowInstance | undefined,\n strict: boolean\n): { resolved: boolean; value?: unknown } {\n const parsedToken = parseInterpolationToken(rawToken)\n if (!parsedToken.ok) {\n if (strict) throw strictInterpolationError(rawToken, parsedToken.error)\n return { resolved: false }\n }\n const resolution = resolveInterpolationBaseValue(parsedToken.path, context, workflowInstance)\n if (resolution.status === 'unknown-workflow-key') {\n if (strict) throw strictInterpolationError(rawToken, `unknown workflow key \"${resolution.workflowKey}\"`)\n return { resolved: false }\n }\n if (resolution.status === 'env-not-allowlisted') {\n if (strict) throw strictInterpolationError(rawToken, `env variable \"${resolution.envKey}\" is not allowlisted`)\n }\n const baseValue =\n resolution.status === 'resolved'\n ? resolution.value\n : resolution.status === 'env-not-allowlisted'\n ? ''\n : undefined\n if (parsedToken.transforms.length === 0) {\n if (resolution.status === 'unresolved-context') {\n if (strict) throw strictInterpolationError(rawToken, `context path \"${resolution.contextPath}\" is not defined`)\n return { resolved: false }\n }\n return { resolved: true, value: baseValue }\n }\n const transformed = applyTransforms(baseValue, parsedToken.transforms)\n if (!transformed.ok) {\n if (strict) throw strictInterpolationError(rawToken, transformed.error.message)\n return { resolved: false }\n }\n if (transformed.value === undefined) {\n if (strict) throw strictInterpolationError(rawToken, 'the transform pipeline produced no value')\n return { resolved: false }\n }\n return { resolved: true, value: transformed.value }\n}\n\n/**\n * Interpolate variables in config from workflow context\n *\n * Supports syntax:\n * - {{context.field}} or {{context.nested.field}} - from workflow context\n * - {{workflow.instanceId}} - workflow instance ID\n * - {{workflow.tenantId}} - tenant ID\n * - {{workflow.organizationId}} - organization ID\n * - {{workflow.currentStepId}} - current step ID\n * - {{env.VAR_NAME}} - server-allowlisted environment variables\n * - {{now}} - current ISO timestamp\n * - {{ path | transform(args) | ... }} - pill transform pipeline\n * (`lib/interpolation-pipeline.ts`): a fixed table of pure transforms folded\n * over the resolved base value. Lenient behavior (the default): an\n * unparseable token, an unresolved path without a rescuing `default`, or a\n * failed transform passes the original token/config through unchanged. In\n * strict mode (`options.mode: 'strict'`, opted in per definition) the same\n * situations throw `WorkflowInterpolationError` naming the offending token;\n * only a `default(...)` transform can rescue an unresolved context path.\n */\nexport function interpolateVariables(\n config: any,\n context: Record<string, any>,\n workflowInstance?: WorkflowInstance,\n options?: { mode?: WorkflowInterpolationMode }\n): any {\n const strict = options?.mode === 'strict'\n if (typeof config === 'string') {\n // Check if this is a single variable reference (e.g., \"{{context.cart.items}}\")\n // This preserves the original type (array, object, number, boolean)\n const singleVarMatch = config.match(/^\\{\\{([^}]+)\\}\\}$/)\n\n if (singleVarMatch) {\n const outcome = interpolateToken(singleVarMatch[1], context, workflowInstance, strict)\n return outcome.resolved ? outcome.value : config\n }\n\n // Multiple interpolations or mixed text - return string\n return config.replace(/\\{\\{([^}]+)\\}\\}/g, (match, token) => {\n const outcome = interpolateToken(token, context, workflowInstance, strict)\n return outcome.resolved ? String(outcome.value) : match\n })\n }\n\n if (Array.isArray(config)) {\n return config.map((item) => interpolateVariables(item, context, workflowInstance, options))\n }\n\n if (config && typeof config === 'object') {\n const result: Record<string, any> = {}\n for (const [key, value] of Object.entries(config)) {\n result[key] = interpolateVariables(value, context, workflowInstance, options)\n }\n return result\n }\n\n return config\n}\n\nfunction interpolateActivityConfig(\n config: any,\n context: ActivityContext,\n activityType: ActivityType,\n activityName?: string\n): any {\n try {\n return interpolateVariables(config, context.workflowContext, context.workflowInstance, {\n mode: context.interpolationMode,\n })\n } catch (error) {\n if (error instanceof WorkflowInterpolationError) {\n throw new ActivityExecutionError(error.message, activityType, activityName, { token: error.token })\n }\n throw error\n }\n}\n\n/**\n * Get nested value from object by path (e.g., \"user.email\")\n */\nfunction getNestedValue(obj: any, path: string): any {\n const parts = path.split('.')\n let value = obj\n\n for (const part of parts) {\n if (value && typeof value === 'object' && part in value) {\n value = value[part]\n } else {\n return undefined\n }\n }\n\n return value\n}\n\n/**\n * Calculate exponential backoff delay\n */\nfunction calculateBackoff(\n initialIntervalMs: number,\n backoffCoefficient: number,\n attempt: number,\n maxIntervalMs: number\n): number {\n const backoff = initialIntervalMs * Math.pow(backoffCoefficient, attempt)\n return Math.min(backoff, maxIntervalMs || Infinity)\n}\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Execute a promise with timeout\n *\n * Only CALL_API and CALL_WEBHOOK honour the abort signal today \u2014 they forward\n * it to `fetch`. SEND_EMAIL, EMIT_EVENT, UPDATE_ENTITY and EXECUTE_FUNCTION\n * still run to completion after the timeout has been recorded. Tracked in\n * #5148.\n */\nasync function executeWithTimeout<T>(\n executor: (signal: AbortSignal) => Promise<T>,\n timeoutMs: number\n): Promise<T> {\n let timeoutId: NodeJS.Timeout\n const abortController = new AbortController()\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n abortController.abort()\n reject(new Error(`Activity execution timeout after ${timeoutMs}ms`))\n }, timeoutMs)\n })\n\n try {\n return await Promise.race([executor(abortController.signal), timeoutPromise])\n } finally {\n clearTimeout(timeoutId!)\n }\n}\n\nbindActivityExecutor({\n executeSendEmail,\n executeEmitEvent,\n executeUpdateEntity,\n executeCallWebhook,\n executeFunction,\n executeCallApi,\n executeSetVariable,\n executeInvokeAgent,\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["calculateWaitDelayMs"]
|
|
7
7
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const WORKFLOW_ACTIVITIES_QUEUE_NAME = "workflow-activities";
|
|
2
|
+
const WORKFLOW_INVOKE_AGENT_QUEUE_NAME = "workflow-invoke-agent";
|
|
2
3
|
export {
|
|
3
|
-
WORKFLOW_ACTIVITIES_QUEUE_NAME
|
|
4
|
+
WORKFLOW_ACTIVITIES_QUEUE_NAME,
|
|
5
|
+
WORKFLOW_INVOKE_AGENT_QUEUE_NAME
|
|
4
6
|
};
|
|
5
7
|
//# sourceMappingURL=activity-queue-types.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/workflows/lib/activity-queue-types.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Workflow Activity Queue Types\n *\n * Type definitions for async activity execution via queue system.\n * Jobs are discriminated by the optional `kind` field:\n * - `'activity'` (default, back-compat): background execution of a workflow activity\n * - `'timer'`: delayed fire-timer job for a WAIT_FOR_TIMER step\n */\n\nexport interface WorkflowActivityJobBase {\n workflowInstanceId: string\n stepInstanceId?: string\n // Set when the job belongs to a parallel branch; resume targets that branch.\n // Absent on jobs enqueued before parallel support shipped \u2192 instance-level resume.\n branchInstanceId?: string | null\n tenantId: string\n organizationId: string\n userId?: string\n}\n\nexport interface WorkflowActivityJobActivity extends WorkflowActivityJobBase {\n kind?: 'activity'\n transitionId?: string\n\n activityId: string\n activityName: string\n activityType: string\n activityConfig: any\n\n workflowContext: Record<string, any>\n stepContext?: Record<string, any>\n\n retryPolicy?: {\n maxAttempts: number\n initialIntervalMs: number\n backoffCoefficient: number\n maxIntervalMs: number\n }\n timeoutMs?: number\n}\n\nexport interface WorkflowActivityJobTimer extends WorkflowActivityJobBase {\n kind: 'timer'\n stepInstanceId: string\n fireAt: string // ISO 8601 timestamp for when the timer should fire\n}\n\nexport type WorkflowActivityJob
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * Workflow Activity Queue Types\n *\n * Type definitions for async activity execution via queue system.\n * Jobs are discriminated by the optional `kind` field:\n * - `'activity'` (default, back-compat): background execution of a workflow activity\n * - `'timer'`: delayed fire-timer job for a WAIT_FOR_TIMER step\n * - `'condition'`: delayed poll job for a WAIT_FOR_CONDITION step \u2014 the\n * durability backstop behind the event-driven context-write wake\n * - `'task_sla'`: delayed reminder / deadline-breach job for a USER_TASK,\n * carrying the absolute deadline so the queue cannot extend it\n * - `'invoke_agent'`: run an INVOKE_AGENT step's agent OUTSIDE the workflow\n * transaction, then resume the parked step via the proposal-ready signal\n * - `'workflow_error_handler'`: start the definition's catch-all handler\n * sub-workflow for a failed instance, outside the failing transaction\n */\n\nimport type { AgentDispositionReview } from './agent-disposition-task'\n\nexport interface WorkflowActivityJobBase {\n workflowInstanceId: string\n stepInstanceId?: string\n // Set when the job belongs to a parallel branch; resume targets that branch.\n // Absent on jobs enqueued before parallel support shipped \u2192 instance-level resume.\n branchInstanceId?: string | null\n tenantId: string\n organizationId: string\n userId?: string\n}\n\nexport interface WorkflowActivityJobActivity extends WorkflowActivityJobBase {\n kind?: 'activity'\n transitionId?: string\n\n activityId: string\n activityName: string\n activityType: string\n activityConfig: any\n\n workflowContext: Record<string, any>\n stepContext?: Record<string, any>\n\n retryPolicy?: {\n maxAttempts: number\n initialIntervalMs: number\n backoffCoefficient: number\n maxIntervalMs: number\n }\n timeoutMs?: number\n}\n\nexport interface WorkflowActivityJobTimer extends WorkflowActivityJobBase {\n kind: 'timer'\n stepInstanceId: string\n fireAt: string // ISO 8601 timestamp for when the timer should fire\n}\n\n/**\n * Poll job for a WAIT_FOR_CONDITION step. `deadlineAt` is absolute and carried\n * on the payload rather than recomputed per tick, so a slow queue can never\n * silently extend the configured timeout. `attempt` is 1-based and guards\n * against a runaway re-enqueue loop (see OM_WORKFLOWS_MAX_CONDITION_ATTEMPTS).\n */\nexport interface WorkflowActivityJobCondition extends WorkflowActivityJobBase {\n kind: 'condition'\n stepInstanceId: string\n deadlineAt: string\n attempt: number\n}\n\n/**\n * SLA job for a USER_TASK's deadline. One job per authored reminder offset plus\n * one for the deadline itself, all enqueued when the task is created.\n *\n * `deadlineAt` is ABSOLUTE and travels on the payload \u2014 exactly like the\n * WAIT_FOR_CONDITION backstop \u2014 so a queue that runs late can never silently\n * extend the deadline the author configured. `fireAt` records when this\n * particular job was meant to run, so a late reminder can recognise itself.\n *\n * Delivery is at-least-once: the handler is idempotent (a completed, cancelled\n * or already-breached task makes the job a no-op).\n */\nexport interface WorkflowActivityJobTaskSla extends WorkflowActivityJobBase {\n kind: 'task_sla'\n stepInstanceId: string\n userTaskId: string\n phase: 'reminder' | 'breach'\n deadlineAt: string\n fireAt: string\n}\n\nexport interface WorkflowActivityJobInvokeAgent extends WorkflowActivityJobBase {\n kind: 'invoke_agent'\n stepInstanceId: string\n // The step (node) id the agent runs for; used to confirm the instance is still\n // parked on this step before running the agent (race + idempotency guard).\n stepId: string\n // Signal the parked step listens on; the worker fires it to resume after the\n // agent run (agent_orchestrator.proposal.ready).\n signalName: string\n agentId: string\n input: Record<string, any>\n onResult: { autoApproveThreshold: number } | { alwaysAsk: true }\n // Optional routing of the agent result into workflow context (see\n // invokeAgentConfigSchema.outputMapping). Threaded through so the worker that\n // resumes the parked step can build the same context patch the inline path does.\n outputMapping?: Record<string, string>\n // Optional already-interpolated business-record descriptor (see\n // invokeAgentConfigSchema.subject); forwarded opaquely to the bridge ctx.\n subject?: Record<string, any>\n // Optional already-RESOLVED Review section (see invokeAgentConfigSchema.review,\n // spec 7.5). Resolved by the executor against the context the step ran with,\n // so an in-flight definition edit cannot retro-change who the disposition task\n // belongs to. Absent on every job enqueued before the section existed.\n review?: AgentDispositionReview\n}\n\n/**\n * Resume-parent job enqueued by `completeWorkflow` when a child instance with a\n * parent linkage reaches a terminal state. The worker loads the parent, confirms\n * it is still parked on the SUB_WORKFLOW step, maps the child output, and resumes\n * (or fails) the parent. Idempotent: a child completed inline (synchronous fast\n * path) enqueues a job that the worker guard skips.\n */\nexport interface WorkflowActivityJobResumeSubWorkflowParent extends WorkflowActivityJobBase {\n kind: 'resume_subworkflow_parent'\n parentInstanceId: string\n parentStepId: string\n parentStepInstanceId: string\n childInstanceId: string\n childStatus: 'COMPLETED' | 'FAILED'\n}\n\n/**\n * Workflow-level error handler job (spec 5.9), enqueued by `completeWorkflow`\n * before compensation runs. The failure triple travels on the payload so the\n * handler observes the PRE-compensation state, and the worker starts it on its\n * own connection \u2014 never inside the failing instance's transaction.\n */\nexport interface WorkflowActivityJobErrorHandler extends WorkflowActivityJobBase {\n kind: 'workflow_error_handler'\n handlerWorkflowId: string\n handlerVersion?: number\n failedStepId: string | null\n error: string | null\n contextSnapshot: Record<string, unknown>\n // 1-based nesting level of the handler being started; capped by\n // WORKFLOW_MAX_ERROR_HANDLER_DEPTH so a failing handler never recurses.\n depth: number\n}\n\nexport type WorkflowActivityJob =\n | WorkflowActivityJobActivity\n | WorkflowActivityJobTimer\n | WorkflowActivityJobCondition\n | WorkflowActivityJobTaskSla\n | WorkflowActivityJobInvokeAgent\n | WorkflowActivityJobResumeSubWorkflowParent\n | WorkflowActivityJobErrorHandler\n\nexport const WORKFLOW_ACTIVITIES_QUEUE_NAME = 'workflow-activities'\n\n/**\n * Dedicated queue for `invoke_agent` jobs. Minute-long LLM runs must not share\n * execution slots with fast workflow activities (timers, emails, API calls), so\n * `executeInvokeAgent` enqueues here and the `workflow-invoke-agent` worker\n * consumes with its own concurrency (`WORKERS_WORKFLOW_INVOKE_AGENT_CONCURRENCY`).\n */\nexport const WORKFLOW_INVOKE_AGENT_QUEUE_NAME = 'workflow-invoke-agent'\n"],
|
|
5
|
+
"mappings": "AAgKO,MAAM,iCAAiC;AAQvC,MAAM,mCAAmC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/workflows/lib/activity-registry-bootstrap.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Side-effect entry point that populates the Activity Registry with the\n * built-in activity types. Import this module wherever registry lookups must\n * be guaranteed (executor, worker, validators).\n */\n\nimport './activity-types'\n"],
|
|
5
|
+
"mappings": "AAMA,OAAO;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const registry = /* @__PURE__ */ new Map();
|
|
2
|
+
function registerActivityType(entry) {
|
|
3
|
+
if (registry.has(entry.id)) {
|
|
4
|
+
throw new Error(`[internal] Activity type already registered: ${entry.id}`);
|
|
5
|
+
}
|
|
6
|
+
registry.set(entry.id, entry);
|
|
7
|
+
}
|
|
8
|
+
function getActivityType(id) {
|
|
9
|
+
return registry.get(id) ?? null;
|
|
10
|
+
}
|
|
11
|
+
function listActivityTypes() {
|
|
12
|
+
return Array.from(registry.values());
|
|
13
|
+
}
|
|
14
|
+
function activityTypeIds() {
|
|
15
|
+
const ids = Array.from(registry.keys());
|
|
16
|
+
if (ids.length === 0) {
|
|
17
|
+
throw new Error("[internal] Activity registry is empty; register activity types before requesting ids");
|
|
18
|
+
}
|
|
19
|
+
return ids;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
activityTypeIds,
|
|
23
|
+
getActivityType,
|
|
24
|
+
listActivityTypes,
|
|
25
|
+
registerActivityType
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=activity-registry.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/workflows/lib/activity-registry.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Workflows Module - Activity Registry\n *\n * One declarative entry per activity type: dispatch, validation schema, form\n * spec, async capability, and dry-run behavior live together (spec\n * 2026-07-26-workflows-ux-redesign.md section 3.2).\n *\n * Runtime contract (the sync/async split made explicit):\n * - Lookups are by the activityType STRING on both the sync and async sides;\n * registry entries are never serialized.\n * - Job payloads carry `activityType` plus the already-interpolated config.\n * - Interpolation happens at enqueue time for async activities and at\n * dispatch time for sync activities.\n * - This module stays PURE: no React, no MikroORM/EntityManager, and no\n * Awilix container imports at module scope \u2014 type-only imports only \u2014 so\n * both the UI and the worker can load it without dragging in either\n * runtime.\n */\n\nimport type { ZodTypeAny } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { AwilixContainer } from 'awilix'\nimport type { ActivityContext } from './activity-executor'\n\nexport type ActivityAsyncCapability =\n | { capable: true }\n | { capable: false; reason: string }\n\nexport interface ActivityFormFieldSpec {\n id: string\n component: string\n labelKey?: string\n descriptionKey?: string\n required?: boolean\n}\n\nexport interface ActivityExecuteDeps {\n em: EntityManager\n container: AwilixContainer\n signal?: AbortSignal\n}\n\nexport interface ActivityTypeEntry<TConfig = unknown> {\n id: string\n icon: string\n i18nKey: string\n configSchema: ZodTypeAny\n form: ActivityFormFieldSpec[]\n execute: (\n config: TConfig,\n ctx: ActivityContext,\n deps: ActivityExecuteDeps\n ) => Promise<unknown>\n executeAsync?: (\n config: TConfig,\n ctx: ActivityContext,\n deps: ActivityExecuteDeps\n ) => Promise<unknown>\n async: ActivityAsyncCapability\n enqueueDelayMs?: (config: TConfig) => number | null\n mock?: ((config: TConfig, ctx: ActivityContext) => unknown) | 'refuse'\n compensable?: boolean\n outputContract?: 'unknown' | ((config: TConfig) => ZodTypeAny | 'unknown')\n}\n\nconst registry = new Map<string, ActivityTypeEntry>()\n\nexport function registerActivityType<TConfig>(entry: ActivityTypeEntry<TConfig>): void {\n if (registry.has(entry.id)) {\n throw new Error(`[internal] Activity type already registered: ${entry.id}`)\n }\n registry.set(entry.id, entry as ActivityTypeEntry)\n}\n\nexport function getActivityType(id: string): ActivityTypeEntry | null {\n return registry.get(id) ?? null\n}\n\nexport function listActivityTypes(): ActivityTypeEntry[] {\n return Array.from(registry.values())\n}\n\nexport function activityTypeIds(): [string, ...string[]] {\n const ids = Array.from(registry.keys())\n if (ids.length === 0) {\n throw new Error('[internal] Activity registry is empty; register activity types before requesting ids')\n }\n return ids as [string, ...string[]]\n}\n"],
|
|
5
|
+
"mappings": "AAiEA,MAAM,WAAW,oBAAI,IAA+B;AAE7C,SAAS,qBAA8B,OAAyC;AACrF,MAAI,SAAS,IAAI,MAAM,EAAE,GAAG;AAC1B,UAAM,IAAI,MAAM,gDAAgD,MAAM,EAAE,EAAE;AAAA,EAC5E;AACA,WAAS,IAAI,MAAM,IAAI,KAA0B;AACnD;AAEO,SAAS,gBAAgB,IAAsC;AACpE,SAAO,SAAS,IAAI,EAAE,KAAK;AAC7B;AAEO,SAAS,oBAAyC;AACvD,SAAO,MAAM,KAAK,SAAS,OAAO,CAAC;AACrC;AAEO,SAAS,kBAAyC;AACvD,QAAM,MAAM,MAAM,KAAK,SAAS,KAAK,CAAC;AACtC,MAAI,IAAI,WAAW,GAAG;AACpB,UAAM,IAAI,MAAM,sFAAsF;AAAA,EACxG;AACA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|