Portal Community

1. New Node — Minimal Setup

Simple action node with no HIL, no sensitive data. Return Empty.

// MyNode.Config.cs
protected override NodeExecutorManifest? GetNodeExecutorManifest()
    => NodeExecutorManifest.Empty(ProcessElementTypeCode);

2. Field Receiving Upstream Input

Field populated automatically from upstream node's output data bag.

new NodeFieldDescriptor
{
    FieldId          = "recipientId",
    Description      = "User ID resolved from upstream lookup.",
    ExpressionPolicy = new ExpressionPolicy
    {
        EvaluationStage = EvaluationStage.AtInputReady,
        EvaluatorKind   = EvaluatorKind.Template
    },
    DataFlowPolicy = new DataFlowPolicy
    {
        AcceptsUpstreamInput     = true,
        ExcludeFromInputMapping  = false,
        ExcludeFromOutputMapping = true
    },
    HilPolicy      = new HilPolicy { SendToHil = false, DisplayMode = HilDisplayMode.Concealed },
    SecurityPolicy = new SecurityPolicy()
}

3. Output Field for Downstream Nodes

Result produced by executor, passed to downstream nodes, persisted to memory.

new NodeFieldDescriptor
{
    FieldId          = "parsedResult",
    Description      = "Parsed output data for downstream processing.",
    ExpressionPolicy = new ExpressionPolicy
    {
        EvaluationStage = EvaluationStage.AtInputReady,
        EvaluatorKind   = EvaluatorKind.None   // set by executor
    },
    DataFlowPolicy = new DataFlowPolicy
    {
        AcceptsUpstreamInput     = false,
        EmitsToDownstream        = true,
        PersistsToMemory         = true,
        ExcludeFromInputMapping  = true,
        ExcludeFromOutputMapping = false
    },
    HilPolicy      = new HilPolicy { SendToHil = false, DisplayMode = HilDisplayMode.Concealed },
    SecurityPolicy = new SecurityPolicy()
}

4. Credential Field — Maximum Security

Full lockdown — masked, concealed, excluded from all mapping, elevated access required.

new NodeFieldDescriptor
{
    FieldId          = "credentialId",
    Description      = "Vault credential ID resolved via ICredentialResolver.",
    ExpressionPolicy = new ExpressionPolicy
    {
        EvaluationStage = EvaluationStage.AtConfigLoad,
        EvaluatorKind   = EvaluatorKind.Template
    },
    DataFlowPolicy = new DataFlowPolicy
    {
        AcceptsUpstreamInput     = false,
        EmitsToDownstream        = false,
        PersistsToMemory         = false,
        ExcludeFromInputMapping  = true,
        ExcludeFromOutputMapping = true
    },
    HilPolicy = new HilPolicy
    {
        SendToHil   = false,
        DisplayMode = HilDisplayMode.Concealed,
        InputMode   = HilInputMode.Locked,
        Label       = "Credential",
        Description = "Internal vault reference — not shown to reviewers."
    },
    SecurityPolicy = new SecurityPolicy
    {
        MaskInLogs             = true,
        MaskInOutput           = true,
        RequiresElevatedAccess = true
    }
}

5. HIL Context-Only Field

Human sees the value for context but cannot change it.

new NodeFieldDescriptor
{
    FieldId          = "strategy",
    Description      = "Approval strategy — shown in inbox for context.",
    ExpressionPolicy = new ExpressionPolicy
    {
        EvaluationStage = EvaluationStage.AtConfigLoad,
        EvaluatorKind   = EvaluatorKind.Template
    },
    DataFlowPolicy = new DataFlowPolicy
    {
        ExcludeFromInputMapping  = true,
        ExcludeFromOutputMapping = true
    },
    HilPolicy = new HilPolicy
    {
        SendToHil   = true,
        DisplayMode = HilDisplayMode.ReadableContext,
        InputMode   = HilInputMode.Locked,
        Label       = "Approval Strategy",
        Description = "How votes are counted to reach a decision."
    },
    SecurityPolicy = new SecurityPolicy()
}

6. HIL Required Confirmation

Human must explicitly confirm or provide a value before the workflow continues.

new NodeFieldDescriptor
{
    FieldId          = "body",
    Description      = "Message body — human must confirm before sending.",
    ExpressionPolicy = new ExpressionPolicy
    {
        EvaluationStage = EvaluationStage.AtInputReady,
        EvaluatorKind   = EvaluatorKind.Template
    },
    DataFlowPolicy = new DataFlowPolicy
    {
        AcceptsUpstreamInput     = true,
        ExcludeFromInputMapping  = false,
        ExcludeFromOutputMapping = true
    },
    HilPolicy = new HilPolicy
    {
        SendToHil   = true,
        DisplayMode = HilDisplayMode.ReadableContext,
        InputMode   = HilInputMode.RequiredFromHuman,
        Label       = "Message Body",
        Description = "Read the full message. You must confirm it before it is sent."
    },
    SecurityPolicy = new SecurityPolicy()
}

7. Suspending Node with Approval Logic

Full manifest with 48h hard deadline approval suspension.

protected override NodeExecutorManifest? GetNodeExecutorManifest()
    => NodeExecutorManifest.From(
        ProcessElementTypeCode,
        fields: new[]
        {
            // ... field descriptors ...
        },
        suspensionPolicy: new SuspensionPolicy
        {
            TimeoutSeconds               = 172800,             // 48 hours
            TimeoutPortKey               = "expired",
            TimeoutBehavior              = TimeoutBehavior.AbsoluteDeadline,
            ReminderIntervalSeconds      = new[] { 86400, 43200, 3600 },
            SlaThresholdSeconds          = 86400,              // 24h SLA
            EmitSlaBreachEvent           = true,
            AllowAdminForceComplete      = true,
            CapturePreSuspensionSnapshot = true
        }
    );

8. JavaScript Expression Field

Field whose value is computed by a JavaScript snippet from multiple upstream inputs.

new NodeFieldDescriptor
{
    FieldId          = "payload",
    Description      = "Webhook payload built dynamically from upstream inputs.",
    ExpressionPolicy = new ExpressionPolicy
    {
        EvaluationStage = EvaluationStage.AtInputReady,
        EvaluatorKind   = EvaluatorKind.JavaScript
    },
    DataFlowPolicy = new DataFlowPolicy
    {
        AcceptsUpstreamInput     = true,
        ExcludeFromInputMapping  = false,
        ExcludeFromOutputMapping = true
    },
    HilPolicy = new HilPolicy
    {
        SendToHil   = true,
        DisplayMode = HilDisplayMode.ReadableContext,
        InputMode   = HilInputMode.EditableOptional,
        Label       = "Webhook Payload",
        Description = "The JSON payload to send. You may edit before sending."
    },
    SecurityPolicy = new SecurityPolicy()
}
// Config value stored in DB / workflow definition:
// JSON.stringify({ userId: inputs.customerId, amount: inputs.total })

9. Extension JSON Override (No Redeployment)

Override a field's HIL policy for a specific tenant via database without code changes.

{
  "nodeTypeName": "email-smtp",
  "suspensionPolicy": null,
  "fields": [
    {
      "id": "body",
      "hilPolicy": {
        "sendToHil": true,
        "displayMode": "ReadableContext",
        "inputMode": "RequiredFromHuman",
        "label": "Email Body",
        "description": "Compliance requirement: you must confirm every email body."
      }
    }
  ]
}
// Only hilPolicy is overridden. expressionPolicy, dataFlowPolicy, securityPolicy
// keep their code-defined values.

10. Checklist — Adding Manifest to Existing Node