@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.
Files changed (147) hide show
  1. package/dist/constants/error-messages.d.ts +1 -0
  2. package/dist/constants/error-messages.d.ts.map +1 -1
  3. package/dist/constants/error-messages.js +1 -0
  4. package/dist/constants/error-messages.js.map +1 -1
  5. package/dist/dtos/create-chatter-message.dto.d.ts +1 -0
  6. package/dist/dtos/create-chatter-message.dto.d.ts.map +1 -1
  7. package/dist/dtos/create-chatter-message.dto.js +7 -1
  8. package/dist/dtos/create-chatter-message.dto.js.map +1 -1
  9. package/dist/dtos/post-chatter-message.dto.d.ts +1 -0
  10. package/dist/dtos/post-chatter-message.dto.d.ts.map +1 -1
  11. package/dist/dtos/post-chatter-message.dto.js +6 -1
  12. package/dist/dtos/post-chatter-message.dto.js.map +1 -1
  13. package/dist/dtos/update-chatter-message.dto.d.ts +1 -0
  14. package/dist/dtos/update-chatter-message.dto.d.ts.map +1 -1
  15. package/dist/dtos/update-chatter-message.dto.js +8 -1
  16. package/dist/dtos/update-chatter-message.dto.js.map +1 -1
  17. package/dist/dtos/update-chatter-note-message.dto.d.ts +1 -0
  18. package/dist/dtos/update-chatter-note-message.dto.d.ts.map +1 -1
  19. package/dist/dtos/update-chatter-note-message.dto.js +7 -1
  20. package/dist/dtos/update-chatter-note-message.dto.js.map +1 -1
  21. package/dist/entities/chatter-message.entity.d.ts +1 -0
  22. package/dist/entities/chatter-message.entity.d.ts.map +1 -1
  23. package/dist/entities/chatter-message.entity.js +5 -1
  24. package/dist/entities/chatter-message.entity.js.map +1 -1
  25. package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
  26. package/dist/helpers/solid-core-error-codes-provider.service.js +9 -0
  27. package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
  28. package/dist/interfaces/chatter-mention-notification.interface.d.ts +27 -0
  29. package/dist/interfaces/chatter-mention-notification.interface.d.ts.map +1 -0
  30. package/dist/interfaces/chatter-mention-notification.interface.js +3 -0
  31. package/dist/interfaces/chatter-mention-notification.interface.js.map +1 -0
  32. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts +17 -0
  33. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts.map +1 -0
  34. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js +106 -0
  35. package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js.map +1 -0
  36. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts +12 -0
  37. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts.map +1 -0
  38. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js +39 -0
  39. package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js.map +1 -0
  40. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts +8 -0
  41. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts.map +1 -0
  42. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js +10 -0
  43. package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js.map +1 -0
  44. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts +20 -0
  45. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts.map +1 -0
  46. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js +48 -0
  47. package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js.map +1 -0
  48. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts +12 -0
  49. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts.map +1 -0
  50. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js +39 -0
  51. package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js.map +1 -0
  52. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts +8 -0
  53. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts.map +1 -0
  54. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js +10 -0
  55. package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js.map +1 -0
  56. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts +18 -0
  57. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts.map +1 -0
  58. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js +45 -0
  59. package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js.map +1 -0
  60. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts +12 -0
  61. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts.map +1 -0
  62. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js +39 -0
  63. package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js.map +1 -0
  64. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts +8 -0
  65. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts.map +1 -0
  66. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js +10 -0
  67. package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js.map +1 -0
  68. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts +18 -0
  69. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts.map +1 -0
  70. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js +45 -0
  71. package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js.map +1 -0
  72. package/dist/seeders/seed-data/solid-core-metadata.json +21 -0
  73. package/dist/services/chatter-message.service.d.ts +7 -1
  74. package/dist/services/chatter-message.service.d.ts.map +1 -1
  75. package/dist/services/chatter-message.service.js +85 -4
  76. package/dist/services/chatter-message.service.js.map +1 -1
  77. package/dist/solid-core.module.d.ts.map +1 -1
  78. package/dist/solid-core.module.js +14 -0
  79. package/dist/solid-core.module.js.map +1 -1
  80. package/dist-tests/api/authenticate.spec.js +119 -0
  81. package/dist-tests/api/authenticate.spec.js.map +1 -0
  82. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
  83. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
  84. package/dist-tests/api/ping.spec.js +21 -0
  85. package/dist-tests/api/ping.spec.js.map +1 -0
  86. package/dist-tests/helpers/auth.js +41 -0
  87. package/dist-tests/helpers/auth.js.map +1 -0
  88. package/dist-tests/helpers/env.js +11 -0
  89. package/dist-tests/helpers/env.js.map +1 -0
  90. package/docs/agent-builder/notebook-lm-prompt-for-agent-builder.md +136 -0
  91. package/docs/agent-builder/team-ready-note-agent-builder.md +305 -0
  92. package/docs/agent-hub-grooming.md +301 -0
  93. package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +438 -0
  94. package/docs/dashboards/dashboard-curl-smoke-tests.txt +146 -0
  95. package/docs/dashboards/delete-legacy-dashboard-metadata.sql +172 -0
  96. package/docs/datasource-introspection-ddl-analysis.md +326 -0
  97. package/docs/datasource-introspection-implementation-plan.md +306 -0
  98. package/docs/grouping-enhancements.md +89 -0
  99. package/docs/java-spring/README.md +3 -0
  100. package/docs/java-spring/solid-core-module-deep-dive-report.md +1317 -0
  101. package/docs/module-package-import-handoff.md +691 -0
  102. package/docs/seed-changes.md +65 -0
  103. package/docs/test-data-workflow.md +200 -0
  104. package/docs/type-declaration-import-issue.md +24 -0
  105. package/docs/workflow/business-automation-example-notes.md +309 -0
  106. package/docs/workflow/data-engineering-pipeline-example-notes.md +330 -0
  107. package/docs/workflow/foreach-example-notes.md +187 -0
  108. package/docs/workflow/hello-world-example-notes.md +271 -0
  109. package/docs/workflow/kestra-concepts-plugins-blueprints.md +315 -0
  110. package/docs/workflow/loop-until-example-notes.md +198 -0
  111. package/docs/workflow/microservices-and-apis-example-notes.md +264 -0
  112. package/docs/workflow/samples.md +25 -0
  113. package/docs/workflow/what-is-kestra.md +79 -0
  114. package/docs/workflow/workflow-core-module-handoff-summary.md +191 -0
  115. package/docs/workflow/workflow-module-brd.md +185 -0
  116. package/docs/workflow/workflow-module-domain-model.md +252 -0
  117. package/docs/workflow/workflow-module-metadata-dsl.md +302 -0
  118. package/docs/workflow/workflow-module-technical-spec.md +293 -0
  119. package/docs/workflow/workflow-node-type-contracts.md +635 -0
  120. package/docs/workflow/workflow-node-ui-metadata-contract.md +1262 -0
  121. package/docs/workflow/workflow-solidx-model-field-spec.md +284 -0
  122. package/package.json +1 -1
  123. package/src/constants/error-messages.ts +1 -0
  124. package/src/dtos/create-chatter-message.dto.ts +5 -0
  125. package/src/dtos/post-chatter-message.dto.ts +4 -0
  126. package/src/dtos/update-chatter-message.dto.ts +6 -0
  127. package/src/dtos/update-chatter-note-message.dto.ts +5 -0
  128. package/src/entities/chatter-message.entity.ts +3 -0
  129. package/src/helpers/solid-core-error-codes-provider.service.ts +9 -0
  130. package/src/interfaces/chatter-mention-notification.interface.ts +29 -0
  131. package/src/jobs/chatter-mention-notification-email-queue-handler.service.ts +114 -0
  132. package/src/jobs/database/chatter-mention-notification-email-publisher-database.service.ts +23 -0
  133. package/src/jobs/database/chatter-mention-notification-email-queue-options-database.ts +9 -0
  134. package/src/jobs/database/chatter-mention-notification-email-subscriber-database.service.ts +32 -0
  135. package/src/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.ts +23 -0
  136. package/src/jobs/rabbitmq/chatter-mention-notification-email-queue-options.ts +9 -0
  137. package/src/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.ts +30 -0
  138. package/src/jobs/redis/chatter-mention-notification-email-publisher-redis.service.ts +23 -0
  139. package/src/jobs/redis/chatter-mention-notification-email-queue-options-redis.ts +9 -0
  140. package/src/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.ts +30 -0
  141. package/src/seeders/seed-data/email-templates/chatter-mention-notification.handlebars.html +200 -0
  142. package/src/seeders/seed-data/solid-core-metadata.json +21 -0
  143. package/src/services/chatter-message.service.ts +97 -2
  144. package/src/solid-core.module.ts +14 -0
  145. package/.claude/settings.local.json +0 -16
  146. package/CLAUDE.md +0 -26
  147. package/src/services/1.js +0 -6
@@ -0,0 +1,1262 @@
1
+ # Workflow Node UI Metadata Contract
2
+
3
+ ## Purpose
4
+
5
+ This document explains the newly added workflow node metadata interfaces in:
6
+
7
+ - `solid-core-module/src/types/workflow-dsl.types.ts`
8
+ - `solid-core-ui/src/types/extension-registry.ts`
9
+
10
+ The goal is to support a workflow editor that is:
11
+
12
+ - schema-driven by default
13
+ - dynamically documented
14
+ - extensible through optional UI overrides
15
+ - safe for both `solid-core-ui` and consuming `solid-ui` projects
16
+
17
+ The core principle remains:
18
+
19
+ - backend metadata is the source of truth
20
+ - custom React components are optional escape hatches
21
+ - UI modules resolve component keys, the backend does not import React directly
22
+
23
+ ---
24
+
25
+ ## Design Summary
26
+
27
+ The new contract separates concerns into four layers:
28
+
29
+ 1. `runtime`
30
+ What the node does when executed.
31
+ 2. `authoring`
32
+ How the node is configured in schema-driven forms.
33
+ 3. `documentation`
34
+ What the Docs panel can render.
35
+ 4. `ui`
36
+ Optional extension keys for richer editors and docs renderers.
37
+
38
+ ---
39
+
40
+ ## Object Graph
41
+
42
+ The following diagram shows how the newly added types relate to each other.
43
+
44
+ ```mermaid
45
+ graph TD
46
+ A["WorkflowNodeProviderMetadata"] --> B["authoring: WorkflowNodeAuthoringMetadata"]
47
+ A --> C["runtime: WorkflowNodeRuntimeMetadata"]
48
+ A --> D["documentation: WorkflowNodeDocumentationMetadata"]
49
+ A --> E["ui: WorkflowNodeUiMetadata"]
50
+ A --> F["examples: WorkflowNodeExampleDefinition[]"]
51
+ A --> G["metrics: WorkflowNodeMetricDefinition[]"]
52
+ A --> H["definitions: WorkflowNodeReferenceDefinition[]"]
53
+ A --> I["configSchema / uiSchema / outputSchema"]
54
+
55
+ B --> B1["defaultConfiguration"]
56
+ B --> B2["configurationFields: WorkflowNodeConfigurationFieldDefinition[]"]
57
+ B --> B3["childSlots: WorkflowNodeChildSlotDefinition[]"]
58
+ B --> B4["outputs: WorkflowNodeOutputDefinition[]"]
59
+ B --> B5["supportsExpressions / retry / timeout / onError / etc."]
60
+
61
+ B2 --> B2a["valueType: WorkflowNodeConfigurationValueType"]
62
+ B2 --> B2b["extensionComponentKey?"]
63
+ B2 --> B2c["schema / uiSchema"]
64
+
65
+ B3 --> B3a["sequence"]
66
+ B3 --> B3b["branch-collection"]
67
+
68
+ D --> D1["summary"]
69
+ D --> D2["sections: WorkflowNodeDocumentationSection[]"]
70
+ D --> D3["examples: WorkflowNodeExampleDefinition[]"]
71
+ D --> D4["outputs: WorkflowNodeOutputDefinition[]"]
72
+ D --> D5["metrics: WorkflowNodeMetricDefinition[]"]
73
+ D --> D6["definitions: WorkflowNodeReferenceDefinition[]"]
74
+
75
+ E --> E1["editorComponentKey"]
76
+ E --> E2["docsComponentKey"]
77
+ E --> E3["paletteComponentKey"]
78
+ E --> E4["fieldComponentKeys"]
79
+ E --> E5["layoutHints"]
80
+
81
+ J["WorkflowNodeMetadataResponse"] --> A
82
+
83
+ K["solid-core-ui ExtensionComponentTypes"] --> K1["workflowNodeEditor"]
84
+ K --> K2["workflowNodeDocs"]
85
+ K --> K3["workflowNodeFieldEditor"]
86
+ K --> K4["workflowNodePaletteCard"]
87
+
88
+ E1 -.resolved by.-> K1
89
+ E2 -.resolved by.-> K2
90
+ B2b -.resolved by.-> K3
91
+ E3 -.resolved by.-> K4
92
+ ```
93
+
94
+ ### Hierarchy in words
95
+
96
+ At the top level:
97
+
98
+ - `WorkflowNodeProviderMetadata` is the main backend contract for one node type
99
+ - `WorkflowNodeMetadataResponse` is the client-facing shape that can expose that metadata to the UI
100
+
101
+ Inside node metadata:
102
+
103
+ - `authoring` drives schema-based form editing
104
+ - `runtime` describes execution behavior hints
105
+ - `documentation` drives the Docs panel
106
+ - `ui` provides optional extension keys and layout hints
107
+
108
+ Inside authoring:
109
+
110
+ - `configurationFields` define editable properties
111
+ - each property can use `WorkflowNodeConfigurationValueType`
112
+ - each property can optionally point to a field-level extension component
113
+ - `childSlots` define control-node nesting structure
114
+ - `outputs` define what downstream nodes can reference
115
+
116
+ Inside documentation:
117
+
118
+ - sections, examples, outputs, metrics, and definitions can all be rendered dynamically
119
+
120
+ On the frontend:
121
+
122
+ - `workflowNodeEditor` is the full-node editor escape hatch
123
+ - `workflowNodeDocs` is the custom docs renderer escape hatch
124
+ - `workflowNodeFieldEditor` is the preferred field-level override
125
+ - `workflowNodePaletteCard` customizes node selection/palette cards
126
+
127
+ ### Runtime execution graph
128
+
129
+ The following smaller diagram shows how the runtime-side workflow types fit together during actual execution.
130
+
131
+ ```mermaid
132
+ graph TD
133
+ A["WorkflowDefinitionDsl"] --> B["WorkflowNodeDefinition[]"]
134
+ B --> C["WorkflowRuntimeContext"]
135
+ C --> D["WorkflowNodeExecutionContext"]
136
+
137
+ D --> E["WorkflowNodeHandler.execute(...)"]
138
+ E --> F["WorkflowNodeHandlerResult"]
139
+
140
+ C --> G["input"]
141
+ C --> H["variables"]
142
+ C --> I["outputs"]
143
+ C --> J["execution: WorkflowExecution"]
144
+ C --> K["stepExecution: WorkflowStepExecution?"]
145
+ C --> L["item / index / parentNodeId"]
146
+
147
+ D --> M["expression resolver"]
148
+ D --> N["runNodes(...)"]
149
+ D --> O["emitLog(...)"]
150
+ D --> P["emitArtifact(...)"]
151
+
152
+ F --> Q["output"]
153
+ F --> R["artifacts"]
154
+ F --> S["status"]
155
+
156
+ O --> T["WorkflowExecutionLog"]
157
+ P --> U["WorkflowExecutionArtifact"]
158
+ Q --> I
159
+ S --> K
160
+
161
+ V["Future: WorkflowExecutionMetric"] -.pending.-> W["metric persistence / telemetry"]
162
+ E -.may emit.-> V
163
+ ```
164
+
165
+ ### Runtime hierarchy in words
166
+
167
+ At execution time:
168
+
169
+ - `WorkflowDefinitionDsl` is parsed from `definitionYaml` and contains the ordered `WorkflowNodeDefinition[]`
170
+ - the runtime builds a `WorkflowRuntimeContext`
171
+ - when a node is about to run, that becomes a `WorkflowNodeExecutionContext`
172
+ - the node handler executes against that context
173
+ - the result can update:
174
+ - `outputs`
175
+ - `WorkflowStepExecution` status
176
+ - `WorkflowExecutionLog`
177
+ - `WorkflowExecutionArtifact`
178
+
179
+ Important separation:
180
+
181
+ - `WorkflowNodeDefinition` is design-time configuration
182
+ - `WorkflowRuntimeContext` is in-memory execution state
183
+ - `WorkflowExecution`, `WorkflowStepExecution`, logs, and artifacts are persisted runtime records
184
+ - `metrics` are still pending a persistence or telemetry strategy
185
+
186
+ ---
187
+
188
+ ## New Backend Types
189
+
190
+ ### `WorkflowNodeConfigurationValueType`
191
+
192
+ This is the common vocabulary for describing field value shapes across authoring, outputs, and docs.
193
+
194
+ ```ts
195
+ type WorkflowNodeConfigurationValueType =
196
+ | "string"
197
+ | "number"
198
+ | "integer"
199
+ | "boolean"
200
+ | "object"
201
+ | "array"
202
+ | "json"
203
+ | "secret"
204
+ | "expression"
205
+ | "relation"
206
+ | "uri"
207
+ | "any";
208
+ ```
209
+
210
+ Example:
211
+
212
+ ```ts
213
+ const queryFieldType: WorkflowNodeConfigurationValueType = "string";
214
+ const providerFieldType: WorkflowNodeConfigurationValueType = "object";
215
+ const secretFieldType: WorkflowNodeConfigurationValueType = "secret";
216
+ ```
217
+
218
+ Why it matters:
219
+
220
+ - keeps backend and frontend aligned on data type meaning
221
+ - supports form generation
222
+ - supports docs badges such as `String`, `Object`, `URI`, `Secret`
223
+
224
+ ---
225
+
226
+ ### `WorkflowNodeProviderMetadata`
227
+
228
+ This is now the canonical metadata contract for one node type.
229
+
230
+ Example:
231
+
232
+ ```ts
233
+ const httpRequestNodeMetadata: WorkflowNodeProviderMetadata = {
234
+ type: "http.request",
235
+ kind: "task",
236
+ version: "1.0.0",
237
+ category: "integration",
238
+ subcategory: "http",
239
+ label: "HTTP Request",
240
+ description: "Execute an outbound HTTP request and expose the response.",
241
+ icon: "globe",
242
+ tags: ["http", "api", "integration"],
243
+ aliases: ["http.fetch"],
244
+ configSchema: {
245
+ type: "object",
246
+ required: ["uri"],
247
+ properties: {
248
+ method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"] },
249
+ uri: { type: "string" },
250
+ headers: { type: "object" },
251
+ body: {},
252
+ timeoutMs: { type: "number" }
253
+ }
254
+ },
255
+ uiSchema: {
256
+ "ui:order": ["method", "uri", "headers", "body", "timeoutMs"]
257
+ },
258
+ outputSchema: {
259
+ type: "object",
260
+ properties: {
261
+ ok: { type: "boolean" },
262
+ status: { type: "number" },
263
+ headers: { type: "object" },
264
+ body: {}
265
+ }
266
+ },
267
+ examples: [
268
+ {
269
+ key: "simple-get",
270
+ label: "Simple GET request",
271
+ language: "json",
272
+ snippet: "{\"method\":\"GET\",\"uri\":\"{{ inputs.endpoint }}\"}",
273
+ configurationOnly: true
274
+ }
275
+ ],
276
+ metrics: [
277
+ {
278
+ key: "http.request.duration",
279
+ label: "Request duration",
280
+ type: "timer",
281
+ unit: "ms"
282
+ }
283
+ ],
284
+ definitions: [
285
+ {
286
+ key: "success-status-behavior",
287
+ label: "Success status behavior",
288
+ content: "When configured, the node treats only the given status codes as successful."
289
+ }
290
+ ],
291
+ authoring: {
292
+ supportsExpressions: true,
293
+ supportsRetryPolicy: true,
294
+ supportsTimeoutMs: true,
295
+ supportsOnError: true,
296
+ supportsDisableToggle: true,
297
+ supportsName: true,
298
+ supportsDescription: true
299
+ },
300
+ runtime: {
301
+ emitsLogs: true,
302
+ emitsArtifacts: false,
303
+ deterministicOutputs: false,
304
+ executionMode: "task",
305
+ successStatuses: ["success"]
306
+ },
307
+ documentation: {
308
+ summary: "Call an API, capture the response, and expose it to downstream nodes."
309
+ },
310
+ ui: {
311
+ defaultEditorMode: "schema",
312
+ editorComponentKey: "workflow.node.httpRequest.editor",
313
+ docsComponentKey: "workflow.node.httpRequest.docs",
314
+ paletteComponentKey: "workflow.node.httpRequest.palette",
315
+ modalSize: "xl"
316
+ }
317
+ };
318
+ ```
319
+
320
+ Why it matters:
321
+
322
+ - one object can power Code, Flow, and Docs
323
+ - allows core tasks and consuming-project tasks to look uniform
324
+ - enables future API endpoints such as `GET /workflow-node-types`
325
+
326
+ ---
327
+
328
+ ### `WorkflowNodeChildSlotDefinition`
329
+
330
+ Describes how a control node owns nested node collections.
331
+
332
+ Example for an `if` node:
333
+
334
+ ```ts
335
+ const ifChildSlots: WorkflowNodeChildSlotDefinition[] = [
336
+ {
337
+ key: "then",
338
+ label: "Then branch",
339
+ description: "Runs when the condition evaluates to true.",
340
+ kind: "sequence",
341
+ required: true,
342
+ minItems: 1
343
+ },
344
+ {
345
+ key: "else",
346
+ label: "Else branch",
347
+ description: "Runs when the condition evaluates to false.",
348
+ kind: "sequence",
349
+ required: false
350
+ }
351
+ ];
352
+ ```
353
+
354
+ Example for a `parallel` node:
355
+
356
+ ```ts
357
+ const parallelChildSlots: WorkflowNodeChildSlotDefinition[] = [
358
+ {
359
+ key: "branches",
360
+ label: "Parallel branches",
361
+ description: "Each branch runs concurrently and contains its own ordered node list.",
362
+ kind: "branch-collection",
363
+ required: true,
364
+ minItems: 1
365
+ }
366
+ ];
367
+ ```
368
+
369
+ Why it matters:
370
+
371
+ - tells the Flow editor which nested containers to render
372
+ - keeps control-node authoring declarative
373
+ - avoids hardcoding `then`, `else`, `children`, `branches` everywhere
374
+
375
+ ---
376
+
377
+ ### `WorkflowNodeConfigurationFieldDefinition`
378
+
379
+ Describes one configurable field for schema-driven authoring.
380
+
381
+ Example:
382
+
383
+ ```ts
384
+ const uriField: WorkflowNodeConfigurationFieldDefinition = {
385
+ key: "uri",
386
+ label: "Request URI",
387
+ description: "The target endpoint for the request.",
388
+ valueType: "uri",
389
+ required: true,
390
+ path: "uri",
391
+ expressionAllowed: true,
392
+ secretAllowed: false,
393
+ examples: ["https://example.com", "{{ inputs.endpoint }}"],
394
+ group: "Request",
395
+ widgetHint: "text",
396
+ schema: {
397
+ type: "string"
398
+ },
399
+ uiSchema: {
400
+ "ui:placeholder": "https://api.example.com/orders"
401
+ }
402
+ };
403
+ ```
404
+
405
+ Example with an escape-hatch field renderer:
406
+
407
+ ```ts
408
+ const headersField: WorkflowNodeConfigurationFieldDefinition = {
409
+ key: "headers",
410
+ label: "Headers",
411
+ description: "Optional request headers.",
412
+ valueType: "object",
413
+ path: "headers",
414
+ expressionAllowed: true,
415
+ group: "Request",
416
+ widgetHint: "key-value-editor",
417
+ extensionComponentKey: "workflow.node.field.headersEditor"
418
+ };
419
+ ```
420
+
421
+ Why it matters:
422
+
423
+ - default form generation happens from these definitions
424
+ - special UX can still be plugged in at the field level
425
+ - supports property tables in the Docs panel
426
+
427
+ ---
428
+
429
+ ### `WorkflowNodeOutputDefinition`
430
+
431
+ Describes one named output exposed by a node.
432
+
433
+ Example:
434
+
435
+ ```ts
436
+ const httpOutputs: WorkflowNodeOutputDefinition[] = [
437
+ {
438
+ key: "status",
439
+ label: "HTTP status",
440
+ description: "Status code returned by the remote server.",
441
+ valueType: "integer",
442
+ path: "status",
443
+ required: true
444
+ },
445
+ {
446
+ key: "body",
447
+ label: "Response body",
448
+ description: "Parsed response body.",
449
+ valueType: "any",
450
+ path: "body"
451
+ }
452
+ ];
453
+ ```
454
+
455
+ Why it matters:
456
+
457
+ - powers downstream autocomplete such as `{{ outputs.makeRequest.status }}`
458
+ - powers output docs
459
+ - keeps output semantics explicit instead of implied only by runtime code
460
+
461
+ ---
462
+
463
+ ### `WorkflowNodeMetricDefinition`
464
+
465
+ Describes metrics that a node may emit or contribute to.
466
+
467
+ Example:
468
+
469
+ ```ts
470
+ const httpMetrics: WorkflowNodeMetricDefinition[] = [
471
+ {
472
+ key: "http.request.duration",
473
+ label: "Request duration",
474
+ description: "Measures the end-to-end request duration.",
475
+ type: "timer",
476
+ unit: "ms",
477
+ tags: ["http", "latency"]
478
+ },
479
+ {
480
+ key: "http.request.error.count",
481
+ label: "Request errors",
482
+ description: "Counts request failures.",
483
+ type: "counter",
484
+ tags: ["http", "errors"]
485
+ }
486
+ ];
487
+ ```
488
+
489
+ Why it matters:
490
+
491
+ - lets the Docs panel show observability affordances
492
+ - helps future execution dashboards stay aligned with task metadata
493
+
494
+ ---
495
+
496
+ ### `WorkflowNodeExampleDefinition`
497
+
498
+ Represents a runnable or illustrative example.
499
+
500
+ Example:
501
+
502
+ ```ts
503
+ const simpleExample: WorkflowNodeExampleDefinition = {
504
+ key: "simple-log",
505
+ label: "Simple log statement",
506
+ description: "Minimal log task example.",
507
+ language: "json",
508
+ snippet: "{\"message\":\"Hello {{ inputs.name }}\"}",
509
+ configurationOnly: true
510
+ };
511
+ ```
512
+
513
+ Flow-level example:
514
+
515
+ ```ts
516
+ const fullFlowExample: WorkflowNodeExampleDefinition = {
517
+ key: "health-check-flow",
518
+ label: "Health check flow",
519
+ description: "Make a request and log the status code.",
520
+ language: "json",
521
+ snippet: "{\n \"nodes\": [\n {\n \"id\": \"makeRequest\",\n \"kind\": \"task\",\n \"type\": \"http.request\",\n \"configuration\": {\n \"uri\": \"{{ inputs.uri }}\"\n }\n }\n ]\n}"
522
+ };
523
+ ```
524
+
525
+ Why it matters:
526
+
527
+ - docs become immediately practical
528
+ - examples can later power “insert sample configuration” actions
529
+
530
+ ---
531
+
532
+ ### `WorkflowNodeReferenceDefinition`
533
+
534
+ Represents richer supporting definitions, reference cards, or embedded sub-docs.
535
+
536
+ Example:
537
+
538
+ ```ts
539
+ const pgVectorDefinition: WorkflowNodeReferenceDefinition = {
540
+ key: "pgvector-connection",
541
+ label: "PGVector connection definition",
542
+ description: "Fields required when using the PGVector embedding store.",
543
+ content: "The PGVector provider needs host, port, user, password, database, and table.",
544
+ schema: {
545
+ type: "object",
546
+ required: ["host", "port", "database", "table"]
547
+ },
548
+ examples: [
549
+ {
550
+ key: "pgvector-sample",
551
+ label: "PGVector sample",
552
+ language: "json",
553
+ snippet: "{\"host\":\"localhost\",\"port\":5432,\"database\":\"postgres\",\"table\":\"embeddings\"}",
554
+ configurationOnly: true
555
+ }
556
+ ]
557
+ };
558
+ ```
559
+
560
+ Why it matters:
561
+
562
+ - supports the richer Kestra-style docs experience
563
+ - lets one task document nested definition families cleanly
564
+
565
+ ---
566
+
567
+ ### `WorkflowNodeDocumentationSection`
568
+
569
+ Represents one named section in the Docs panel.
570
+
571
+ Example:
572
+
573
+ ```ts
574
+ const docsSections: WorkflowNodeDocumentationSection[] = [
575
+ {
576
+ key: "summary",
577
+ label: "Summary",
578
+ markdown: "Calls an HTTP endpoint and exposes the response to downstream nodes.",
579
+ initiallyExpanded: true
580
+ },
581
+ {
582
+ key: "error-behavior",
583
+ label: "Error behavior",
584
+ markdown: "Network failures and timeout failures cause the node to fail."
585
+ }
586
+ ];
587
+ ```
588
+
589
+ Why it matters:
590
+
591
+ - keeps docs structured instead of one long markdown blob
592
+ - supports stable tabs, accordions, and search anchors later
593
+
594
+ ---
595
+
596
+ ### `WorkflowNodeAuthoringMetadata`
597
+
598
+ Defines the schema-driven authoring experience.
599
+
600
+ Example:
601
+
602
+ ```ts
603
+ const httpAuthoring: WorkflowNodeAuthoringMetadata = {
604
+ defaultConfiguration: {
605
+ method: "GET",
606
+ headers: {},
607
+ timeoutMs: 30000
608
+ },
609
+ configurationFields: [
610
+ {
611
+ key: "method",
612
+ label: "Method",
613
+ valueType: "string",
614
+ required: false,
615
+ enumValues: ["GET", "POST", "PUT", "PATCH", "DELETE"],
616
+ defaultValue: "GET",
617
+ group: "Request"
618
+ },
619
+ {
620
+ key: "uri",
621
+ label: "URI",
622
+ valueType: "uri",
623
+ required: true,
624
+ expressionAllowed: true,
625
+ group: "Request"
626
+ }
627
+ ],
628
+ outputs: [
629
+ {
630
+ key: "status",
631
+ label: "Status",
632
+ valueType: "integer",
633
+ required: true
634
+ }
635
+ ],
636
+ supportsExpressions: true,
637
+ supportsRetryPolicy: true,
638
+ supportsTimeoutMs: true,
639
+ supportsOnError: true,
640
+ supportsDisableToggle: true,
641
+ supportsName: true,
642
+ supportsDescription: true,
643
+ searchableText: ["http", "api", "request", "rest"]
644
+ };
645
+ ```
646
+
647
+ Why it matters:
648
+
649
+ - this is the default engine for modal-form node editing
650
+ - lets the editor stay metadata-driven for most nodes
651
+
652
+ ---
653
+
654
+ ### `WorkflowNodeRuntimeMetadata`
655
+
656
+ Describes runtime behavior hints.
657
+
658
+ Example:
659
+
660
+ ```ts
661
+ const forEachRuntime: WorkflowNodeRuntimeMetadata = {
662
+ emitsLogs: false,
663
+ emitsArtifacts: false,
664
+ deterministicOutputs: false,
665
+ executionMode: "engine-controlled",
666
+ successStatuses: ["success", "skipped"]
667
+ };
668
+ ```
669
+
670
+ Why it matters:
671
+
672
+ - separates runtime semantics from docs and authoring concerns
673
+ - especially useful for control nodes where the engine owns traversal
674
+
675
+ ---
676
+
677
+ ### `WorkflowNodeDocumentationMetadata`
678
+
679
+ Bundles the content needed for the Docs panel.
680
+
681
+ Example:
682
+
683
+ ```ts
684
+ const searchNodeDocs: WorkflowNodeDocumentationMetadata = {
685
+ summary: "Search an embedding store and return ranked matches.",
686
+ sections: [
687
+ {
688
+ key: "behavior",
689
+ label: "Behavior",
690
+ markdown: "The node computes embeddings using the configured provider and queries the selected store."
691
+ }
692
+ ],
693
+ examples: [
694
+ {
695
+ key: "search-example",
696
+ label: "Search embeddings",
697
+ language: "json",
698
+ snippet: "{\"query\":\"workflow builder\",\"maxResults\":5}",
699
+ configurationOnly: true
700
+ }
701
+ ],
702
+ outputs: [
703
+ {
704
+ key: "results",
705
+ label: "Results",
706
+ valueType: "array"
707
+ }
708
+ ],
709
+ metrics: [
710
+ {
711
+ key: "ai.provider.calls",
712
+ label: "Provider calls",
713
+ type: "counter"
714
+ }
715
+ ],
716
+ definitions: [
717
+ {
718
+ key: "embedding-store-definitions",
719
+ label: "Embedding store definitions",
720
+ content: "Available stores may define different required connection properties."
721
+ }
722
+ ]
723
+ };
724
+ ```
725
+
726
+ Why it matters:
727
+
728
+ - gives the Docs panel a stable API
729
+ - aligns closely with the examples shown in the Kestra screenshots
730
+
731
+ ---
732
+
733
+ ### `WorkflowNodeUiMetadata`
734
+
735
+ Defines optional UI extension keys and layout hints.
736
+
737
+ Example:
738
+
739
+ ```ts
740
+ const httpUi: WorkflowNodeUiMetadata = {
741
+ editorComponentKey: "workflow.node.httpRequest.editor",
742
+ docsComponentKey: "workflow.node.httpRequest.docs",
743
+ paletteComponentKey: "workflow.node.httpRequest.palette",
744
+ defaultEditorMode: "schema",
745
+ fieldComponentKeys: {
746
+ headers: "workflow.node.field.headersEditor",
747
+ body: "workflow.node.field.bodyEditor"
748
+ },
749
+ modalSize: "xl",
750
+ layoutHints: {
751
+ preferredPanel: "flow",
752
+ groupOrder: ["Request", "Authentication", "Advanced"],
753
+ stickySummary: true
754
+ }
755
+ };
756
+ ```
757
+
758
+ Meaning of the fields:
759
+
760
+ - `editorComponentKey`
761
+ Optional full-node editor override.
762
+ - `docsComponentKey`
763
+ Optional docs renderer override.
764
+ - `paletteComponentKey`
765
+ Optional custom card for the node picker/palette.
766
+ - `defaultEditorMode`
767
+ Tells the UI whether the preferred experience is still schema-first or custom-first.
768
+ - `fieldComponentKeys`
769
+ Field-specific escape hatches without replacing the entire node editor.
770
+ - `modalSize`
771
+ Good for large configuration surfaces.
772
+ - `layoutHints`
773
+ Helps the UI arrange content without hardcoding per-node behavior.
774
+
775
+ Why it matters:
776
+
777
+ - keeps the backend decoupled from React
778
+ - gives the UI enough information to resolve optional enhancements
779
+
780
+ ---
781
+
782
+ ### `WorkflowNodeMetadataResponse`
783
+
784
+ Represents the shape the backend can safely expose to clients.
785
+
786
+ Example:
787
+
788
+ ```ts
789
+ const metadataResponse: WorkflowNodeMetadataResponse = {
790
+ type: "http.request",
791
+ kind: "task",
792
+ version: "1.0.0",
793
+ category: "integration",
794
+ subcategory: "http",
795
+ label: "HTTP Request",
796
+ description: "Execute an outbound HTTP request.",
797
+ icon: "globe",
798
+ tags: ["http", "api"],
799
+ configSchema: {
800
+ type: "object",
801
+ required: ["uri"]
802
+ },
803
+ uiSchema: {
804
+ "ui:order": ["method", "uri", "headers", "body"]
805
+ },
806
+ outputSchema: {
807
+ type: "object",
808
+ properties: {
809
+ status: { type: "number" }
810
+ }
811
+ },
812
+ examples: [
813
+ {
814
+ key: "basic",
815
+ label: "Basic request",
816
+ language: "json",
817
+ snippet: "{\"uri\":\"{{ inputs.url }}\"}",
818
+ configurationOnly: true
819
+ }
820
+ ],
821
+ metrics: [
822
+ {
823
+ key: "http.request.duration",
824
+ label: "Request duration",
825
+ type: "timer"
826
+ }
827
+ ],
828
+ definitions: [
829
+ {
830
+ key: "status-definition",
831
+ label: "Status definition",
832
+ content: "HTTP status code returned by the response."
833
+ }
834
+ ],
835
+ authoring: httpAuthoring,
836
+ runtime: {
837
+ emitsLogs: true,
838
+ executionMode: "task"
839
+ },
840
+ documentation: searchNodeDocs,
841
+ ui: httpUi
842
+ };
843
+ ```
844
+
845
+ Why it matters:
846
+
847
+ - good DTO/API shape for the future editor
848
+ - allows UI clients to stay ignorant of server implementation details
849
+
850
+ ---
851
+
852
+ ## Example: Full Core Node Metadata
853
+
854
+ Below is a compact end-to-end example for a core `log.write` node:
855
+
856
+ ```ts
857
+ const logWriteNode: WorkflowNodeProviderMetadata = {
858
+ type: "log.write",
859
+ kind: "task",
860
+ version: "1.0.0",
861
+ category: "core",
862
+ label: "Write Log",
863
+ description: "Write a log line into the workflow execution log.",
864
+ icon: "file-text",
865
+ tags: ["log", "observability"],
866
+ configSchema: {
867
+ type: "object",
868
+ required: ["message"],
869
+ properties: {
870
+ level: { type: "string", enum: ["debug", "info", "warn", "error"] },
871
+ message: { type: "string" },
872
+ metadata: { type: "object" }
873
+ }
874
+ },
875
+ authoring: {
876
+ defaultConfiguration: {
877
+ level: "info"
878
+ },
879
+ configurationFields: [
880
+ {
881
+ key: "level",
882
+ label: "Level",
883
+ valueType: "string",
884
+ enumValues: ["debug", "info", "warn", "error"],
885
+ defaultValue: "info",
886
+ group: "Message"
887
+ },
888
+ {
889
+ key: "message",
890
+ label: "Message",
891
+ valueType: "string",
892
+ required: true,
893
+ expressionAllowed: true,
894
+ group: "Message"
895
+ },
896
+ {
897
+ key: "metadata",
898
+ label: "Metadata",
899
+ valueType: "object",
900
+ expressionAllowed: true,
901
+ group: "Advanced"
902
+ }
903
+ ],
904
+ outputs: [
905
+ {
906
+ key: "message",
907
+ label: "Rendered message",
908
+ valueType: "string"
909
+ },
910
+ {
911
+ key: "level",
912
+ label: "Rendered level",
913
+ valueType: "string"
914
+ }
915
+ ],
916
+ supportsExpressions: true,
917
+ supportsDisableToggle: true,
918
+ supportsName: true,
919
+ supportsDescription: true
920
+ },
921
+ runtime: {
922
+ emitsLogs: true,
923
+ emitsArtifacts: false,
924
+ deterministicOutputs: true,
925
+ executionMode: "task",
926
+ successStatuses: ["success"]
927
+ },
928
+ documentation: {
929
+ summary: "A lightweight task for debug messages, audit breadcrumbs, and quick verification.",
930
+ sections: [
931
+ {
932
+ key: "usage",
933
+ label: "Usage",
934
+ markdown: "Use this task to inspect expressions and execution values during development."
935
+ }
936
+ ],
937
+ examples: [
938
+ {
939
+ key: "simple-message",
940
+ label: "Simple message",
941
+ language: "json",
942
+ snippet: "{\"message\":\"Hello {{ inputs.name }}\"}",
943
+ configurationOnly: true
944
+ }
945
+ ],
946
+ outputs: [
947
+ {
948
+ key: "message",
949
+ label: "Message",
950
+ valueType: "string"
951
+ }
952
+ ]
953
+ },
954
+ ui: {
955
+ defaultEditorMode: "schema",
956
+ modalSize: "lg",
957
+ layoutHints: {
958
+ preferredPanel: "flow",
959
+ groupOrder: ["Message", "Advanced"]
960
+ }
961
+ }
962
+ };
963
+ ```
964
+
965
+ ---
966
+
967
+ ## New Frontend Extension Component Types
968
+
969
+ The following lines were added to:
970
+
971
+ - `solid-core-ui/src/types/extension-registry.ts`
972
+
973
+ ```ts
974
+ workflowNodeEditor: "workflowNodeEditor",
975
+ workflowNodeDocs: "workflowNodeDocs",
976
+ workflowNodeFieldEditor: "workflowNodeFieldEditor",
977
+ workflowNodePaletteCard: "workflowNodePaletteCard",
978
+ ```
979
+
980
+ Each one is documented below.
981
+
982
+ ---
983
+
984
+ ### `workflowNodeEditor`
985
+
986
+ Line:
987
+
988
+ ```ts
989
+ workflowNodeEditor: "workflowNodeEditor"
990
+ ```
991
+
992
+ Meaning:
993
+
994
+ - registers a full custom node editor experience
995
+ - used only when schema-driven editing is insufficient
996
+ - should be rare
997
+
998
+ When to use:
999
+
1000
+ - deeply nested configurations
1001
+ - highly visual domain-specific editors
1002
+ - tasks that need a specialized multi-step setup flow
1003
+
1004
+ Example registration:
1005
+
1006
+ ```ts
1007
+ {
1008
+ name: "workflow.node.httpRequest.editor",
1009
+ type: ExtensionComponentTypes.workflowNodeEditor,
1010
+ component: HttpRequestNodeEditor
1011
+ }
1012
+ ```
1013
+
1014
+ Expected usage:
1015
+
1016
+ - backend metadata sets `ui.editorComponentKey = "workflow.node.httpRequest.editor"`
1017
+ - the workflow editor resolves that key through the extension registry
1018
+
1019
+ ---
1020
+
1021
+ ### `workflowNodeDocs`
1022
+
1023
+ Line:
1024
+
1025
+ ```ts
1026
+ workflowNodeDocs: "workflowNodeDocs"
1027
+ ```
1028
+
1029
+ Meaning:
1030
+
1031
+ - registers a custom docs renderer for one node type
1032
+ - default docs should still come from metadata
1033
+
1034
+ When to use:
1035
+
1036
+ - interactive docs
1037
+ - searchable nested definitions
1038
+ - complex examples needing special rendering
1039
+
1040
+ Example registration:
1041
+
1042
+ ```ts
1043
+ {
1044
+ name: "workflow.node.search.docs",
1045
+ type: ExtensionComponentTypes.workflowNodeDocs,
1046
+ component: SearchNodeDocsPanel
1047
+ }
1048
+ ```
1049
+
1050
+ Expected usage:
1051
+
1052
+ - backend metadata sets `ui.docsComponentKey = "workflow.node.search.docs"`
1053
+ - otherwise the generic Docs renderer uses `documentation`, `examples`, `outputs`, `metrics`, and `definitions`
1054
+
1055
+ ---
1056
+
1057
+ ### `workflowNodeFieldEditor`
1058
+
1059
+ Line:
1060
+
1061
+ ```ts
1062
+ workflowNodeFieldEditor: "workflowNodeFieldEditor"
1063
+ ```
1064
+
1065
+ Meaning:
1066
+
1067
+ - registers a field-level override for one configuration field
1068
+ - this is the preferred escape hatch before replacing the whole node editor
1069
+
1070
+ When to use:
1071
+
1072
+ - key/value header editors
1073
+ - auth setup widgets
1074
+ - provider pickers
1075
+ - nested object builders
1076
+
1077
+ Example registration:
1078
+
1079
+ ```ts
1080
+ {
1081
+ name: "workflow.node.field.headersEditor",
1082
+ type: ExtensionComponentTypes.workflowNodeFieldEditor,
1083
+ component: HeadersKeyValueEditor
1084
+ }
1085
+ ```
1086
+
1087
+ Expected usage:
1088
+
1089
+ - backend metadata sets either:
1090
+ - `WorkflowNodeConfigurationFieldDefinition.extensionComponentKey`
1091
+ - or `WorkflowNodeUiMetadata.fieldComponentKeys["headers"]`
1092
+
1093
+ This is the main UI override pattern we want to encourage.
1094
+
1095
+ ---
1096
+
1097
+ ### `workflowNodePaletteCard`
1098
+
1099
+ Line:
1100
+
1101
+ ```ts
1102
+ workflowNodePaletteCard: "workflowNodePaletteCard"
1103
+ ```
1104
+
1105
+ Meaning:
1106
+
1107
+ - registers a custom visual representation for the node picker / palette / insert dialog
1108
+
1109
+ When to use:
1110
+
1111
+ - rich node cards with icons, tags, quick examples, or usage hints
1112
+ - domain-specific palettes where discoverability matters
1113
+
1114
+ Example registration:
1115
+
1116
+ ```ts
1117
+ {
1118
+ name: "workflow.node.httpRequest.palette",
1119
+ type: ExtensionComponentTypes.workflowNodePaletteCard,
1120
+ component: HttpRequestPaletteCard
1121
+ }
1122
+ ```
1123
+
1124
+ Expected usage:
1125
+
1126
+ - backend metadata sets `ui.paletteComponentKey = "workflow.node.httpRequest.palette"`
1127
+ - otherwise the default palette card can be rendered from `label`, `description`, `category`, `icon`, and `tags`
1128
+
1129
+ ---
1130
+
1131
+ ## Recommended Precedence Rules
1132
+
1133
+ To keep behavior predictable, the workflow UI should use this order:
1134
+
1135
+ 1. render from backend metadata only
1136
+ 2. if a field-level override exists, use `workflowNodeFieldEditor`
1137
+ 3. if a full-node editor override exists, use `workflowNodeEditor`
1138
+ 4. if a docs override exists, use `workflowNodeDocs`
1139
+ 5. if a palette override exists, use `workflowNodePaletteCard`
1140
+
1141
+ This preserves the intended design:
1142
+
1143
+ - schema-driven first
1144
+ - extension-driven only when needed
1145
+
1146
+ ---
1147
+
1148
+ ## Recommended First Implementations
1149
+
1150
+ The first core nodes to enrich with this metadata should likely be:
1151
+
1152
+ 1. `log.write`
1153
+ 2. `http.request`
1154
+ 3. `if`
1155
+ 4. `forEach`
1156
+ 5. `parallel`
1157
+
1158
+ Suggested rollout:
1159
+
1160
+ 1. enrich backend metadata for `log.write`
1161
+ 2. build a generic schema-driven modal editor
1162
+ 3. build a generic docs panel
1163
+ 4. add one field-level override example
1164
+ 5. only after that introduce full custom node editors if still necessary
1165
+
1166
+ ---
1167
+
1168
+ ## Pending Features And Open Decisions
1169
+
1170
+ These items are intentionally not fully implemented yet and should be treated as pending design or delivery work.
1171
+
1172
+ ### Metrics persistence and observability
1173
+
1174
+ The current `metrics` metadata is useful as a node capability declaration, but it does not become operationally valuable until we choose how metrics are emitted and stored.
1175
+
1176
+ Current status:
1177
+
1178
+ - `WorkflowNodeMetricDefinition` documents what a node may measure
1179
+ - the runtime does not yet persist metrics into a dedicated table
1180
+ - the runtime does not yet publish metrics to a monitoring backend
1181
+ - the execution UI does not yet visualize metrics
1182
+
1183
+ Practical implication:
1184
+
1185
+ - today, `metrics` is mainly design metadata for docs and future observability
1186
+ - for production value, we need one or both of the following:
1187
+ - persist metrics in a workflow runtime table for querying and dashboards
1188
+ - emit metrics to an external observability system
1189
+
1190
+ Suggested next-step options:
1191
+
1192
+ 1. Add a dedicated workflow execution metric table, for example `workflowExecutionMetric`
1193
+ 2. Extend execution logs with metric-shaped entries as a simpler interim step
1194
+ 3. Emit metrics to an external telemetry backend while keeping only summaries in SolidX
1195
+
1196
+ Recommended direction:
1197
+
1198
+ - keep `metrics` in the node contract now
1199
+ - treat runtime metric storage as a separate pending feature
1200
+ - avoid overbuilding the metrics UI before persistence/emission strategy is agreed
1201
+
1202
+ ### Node metadata API
1203
+
1204
+ Pending:
1205
+
1206
+ - dedicated API endpoint for listing workflow node metadata for the editor
1207
+ - stable DTO mapping from provider metadata to client-safe response payloads
1208
+
1209
+ ### Expression-aware autocomplete
1210
+
1211
+ Pending:
1212
+
1213
+ - Monaco autocomplete based on workflow DSL plus node metadata
1214
+ - expression suggestions for `inputs`, `outputs`, `execution`, `trigger`, and loop context
1215
+
1216
+ ### Generic workflow docs renderer
1217
+
1218
+ Pending:
1219
+
1220
+ - reusable renderer for `summary`, `sections`, `examples`, `outputs`, `metrics`, and `definitions`
1221
+ - search/filter experience inside the Docs panel
1222
+
1223
+ ### Flow editor integration
1224
+
1225
+ Pending:
1226
+
1227
+ - mapping `childSlots` metadata into React Flow containers and insertion affordances
1228
+ - node modal editor using schema-driven forms by default
1229
+
1230
+ ### Blueprints
1231
+
1232
+ Pending:
1233
+
1234
+ - reintroduce `WorkflowBlueprint` as a first-class concept after the core definition/execution editor is stable
1235
+ - define blueprint metadata shape for starter workflows, tags, categories, and descriptions
1236
+ - decide whether blueprints live as:
1237
+ - dedicated persisted records
1238
+ - metadata-backed JSON assets only
1239
+ - or both
1240
+ - support blueprint browsing in the workflow editor
1241
+ - support “create from blueprint” flows
1242
+ - support core-provided and consuming-project-provided blueprint packs
1243
+
1244
+ Recommended direction:
1245
+
1246
+ - treat blueprints as curated starter workflows, not a separate execution concept
1247
+ - keep them aligned with the same workflow DSL as normal definitions
1248
+ - design the Blueprints panel after the node metadata API and generic docs renderer are in place
1249
+ - defer full blueprint management UX until the definition editor foundation is stable
1250
+
1251
+ ---
1252
+
1253
+ ## Final Guidance
1254
+
1255
+ This contract is intentionally designed so that:
1256
+
1257
+ - the backend describes node behavior and metadata
1258
+ - the frontend can render most nodes dynamically
1259
+ - `solid-core-ui` can ship polished defaults
1260
+ - consuming `solid-ui` projects can override only the pieces they need
1261
+
1262
+ That keeps the workflow system extensible without making every task implementation expensive.