@solidxai/core 0.1.12-beta.0 → 0.1.12-beta.2
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/dist/constants/error-messages.d.ts +1 -0
- package/dist/constants/error-messages.d.ts.map +1 -1
- package/dist/constants/error-messages.js +1 -0
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/dtos/create-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/create-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/create-chatter-message.dto.js +7 -1
- package/dist/dtos/create-chatter-message.dto.js.map +1 -1
- package/dist/dtos/post-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/post-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/post-chatter-message.dto.js +6 -1
- package/dist/dtos/post-chatter-message.dto.js.map +1 -1
- package/dist/dtos/update-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/update-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/update-chatter-message.dto.js +8 -1
- package/dist/dtos/update-chatter-message.dto.js.map +1 -1
- package/dist/dtos/update-chatter-note-message.dto.d.ts +1 -0
- package/dist/dtos/update-chatter-note-message.dto.d.ts.map +1 -1
- package/dist/dtos/update-chatter-note-message.dto.js +7 -1
- package/dist/dtos/update-chatter-note-message.dto.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts +1 -0
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +5 -1
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.js +9 -0
- package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
- package/dist/interfaces/chatter-mention-notification.interface.d.ts +27 -0
- package/dist/interfaces/chatter-mention-notification.interface.d.ts.map +1 -0
- package/dist/interfaces/chatter-mention-notification.interface.js +3 -0
- package/dist/interfaces/chatter-mention-notification.interface.js.map +1 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts +17 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts.map +1 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js +106 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts +12 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js +39 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts +8 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js +10 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts +20 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js +48 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts +12 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js +39 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts +8 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js +10 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts +18 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js +45 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts +12 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js +39 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts +8 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js +10 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts +18 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js +45 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js.map +1 -0
- package/dist/seeders/seed-data/solid-core-metadata.json +21 -0
- package/dist/services/chatter-message.service.d.ts +7 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +85 -4
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +14 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist-tests/api/authenticate.spec.js +119 -0
- package/dist-tests/api/authenticate.spec.js.map +1 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
- package/dist-tests/api/ping.spec.js +21 -0
- package/dist-tests/api/ping.spec.js.map +1 -0
- package/dist-tests/helpers/auth.js +41 -0
- package/dist-tests/helpers/auth.js.map +1 -0
- package/dist-tests/helpers/env.js +11 -0
- package/dist-tests/helpers/env.js.map +1 -0
- package/docs/agent-builder/notebook-lm-prompt-for-agent-builder.md +136 -0
- package/docs/agent-builder/team-ready-note-agent-builder.md +305 -0
- package/docs/agent-hub-grooming.md +301 -0
- package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +438 -0
- package/docs/dashboards/dashboard-curl-smoke-tests.txt +146 -0
- package/docs/dashboards/delete-legacy-dashboard-metadata.sql +172 -0
- package/docs/datasource-introspection-ddl-analysis.md +326 -0
- package/docs/datasource-introspection-implementation-plan.md +306 -0
- package/docs/grouping-enhancements.md +89 -0
- package/docs/java-spring/README.md +3 -0
- package/docs/java-spring/solid-core-module-deep-dive-report.md +1317 -0
- package/docs/module-package-import-handoff.md +691 -0
- package/docs/seed-changes.md +65 -0
- package/docs/test-data-workflow.md +200 -0
- package/docs/type-declaration-import-issue.md +24 -0
- package/docs/workflow/business-automation-example-notes.md +309 -0
- package/docs/workflow/data-engineering-pipeline-example-notes.md +330 -0
- package/docs/workflow/foreach-example-notes.md +187 -0
- package/docs/workflow/hello-world-example-notes.md +271 -0
- package/docs/workflow/kestra-concepts-plugins-blueprints.md +315 -0
- package/docs/workflow/loop-until-example-notes.md +198 -0
- package/docs/workflow/microservices-and-apis-example-notes.md +264 -0
- package/docs/workflow/samples.md +25 -0
- package/docs/workflow/what-is-kestra.md +79 -0
- package/docs/workflow/workflow-core-module-handoff-summary.md +191 -0
- package/docs/workflow/workflow-module-brd.md +185 -0
- package/docs/workflow/workflow-module-domain-model.md +252 -0
- package/docs/workflow/workflow-module-metadata-dsl.md +302 -0
- package/docs/workflow/workflow-module-technical-spec.md +293 -0
- package/docs/workflow/workflow-node-type-contracts.md +635 -0
- package/docs/workflow/workflow-node-ui-metadata-contract.md +1262 -0
- package/docs/workflow/workflow-solidx-model-field-spec.md +284 -0
- package/package.json +1 -1
- package/src/constants/error-messages.ts +1 -0
- package/src/dtos/create-chatter-message.dto.ts +5 -0
- package/src/dtos/post-chatter-message.dto.ts +4 -0
- package/src/dtos/update-chatter-message.dto.ts +6 -0
- package/src/dtos/update-chatter-note-message.dto.ts +5 -0
- package/src/entities/chatter-message.entity.ts +3 -0
- package/src/helpers/solid-core-error-codes-provider.service.ts +9 -0
- package/src/interfaces/chatter-mention-notification.interface.ts +29 -0
- package/src/jobs/chatter-mention-notification-email-queue-handler.service.ts +114 -0
- package/src/jobs/database/chatter-mention-notification-email-publisher-database.service.ts +23 -0
- package/src/jobs/database/chatter-mention-notification-email-queue-options-database.ts +9 -0
- package/src/jobs/database/chatter-mention-notification-email-subscriber-database.service.ts +32 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.ts +23 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-queue-options.ts +9 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.ts +30 -0
- package/src/jobs/redis/chatter-mention-notification-email-publisher-redis.service.ts +23 -0
- package/src/jobs/redis/chatter-mention-notification-email-queue-options-redis.ts +9 -0
- package/src/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.ts +30 -0
- package/src/seeders/seed-data/email-templates/chatter-mention-notification.handlebars.html +200 -0
- package/src/seeders/seed-data/solid-core-metadata.json +21 -0
- package/src/services/chatter-message.service.ts +97 -2
- package/src/solid-core.module.ts +14 -0
- package/.claude/settings.local.json +0 -16
- package/CLAUDE.md +0 -26
- package/src/services/1.js +0 -6
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
# Workflow Node Type Contracts
|
|
2
|
+
|
|
3
|
+
This document defines the v1 node type contract for the `workflow-builder` module.
|
|
4
|
+
|
|
5
|
+
It covers:
|
|
6
|
+
|
|
7
|
+
- the common contract every node type must satisfy
|
|
8
|
+
- the five agreed v1 node types
|
|
9
|
+
- expression/interpolation choices
|
|
10
|
+
- pluggability using SolidX-style providers
|
|
11
|
+
|
|
12
|
+
## Agreed V1 Node Types
|
|
13
|
+
|
|
14
|
+
- `log.write`
|
|
15
|
+
- `http.request`
|
|
16
|
+
- `if`
|
|
17
|
+
- `forEach`
|
|
18
|
+
- `parallel`
|
|
19
|
+
|
|
20
|
+
Deferred node types:
|
|
21
|
+
|
|
22
|
+
- `switch`
|
|
23
|
+
- `loopUntil`
|
|
24
|
+
- `forEachItem`
|
|
25
|
+
- `subflow`
|
|
26
|
+
- database/query tasks
|
|
27
|
+
- notification tasks beyond logging
|
|
28
|
+
|
|
29
|
+
## Common Node Type Registry Contract
|
|
30
|
+
|
|
31
|
+
Every node type should be registered through a provider contract rather than hard-coded into the workflow engine.
|
|
32
|
+
|
|
33
|
+
Suggested registry fields:
|
|
34
|
+
|
|
35
|
+
- `type`
|
|
36
|
+
- `kind`
|
|
37
|
+
- `displayName`
|
|
38
|
+
- `category`
|
|
39
|
+
- `description`
|
|
40
|
+
- `configurationSchema`
|
|
41
|
+
- `uiSchema`
|
|
42
|
+
- `outputSchema`
|
|
43
|
+
- `runtimeHandler`
|
|
44
|
+
- `documentation`
|
|
45
|
+
|
|
46
|
+
Suggested TypeScript-style interface:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
export type WorkflowNodeKind = "task" | "control" | "subflow";
|
|
50
|
+
|
|
51
|
+
export interface WorkflowNodeExecutionContext {
|
|
52
|
+
workflow: Record<string, any>;
|
|
53
|
+
execution: Record<string, any>;
|
|
54
|
+
trigger?: Record<string, any>;
|
|
55
|
+
inputs: Record<string, any>;
|
|
56
|
+
outputs: Record<string, any>;
|
|
57
|
+
step?: Record<string, any>;
|
|
58
|
+
log: (message: string, metadata?: Record<string, any>) => Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface WorkflowNodeExecutionResult {
|
|
62
|
+
status: "success" | "failed" | "skipped";
|
|
63
|
+
outputs?: Record<string, any>;
|
|
64
|
+
error?: {
|
|
65
|
+
message: string;
|
|
66
|
+
code?: string;
|
|
67
|
+
details?: Record<string, any>;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface WorkflowNodeTypeProvider<TConfig = Record<string, any>> {
|
|
72
|
+
type(): string;
|
|
73
|
+
kind(): WorkflowNodeKind;
|
|
74
|
+
displayName(): string;
|
|
75
|
+
category(): string;
|
|
76
|
+
description(): string;
|
|
77
|
+
configurationSchema(): Record<string, any>;
|
|
78
|
+
uiSchema?(): Record<string, any>;
|
|
79
|
+
outputSchema?(): Record<string, any>;
|
|
80
|
+
execute?(config: TConfig, ctxt: WorkflowNodeExecutionContext): Promise<WorkflowNodeExecutionResult>;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Control nodes may not execute in the same way as runnable task nodes. They can either:
|
|
85
|
+
|
|
86
|
+
- expose a specialized control handler, or
|
|
87
|
+
- use the same `execute` contract and delegate child traversal to the engine
|
|
88
|
+
|
|
89
|
+
V1 recommendation: the engine owns traversal for `if`, `forEach`, and `parallel`; the node provider owns schema, validation metadata, and control-specific evaluation rules.
|
|
90
|
+
|
|
91
|
+
## SolidX Pluggability Pattern
|
|
92
|
+
|
|
93
|
+
SolidX already uses a provider discovery pattern for selection providers, computed field providers, dashboard widget data providers, settings providers, mail providers, SMS providers, and other extension points.
|
|
94
|
+
|
|
95
|
+
The pattern is:
|
|
96
|
+
|
|
97
|
+
- define an interface for the provider contract
|
|
98
|
+
- define a decorator that marks provider classes with metadata
|
|
99
|
+
- implement providers as Nest injectable classes
|
|
100
|
+
- discover decorated providers at application bootstrap
|
|
101
|
+
- register discovered providers in a registry
|
|
102
|
+
- resolve providers by `name()` or type-specific key at runtime
|
|
103
|
+
|
|
104
|
+
Relevant existing examples in SolidX:
|
|
105
|
+
|
|
106
|
+
- `SelectionProvider`
|
|
107
|
+
- `ComputedFieldProvider`
|
|
108
|
+
- `DashboardWidgetDataProvider`
|
|
109
|
+
- `SolidIntrospectService`
|
|
110
|
+
- `SolidRegistry`
|
|
111
|
+
|
|
112
|
+
Recommended workflow equivalent:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
export const IS_WORKFLOW_NODE_TYPE_PROVIDER = "IS_WORKFLOW_NODE_TYPE_PROVIDER";
|
|
116
|
+
|
|
117
|
+
export const WorkflowNodeTypeProvider = () => {
|
|
118
|
+
return (target: Function) => {
|
|
119
|
+
Reflect.defineMetadata(IS_WORKFLOW_NODE_TYPE_PROVIDER, true, target);
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Example provider:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
@WorkflowNodeTypeProvider()
|
|
128
|
+
@Injectable()
|
|
129
|
+
export class HttpRequestWorkflowNodeProvider implements WorkflowNodeTypeProvider<HttpRequestNodeConfig> {
|
|
130
|
+
type(): string {
|
|
131
|
+
return "http.request";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
kind(): WorkflowNodeKind {
|
|
135
|
+
return "task";
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
displayName(): string {
|
|
139
|
+
return "HTTP Request";
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
category(): string {
|
|
143
|
+
return "Integration";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
description(): string {
|
|
147
|
+
return "Makes an HTTP request and exposes response details as outputs.";
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
configurationSchema(): Record<string, any> {
|
|
151
|
+
return {
|
|
152
|
+
type: "object",
|
|
153
|
+
required: ["uri"],
|
|
154
|
+
properties: {
|
|
155
|
+
method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"], default: "GET" },
|
|
156
|
+
uri: { type: "string" },
|
|
157
|
+
headers: { type: "object", default: {} },
|
|
158
|
+
body: {},
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
outputSchema(): Record<string, any> {
|
|
164
|
+
return {
|
|
165
|
+
type: "object",
|
|
166
|
+
properties: {
|
|
167
|
+
statusCode: { type: "number" },
|
|
168
|
+
body: {},
|
|
169
|
+
headers: { type: "object" },
|
|
170
|
+
uri: { type: "string" },
|
|
171
|
+
method: { type: "string" },
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async execute(config: HttpRequestNodeConfig, ctxt: WorkflowNodeExecutionContext): Promise<WorkflowNodeExecutionResult> {
|
|
177
|
+
// Runtime implementation detail to be finalized during build.
|
|
178
|
+
return { status: "success", outputs: {} };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Discovery should follow the existing SolidX flow:
|
|
184
|
+
|
|
185
|
+
- `SolidIntrospectService`-style bootstrap scanning finds decorated providers
|
|
186
|
+
- the workflow module registers them into a `WorkflowNodeTypeRegistry`
|
|
187
|
+
- the runtime resolves providers by `node.type`
|
|
188
|
+
- only providers from currently imported/registered Nest modules are available
|
|
189
|
+
|
|
190
|
+
## Expression and Interpolation Strategy
|
|
191
|
+
|
|
192
|
+
We need one expression system for all workflow definitions.
|
|
193
|
+
|
|
194
|
+
Supported use cases:
|
|
195
|
+
|
|
196
|
+
- interpolate values inside strings
|
|
197
|
+
- evaluate boolean conditions
|
|
198
|
+
- resolve structured values
|
|
199
|
+
- transform simple data
|
|
200
|
+
- access execution context safely
|
|
201
|
+
|
|
202
|
+
Minimum context:
|
|
203
|
+
|
|
204
|
+
- `inputs`
|
|
205
|
+
- `outputs`
|
|
206
|
+
- `workflow`
|
|
207
|
+
- `execution`
|
|
208
|
+
- `trigger`
|
|
209
|
+
- `step`
|
|
210
|
+
|
|
211
|
+
Recommended syntax:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
{{ inputs.uri }}
|
|
215
|
+
{{ outputs.makeRequest.statusCode }}
|
|
216
|
+
{{ outputs.makeRequest.statusCode == 200 }}
|
|
217
|
+
{{ step.value }}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
This keeps us close to Kestra and makes seeded workflow YAML familiar.
|
|
221
|
+
|
|
222
|
+
### Complex Expressions
|
|
223
|
+
|
|
224
|
+
For v1, we should support two expression modes:
|
|
225
|
+
|
|
226
|
+
- string interpolation
|
|
227
|
+
- expression-only evaluation
|
|
228
|
+
|
|
229
|
+
String interpolation:
|
|
230
|
+
|
|
231
|
+
```json
|
|
232
|
+
{
|
|
233
|
+
"message": "Status Code: {{ outputs.makeRequest.statusCode }}"
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Expression-only evaluation:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"condition": "{{ outputs.makeRequest.statusCode == 200 }}"
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Recommended v1 expression capabilities:
|
|
246
|
+
|
|
247
|
+
- property access
|
|
248
|
+
- equality and comparison operators
|
|
249
|
+
- boolean operators
|
|
250
|
+
- numeric literals
|
|
251
|
+
- string literals
|
|
252
|
+
- array/object traversal
|
|
253
|
+
- a small allowlist of helper functions
|
|
254
|
+
|
|
255
|
+
Recommended v1 helper functions:
|
|
256
|
+
|
|
257
|
+
- `json(value)`
|
|
258
|
+
- `length(value)`
|
|
259
|
+
- `default(value, fallback)`
|
|
260
|
+
- `contains(value, search)`
|
|
261
|
+
- `date(value, format)` later if needed
|
|
262
|
+
- `secret(key)` later when secret handling is implemented
|
|
263
|
+
|
|
264
|
+
Security rule:
|
|
265
|
+
|
|
266
|
+
- expressions must be evaluated by a safe expression engine or a constrained evaluator
|
|
267
|
+
- no arbitrary JavaScript execution
|
|
268
|
+
- no filesystem, network, process, or module access from expressions
|
|
269
|
+
|
|
270
|
+
Open implementation choice:
|
|
271
|
+
|
|
272
|
+
- adopt an existing safe expression/template engine
|
|
273
|
+
- implement a constrained expression evaluator for the first release
|
|
274
|
+
|
|
275
|
+
Recommendation:
|
|
276
|
+
|
|
277
|
+
- keep `{{ }}` as the DSL syntax
|
|
278
|
+
- choose or build a constrained evaluator behind it
|
|
279
|
+
- treat expression resolution as a service so the underlying engine can change without changing the workflow DSL
|
|
280
|
+
|
|
281
|
+
## Node Type: `log.write`
|
|
282
|
+
|
|
283
|
+
### Purpose
|
|
284
|
+
|
|
285
|
+
Writes an interpolated message into the workflow execution log.
|
|
286
|
+
|
|
287
|
+
### Kind
|
|
288
|
+
|
|
289
|
+
`task`
|
|
290
|
+
|
|
291
|
+
### Required Configuration
|
|
292
|
+
|
|
293
|
+
- `message`
|
|
294
|
+
|
|
295
|
+
### Optional Configuration
|
|
296
|
+
|
|
297
|
+
- `level`
|
|
298
|
+
- `metadata`
|
|
299
|
+
|
|
300
|
+
### Configuration Shape
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"message": "Status Code: {{ outputs.makeRequest.statusCode }}",
|
|
305
|
+
"level": "info",
|
|
306
|
+
"metadata": {}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Output Schema
|
|
311
|
+
|
|
312
|
+
No required outputs.
|
|
313
|
+
|
|
314
|
+
Optional output:
|
|
315
|
+
|
|
316
|
+
- `message`
|
|
317
|
+
|
|
318
|
+
### Runtime Behavior
|
|
319
|
+
|
|
320
|
+
- resolve expressions in `message`
|
|
321
|
+
- write the message to execution logs
|
|
322
|
+
- return success unless logging fails
|
|
323
|
+
|
|
324
|
+
### Failure Behavior
|
|
325
|
+
|
|
326
|
+
- fail the node if expression resolution fails
|
|
327
|
+
- fail the node if log persistence fails
|
|
328
|
+
|
|
329
|
+
### Validation Rules
|
|
330
|
+
|
|
331
|
+
- `message` is required
|
|
332
|
+
- `level` must be one of `debug`, `info`, `warn`, `error` if provided
|
|
333
|
+
|
|
334
|
+
## Node Type: `http.request`
|
|
335
|
+
|
|
336
|
+
### Purpose
|
|
337
|
+
|
|
338
|
+
Makes an HTTP request and exposes response data to downstream nodes.
|
|
339
|
+
|
|
340
|
+
### Kind
|
|
341
|
+
|
|
342
|
+
`task`
|
|
343
|
+
|
|
344
|
+
### Required Configuration
|
|
345
|
+
|
|
346
|
+
- `uri`
|
|
347
|
+
|
|
348
|
+
### Optional Configuration
|
|
349
|
+
|
|
350
|
+
- `method`
|
|
351
|
+
- `headers`
|
|
352
|
+
- `query`
|
|
353
|
+
- `body`
|
|
354
|
+
- `timeoutMs`
|
|
355
|
+
- `successStatusCodes`
|
|
356
|
+
|
|
357
|
+
### Configuration Shape
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"method": "GET",
|
|
362
|
+
"uri": "{{ inputs.uri }}",
|
|
363
|
+
"headers": {},
|
|
364
|
+
"query": {},
|
|
365
|
+
"body": null,
|
|
366
|
+
"timeoutMs": 30000,
|
|
367
|
+
"successStatusCodes": [200, 201, 202, 204]
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Output Schema
|
|
372
|
+
|
|
373
|
+
- `statusCode`
|
|
374
|
+
- `body`
|
|
375
|
+
- `headers`
|
|
376
|
+
- `uri`
|
|
377
|
+
- `method`
|
|
378
|
+
- `durationMs`
|
|
379
|
+
|
|
380
|
+
### Runtime Behavior
|
|
381
|
+
|
|
382
|
+
- resolve expressions in config
|
|
383
|
+
- execute the HTTP request
|
|
384
|
+
- capture status code, response body, headers, final URI, method, and duration
|
|
385
|
+
- expose outputs as `outputs.<nodeId>.*`
|
|
386
|
+
|
|
387
|
+
### Failure Behavior
|
|
388
|
+
|
|
389
|
+
V1 recommendation:
|
|
390
|
+
|
|
391
|
+
- transport errors fail the node
|
|
392
|
+
- timeout errors fail the node
|
|
393
|
+
- HTTP status codes outside `successStatusCodes` fail the node but still capture response outputs where possible
|
|
394
|
+
|
|
395
|
+
This keeps failure semantics predictable while still allowing users to override success ranges.
|
|
396
|
+
|
|
397
|
+
### Validation Rules
|
|
398
|
+
|
|
399
|
+
- `uri` is required
|
|
400
|
+
- `method` defaults to `GET`
|
|
401
|
+
- `method` must be one of `GET`, `POST`, `PUT`, `PATCH`, `DELETE`
|
|
402
|
+
- `headers` must be an object if provided
|
|
403
|
+
- `query` must be an object if provided
|
|
404
|
+
- `timeoutMs` must be a positive number if provided
|
|
405
|
+
- `successStatusCodes` must be an array of HTTP status numbers if provided
|
|
406
|
+
|
|
407
|
+
## Node Type: `if`
|
|
408
|
+
|
|
409
|
+
### Purpose
|
|
410
|
+
|
|
411
|
+
Evaluates a condition and executes either the `then` or `else` node array.
|
|
412
|
+
|
|
413
|
+
### Kind
|
|
414
|
+
|
|
415
|
+
`control`
|
|
416
|
+
|
|
417
|
+
### Required Configuration
|
|
418
|
+
|
|
419
|
+
- `condition`
|
|
420
|
+
- `then`
|
|
421
|
+
|
|
422
|
+
### Optional Configuration
|
|
423
|
+
|
|
424
|
+
- `else`
|
|
425
|
+
|
|
426
|
+
### Configuration Shape
|
|
427
|
+
|
|
428
|
+
```json
|
|
429
|
+
{
|
|
430
|
+
"condition": "{{ outputs.makeRequest.statusCode == 200 }}"
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Child arrays:
|
|
435
|
+
|
|
436
|
+
- `then`
|
|
437
|
+
- `else`
|
|
438
|
+
|
|
439
|
+
### Output Schema
|
|
440
|
+
|
|
441
|
+
No direct outputs in v1.
|
|
442
|
+
|
|
443
|
+
### Runtime Behavior
|
|
444
|
+
|
|
445
|
+
- evaluate `condition` as a boolean expression
|
|
446
|
+
- execute `then` nodes when true
|
|
447
|
+
- execute `else` nodes when false and present
|
|
448
|
+
- mark skipped branch nodes as skipped where execution records are created
|
|
449
|
+
|
|
450
|
+
### Failure Behavior
|
|
451
|
+
|
|
452
|
+
- fail the node if condition evaluation fails
|
|
453
|
+
- fail the node if the selected branch fails, unless future error handling says otherwise
|
|
454
|
+
|
|
455
|
+
### Validation Rules
|
|
456
|
+
|
|
457
|
+
- `condition` is required
|
|
458
|
+
- `condition` must evaluate to boolean
|
|
459
|
+
- `then` must be a node array
|
|
460
|
+
- `else` must be a node array if provided
|
|
461
|
+
|
|
462
|
+
## Node Type: `forEach`
|
|
463
|
+
|
|
464
|
+
### Purpose
|
|
465
|
+
|
|
466
|
+
Executes child nodes once for each item in an array.
|
|
467
|
+
|
|
468
|
+
### Kind
|
|
469
|
+
|
|
470
|
+
`control`
|
|
471
|
+
|
|
472
|
+
### Required Configuration
|
|
473
|
+
|
|
474
|
+
- `values`
|
|
475
|
+
- `children`
|
|
476
|
+
|
|
477
|
+
### Optional Configuration
|
|
478
|
+
|
|
479
|
+
- `concurrency`
|
|
480
|
+
- `continueOnItemFailure`
|
|
481
|
+
|
|
482
|
+
### Configuration Shape
|
|
483
|
+
|
|
484
|
+
```json
|
|
485
|
+
{
|
|
486
|
+
"values": "{{ inputs.customerIds }}",
|
|
487
|
+
"concurrency": 1,
|
|
488
|
+
"continueOnItemFailure": false
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Child array:
|
|
493
|
+
|
|
494
|
+
- `children`
|
|
495
|
+
|
|
496
|
+
### Runtime Context
|
|
497
|
+
|
|
498
|
+
Each iteration exposes:
|
|
499
|
+
|
|
500
|
+
- `step.value`
|
|
501
|
+
- `step.index`
|
|
502
|
+
|
|
503
|
+
Example:
|
|
504
|
+
|
|
505
|
+
```text
|
|
506
|
+
{{ step.value }}
|
|
507
|
+
{{ step.index }}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Output Schema
|
|
511
|
+
|
|
512
|
+
Suggested v1 aggregate outputs:
|
|
513
|
+
|
|
514
|
+
- `count`
|
|
515
|
+
- `successCount`
|
|
516
|
+
- `failedCount`
|
|
517
|
+
- `items`
|
|
518
|
+
|
|
519
|
+
### Runtime Behavior
|
|
520
|
+
|
|
521
|
+
- evaluate `values`
|
|
522
|
+
- require the resolved value to be an array
|
|
523
|
+
- execute `children` once per item
|
|
524
|
+
- expose current item as `step.value`
|
|
525
|
+
- expose current index as `step.index`
|
|
526
|
+
- aggregate per-item results
|
|
527
|
+
|
|
528
|
+
### Failure Behavior
|
|
529
|
+
|
|
530
|
+
V1 recommendation:
|
|
531
|
+
|
|
532
|
+
- default behavior fails the `forEach` node on the first failed item
|
|
533
|
+
- `continueOnItemFailure: true` allows all items to run and fails the node at the end if any item failed
|
|
534
|
+
|
|
535
|
+
### Validation Rules
|
|
536
|
+
|
|
537
|
+
- `values` is required
|
|
538
|
+
- `children` must be a non-empty node array
|
|
539
|
+
- `concurrency` must be a positive number if provided
|
|
540
|
+
- `continueOnItemFailure` must be boolean if provided
|
|
541
|
+
|
|
542
|
+
## Node Type: `parallel`
|
|
543
|
+
|
|
544
|
+
### Purpose
|
|
545
|
+
|
|
546
|
+
Executes multiple branches concurrently.
|
|
547
|
+
|
|
548
|
+
### Kind
|
|
549
|
+
|
|
550
|
+
`control`
|
|
551
|
+
|
|
552
|
+
### Required Configuration
|
|
553
|
+
|
|
554
|
+
- `branches`
|
|
555
|
+
|
|
556
|
+
### Optional Configuration
|
|
557
|
+
|
|
558
|
+
- `failFast`
|
|
559
|
+
|
|
560
|
+
### Configuration Shape
|
|
561
|
+
|
|
562
|
+
```json
|
|
563
|
+
{
|
|
564
|
+
"failFast": true
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Branch shape:
|
|
569
|
+
|
|
570
|
+
```json
|
|
571
|
+
{
|
|
572
|
+
"id": "checkDocs",
|
|
573
|
+
"nodes": []
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Output Schema
|
|
578
|
+
|
|
579
|
+
Suggested v1 aggregate outputs:
|
|
580
|
+
|
|
581
|
+
- `branchCount`
|
|
582
|
+
- `successCount`
|
|
583
|
+
- `failedCount`
|
|
584
|
+
- `branches`
|
|
585
|
+
|
|
586
|
+
### Runtime Behavior
|
|
587
|
+
|
|
588
|
+
- execute each branch concurrently
|
|
589
|
+
- execute nodes inside each branch sequentially
|
|
590
|
+
- aggregate branch results
|
|
591
|
+
|
|
592
|
+
### Failure Behavior
|
|
593
|
+
|
|
594
|
+
V1 recommendation:
|
|
595
|
+
|
|
596
|
+
- `failFast: true` stops scheduling remaining branches where possible after a branch fails
|
|
597
|
+
- already running branches may complete
|
|
598
|
+
- `failFast: false` runs all branches and fails at the end if any branch failed
|
|
599
|
+
|
|
600
|
+
### Validation Rules
|
|
601
|
+
|
|
602
|
+
- `branches` must be a non-empty array
|
|
603
|
+
- every branch must have a unique `id`
|
|
604
|
+
- every branch must have a `nodes` array
|
|
605
|
+
- `failFast` must be boolean if provided
|
|
606
|
+
|
|
607
|
+
## Cross-Cutting Validation Rules
|
|
608
|
+
|
|
609
|
+
Definition-time validation should check:
|
|
610
|
+
|
|
611
|
+
- every node has a unique `id` within the workflow
|
|
612
|
+
- every node has a known registered `type`
|
|
613
|
+
- node `kind` matches the registered provider kind
|
|
614
|
+
- required configuration fields are present
|
|
615
|
+
- node config satisfies the provider `configurationSchema`
|
|
616
|
+
- child node arrays contain valid nodes
|
|
617
|
+
- expression syntax is valid where expressions are used
|
|
618
|
+
- references to known prior outputs are valid where statically knowable
|
|
619
|
+
|
|
620
|
+
Some expression references cannot be fully validated until runtime, especially inside control-flow nodes.
|
|
621
|
+
|
|
622
|
+
## Cross-Cutting Runtime Rules
|
|
623
|
+
|
|
624
|
+
- node definitions hold design-time config only
|
|
625
|
+
- runtime outputs, logs, state, retries, and errors belong to execution records
|
|
626
|
+
- expressions are resolved immediately before a node executes
|
|
627
|
+
- each node execution should record input context, output payload, status, timestamps, and error summary
|
|
628
|
+
- disabled nodes should produce skipped step executions when execution records are created
|
|
629
|
+
|
|
630
|
+
## Open Questions
|
|
631
|
+
|
|
632
|
+
- Which expression engine should back `{{ }}`?
|
|
633
|
+
- Should `forEach` expose loop data as `step.value` or `taskrun.value` to stay closer to Kestra?
|
|
634
|
+
- Should `parallel.failFast` default to true or false?
|
|
635
|
+
- Should `http.request` treat all `2xx` statuses as success by default instead of a fixed list?
|