Portal Community

Empty Manifest

NodeExecutorManifest.Empty(ProcessElementTypeCode)

An empty manifest tells the platform: "This node exists and is registered, but has no field policy declarations. Apply defaults for all cross-cutting concerns."

When to use Empty

What the platform does with Empty

ConcernBehaviour with Empty
Expression evaluationNo field-level evaluation occurs
Data flowInput/output mapping skipped; node receives raw data
HIL renderingNo fields sent to human inbox
Security maskingNo masking applied
SuspensionNo timers registered
// StopWorkflow node — no fields, just halts execution
protected override NodeExecutorManifest? GetNodeExecutorManifest()
    => NodeExecutorManifest.Empty(ProcessElementTypeCode);

Full Manifest (From)

NodeExecutorManifest.From(
    ProcessElementTypeCode,
    fields: new[] { /* NodeFieldDescriptor[] */ },
    suspensionPolicy: null  // or: new SuspensionPolicy { ... }
)

A full manifest declares every field the node cares about and, optionally, a SuspensionPolicy if the node pauses and waits for human input.

When to use From

Full example

protected override NodeExecutorManifest? GetNodeExecutorManifest()
    => NodeExecutorManifest.From(
        nodeTypeName: ProcessElementTypeCode,

        fields: new[]
        {
            new NodeFieldDescriptor
            {
                FieldId          = "to",
                Description      = "Recipient address",
                ExpressionPolicy = new ExpressionPolicy
                {
                    EvaluationStage = EvaluationStage.AtInputReady,
                    EvaluatorKind   = EvaluatorKind.Template
                },
                DataFlowPolicy = new DataFlowPolicy
                {
                    AcceptsUpstreamInput     = true,
                    ExcludeFromOutputMapping = true
                },
                HilPolicy = new HilPolicy
                {
                    SendToHil   = true,
                    DisplayMode = HilDisplayMode.ReadableContext,
                    InputMode   = HilInputMode.EditableOptional,
                    Label       = "To"
                },
                SecurityPolicy = new SecurityPolicy()
            }
            // ... more descriptors
        },

        suspensionPolicy: new SuspensionPolicy
        {
            TimeoutSeconds  = 86400,
            TimeoutPortKey  = "expired",
            TimeoutBehavior = TimeoutBehavior.AbsoluteDeadline
        }
        // or: suspensionPolicy: null
    );

Extension JSON (Database Overrides)

Extension JSON does not use "empty" vs "full" — it just lists the fields to add or override. The resolver merges JSON fields with the code manifest; only the properties present in JSON are overridden. Everything else keeps its code-defined values.

{
  "nodeTypeName": "email-smtp",
  "suspensionPolicy": null,
  "fields": [
    {
      "id": "body",
      "hilPolicy": {
        "sendToHil": true,
        "inputMode": "RequiredFromHuman",
        "label": "Email Body",
        "description": "Compliance requires you to confirm every email body."
      }
    }
  ]
}

Registration Flow

1

DI container loads executor assembly

AddSmtpNodeExecutor() or AddExecutorPluginsFromAssembly() registers the executor.

2

GetNodeExecutorManifest() invoked

Called once per executor type. Result stored in NodeFieldManifestRegistry keyed by node type name.

3

Resolver merges at execution time

NodeFieldManifestResolver.GetManifest(nodeTypeName, extensionJson) — code manifest + DB JSON → final resolved manifest.

4

Platform subsystems read the merged result

Expression evaluator, data flow mapper, HIL renderer, security layer, and suspension orchestrator all read from the final manifest.

Null return If GetNodeExecutorManifest() returns null the platform treats it identically to Empty. The base class default returns null. Always return Empty(ProcessElementTypeCode) explicitly to make intent clear.