Skip to main content

Workflows

The Workflows module provides a powerful event-driven automation engine that lets departments subscribe to system events, transform event data using templates, and execute configurable actions such as sending emails, SMS messages, calling APIs, posting to chat platforms, or uploading files to cloud storage. It is managed by the WorkflowsController.

Authorization: Department Admins only. Access is controlled via ClaimsAuthorizationHelper.IsUserDepartmentAdmin().

Navigation: Department Menu → Workflows

Overview

Workflows follow an Event → Transform → Action pipeline:

System Event Occurs → Match Active Workflows → Render Scriban Templates → Execute Action Steps → Log Results
  1. A system event fires (e.g., a new call is created, a unit changes status)
  2. Resgrid evaluates all active workflows for the department that subscribe to that event type
  3. For each matching workflow, the event data is transformed using user-defined Scriban templates
  4. The rendered output is passed to the configured action (send email, call API, etc.)
  5. Every execution is fully audited with run logs and per-step details

Workflow execution is asynchronous — events are enqueued to a message queue and processed in the background, ensuring no impact on the responsiveness of the core system.

Workflow List (Index)

Displays all workflows configured for the department with:

  • Status indicators — Enabled/disabled toggle
  • Last run status — Color-coded badge (green = success, yellow = retrying, red = failed)
  • Success rate — Percentage badge based on recent runs
  • Quick links to create, edit, view runs, and enable/disable workflows

Creating a Workflow

Navigate to Department → Workflows and click New Workflow.

Workflow Fields

FieldRequiredDescription
NameYesA descriptive name for the workflow (max 250 characters)
DescriptionNoOptional description of the workflow's purpose (max 1000 characters)
Trigger Event TypeYesThe system event that triggers this workflow (see Trigger Event Types)
EnabledYesWhether the workflow is active (default: enabled)
Max Retry CountNoNumber of retry attempts on failure (default: 3, maximum: 5)
Retry Backoff Base (seconds)NoBase delay for exponential backoff between retries (default: 5)

Editing a Workflow

The edit view allows you to modify the workflow settings and manage its steps inline.

Workflow Steps

Each workflow can have one or more steps that execute in sequence. Each step defines:

FieldRequiredDescription
Action TypeYesThe action to perform (see Action Types)
CredentialConditionalThe stored credential to use (filtered by compatible credential types)
Output TemplateYesA Scriban template that transforms event data into the action's input
Action ConfigConditionalAction-specific settings (e.g., email subject/recipients, API URL, S3 bucket)
EnabledYesWhether this step is active (default: enabled)
Step OrderYesExecution order when multiple steps exist

Steps are executed sequentially in Step Order. If a step fails, subsequent steps still execute (failures are logged per-step). Disabled steps are skipped.

Template Editor

The workflow editor embeds an Ace Editor with Scriban syntax highlighting for editing output templates. Features include:

  • Syntax highlighting for Scriban template syntax ({{ variable }}, {% if %}, loops, etc.)
  • Variable side panel — Lists all available template variables for the selected trigger event type (e.g., for CallAdded: {{ call.name }}, {{ call.nature }}, {{ call.address }}, etc.). Array variables are visually distinguished with a list icon and an "array" badge. Clicking an array variable inserts a Scriban for loop snippet instead of a simple variable reference.
  • Preview button — Renders the template with sample data and shows the output inline
  • Test button — Triggers a real execution with sample data and shows the run result
Iterating Over Collections

Some event variables are arrays (e.g., call.unit_dispatches, call.notes_list). When you click an array variable in the side panel, a for loop snippet is inserted automatically:

{{ for unit in call.unit_dispatches }}
{{ unit.unit_name }}
{{ end }}

Hover over an array variable to see the child properties available inside each iteration.

See the Workflows Configuration page for the full template variable reference.

Trigger Event Types

Workflows can subscribe to any of the following system events:

EventDescription
Call AddedNew call/dispatch created
Call UpdatedExisting call updated
Call ClosedCall closed
Unit Status ChangedUnit status changed
Personnel Staffing ChangedPersonnel staffing level changed
Personnel Status ChangedPersonnel action status changed
User CreatedNew user added to department
User Assigned to GroupUser assigned to a group
Document AddedDocument uploaded
Note AddedNote created
Unit AddedUnit created
Log AddedLog entry created
Calendar Event AddedCalendar event created
Calendar Event UpdatedCalendar event updated
Shift CreatedShift created
Shift UpdatedShift updated
Resource Order AddedResource order created
Shift Trade RequestedShift trade requested
Shift Trade FilledShift trade filled
Message SentNew message sent
Training AddedTraining created
Training UpdatedTraining updated
Inventory AdjustedInventory quantity changed
Certification ExpiringPersonnel certification nearing expiry
Form SubmittedForm submitted
Personnel Role ChangedUser role assignment changed
Group AddedDepartment group created
Group UpdatedDepartment group updated

Action Types

Each workflow step supports one of the following action types:

Communication Actions

ActionDescriptionCredential Required
Send EmailSends an email via SMTP. Template renders the HTML email body. Rendered HTML is automatically sanitized (scripts, iframes, event handlers, etc. are stripped).SMTP (host, port, username, password, from address)
Send SMSSends an SMS message via Twilio. Template renders the message body.Twilio (Account SID, Auth Token, from number)
Send Teams MessagePosts a message to Microsoft Teams via Incoming Webhook. Template renders the message body (plain text or Adaptive Card JSON). Webhook URL must target .webhook.office.com or .logic.azure.com.Microsoft Teams (webhook URL)
Send Slack MessagePosts a message to Slack via Incoming Webhook. Template renders the message text (supports Slack mrkdwn). Webhook URL must target hooks.slack.com.Slack (webhook URL)
Send Discord MessagePosts a message to Discord via Webhook. Template renders the message content (supports embed JSON). Webhook URL must target discord.com or discordapp.com with path /api/webhooks/.Discord (webhook URL)

API Actions

ActionDescriptionCredential Required
Call API (GET)Sends an HTTP GET request to a URL. HTTPS only; private/internal IPs blocked.Optional (Bearer, Basic, or API Key)
Call API (POST)Sends an HTTP POST request. Template renders the request body. HTTPS only; private/internal IPs blocked.Optional
Call API (PUT)Sends an HTTP PUT request. Template renders the request body. HTTPS only; private/internal IPs blocked.Optional
Call API (DELETE)Sends an HTTP DELETE request. HTTPS only; private/internal IPs blocked.Optional

File Upload Actions

ActionDescriptionCredential Required
Upload File (FTP)Uploads a file via FTP. Template renders the file content.FTP (host, port, username, password)
Upload File (SFTP)Uploads a file via SFTP. Template renders the file content.SFTP (host, port, username, password/key)
Upload File (S3)Uploads a file to Amazon S3. Template renders the file content.AWS S3 (Access Key, Secret Key, Region, Bucket)
Upload File (Azure Blob)Uploads a file to Azure Blob Storage. Template renders the file content.Azure Blob Storage (Connection String, Container Name)
Upload File (Box)Uploads a file to Box. Template renders the file content.Box (JWT credentials or Developer Token)
Upload File (Dropbox)Uploads a file to Dropbox. Template renders the file content.Dropbox (OAuth2 refresh token, app key/secret)

Action Configuration

Each action type has specific configuration fields set via Action Config:

Email Action Config

FieldRequiredDescription
ToYesRecipient email address(es)
CCNoCC email address(es)
SubjectYesEmail subject line

SMS Action Config

FieldRequiredDescription
ToYesRecipient phone number(s)

API Action Config

FieldRequiredDescription
URLYesThe API endpoint URL
HeadersNoCustom HTTP headers (key-value pairs)
Content TypeNoRequest content type (default: application/json)

Teams Action Config

FieldRequiredDescription
TitleNoOptional message title
Theme ColorNoOptional theme color (hex)

Slack Action Config

FieldRequiredDescription
ChannelNoChannel override
UsernameNoBot username override
Icon EmojiNoBot icon emoji

Discord Action Config

FieldRequiredDescription
UsernameNoUsername override
Avatar URLNoAvatar URL override

File Upload Action Config (FTP/SFTP)

FieldRequiredDescription
Remote PathYesDestination directory on the server
FilenameYesFilename template for the uploaded file

S3 Action Config

FieldRequiredDescription
Key/PathYesS3 object key/path

Azure Blob Action Config

FieldRequiredDescription
Blob Name/PathYesBlob name or path template
Content TypeNoBlob content type

Box Action Config

FieldRequiredDescription
Folder IDYesTarget Box folder ID
FilenameYesFilename template

Dropbox Action Config

FieldRequiredDescription
Target PathYesDestination path in Dropbox
FilenameYesFilename template
Write ModeNoOverwrite or add (default: add)

Workflow Credentials

Credentials store the authentication details needed by workflow actions (SMTP passwords, API keys, webhook URLs, etc.). All credentials are encrypted at rest using AES-256 encryption with department-specific key derivation, ensuring each department's secrets are isolated.

Managing Credentials

Navigate to Department → Workflows → Credentials to manage stored credentials.

  • Credentials are grouped by type for easy browsing
  • Secret values are always displayed as •••••• — they are write-only and never returned in responses
  • When editing a credential, existing secret values are preserved unless you explicitly provide new values

Credential Types

TypeFields
SMTPHost, Port, Username, Password, Use SSL, From Address
TwilioAccount SID, Auth Token, From Number
FTPHost, Port, Username, Password
SFTPHost, Port, Username, Password/Private Key
AWS S3Access Key, Secret Key, Region, Bucket
HTTP BearerBearer Token
HTTP BasicUsername, Password
HTTP API KeyHeader Name, API Key Value
Microsoft TeamsWebhook URL
SlackWebhook URL
DiscordWebhook URL
Azure Blob StorageConnection String (or Account Name + Account Key), Container Name
BoxDeveloper Token or JWT credentials (Client ID, Client Secret, Enterprise ID, Private Key)
DropboxApp Key, App Secret, OAuth2 Refresh Token

Creating a Credential

Click New Credential and select the credential type. Fill in the type-specific fields — all secret fields are encrypted before storage.

Workflow Runs (Execution History)

The Runs view provides a paginated audit trail of all workflow executions:

ColumnDescription
TimestampWhen the workflow execution started
Workflow NameThe workflow that was triggered
StatusColor-coded badge: Pending, Running, Completed, Failed, Cancelled, Retrying
DurationTotal execution time
AttemptCurrent attempt number (if retrying)
Error SummaryBrief error description (if failed)

Click a run to expand and see per-step WorkflowRunLog detail, including:

  • Rendered template output
  • Action result (HTTP status, SMTP response, etc.)
  • Error messages
  • Duration per step

Filtering Runs

Filter runs by:

  • Status — Pending, Running, Completed, Failed, Cancelled, Retrying
  • Date range — Start and end date
  • Workflow — Specific workflow

Workflow Health

The Health view provides per-workflow health metrics:

MetricDescription
Success/Failure countsBroken down by 24h, 7d, and 30d windows
Success ratePercentage of successful runs
Average durationMean execution time
Last run timestampWhen the workflow last executed
Last errorMost recent error message
Recent run timelineVisual timeline of recent executions

Pending Runs

The Pending view lists all currently pending and in-progress workflow runs for the department. Actions available:

  • Cancel — Cancel an individual pending run
  • Clear All — Cancel all pending runs for the department (with confirmation dialog)

Retry Behavior

When a workflow step fails:

  1. If Attempt Number < Max Retry Count, the run is re-enqueued with exponential backoff delay (Retry Backoff Base × 2^(attempt - 1) seconds)
  2. Status is set to Retrying during the delay
  3. If max retries are exceeded, status is set to Failed with the final error message
  4. All retry attempts are visible in the run logs for auditing

The Max Retry Count has a server-side ceiling of 5 to prevent infinite retry abuse.

Template Sandboxing

Scriban templates are executed in a sandboxed environment to prevent abuse:

ProtectionLimit
Loop iterations500 maximum
Recursion depth50 maximum
Regex timeoutEnforced to prevent ReDoS
Output template size (save time)64 KB
Rendered content size256 KB
import / include built-insDisabled

Dynamic Action Config Fields

All text fields in action configuration (email Subject, To, CC, filenames, URLs, etc.) are rendered through the Scriban template engine at execution time. You can use {{ }} expressions in any config field:

  • Subject: New Call: {{ call.name }}
  • Filename: report_{{ timestamp.date }}.csv
  • Recipient: {{ user.email }}

Security Protections

SSRF Prevention

HTTP API calls, FTP, and SFTP actions enforce:

  • HTTPS only for HTTP calls
  • Blocking of private/internal IP ranges (RFC 1918, loopback, link-local, cloud metadata 169.254.169.254)
  • Configurable domain allowlist/blocklist

Webhook URL Validation

Chat platform webhook URLs are validated against expected vendor domains:

  • Teams: .webhook.office.com or .logic.azure.com
  • Slack: hooks.slack.com
  • Discord: discord.com or discordapp.com with /api/webhooks/ path

Email HTML Sanitization

Rendered email body HTML is sanitized before sending. Dangerous elements (<script>, <iframe>, <object>, <embed>, <form>), on* event attributes, and javascript: URLs are stripped. Standard formatting tags are preserved.

Rate Limiting

Workflow execution is rate-limited per department to prevent a single department from flooding the system. Limits are tiered by subscription plan:

LimitFree PlanPaid Plans
Executions per minute560
Daily run limit50Unlimited

Free-plan rate limits are strictly enforced with no exemptions — no event types bypass the limit.

Workflow and Step Limits

The number of workflows and steps per department is capped based on subscription plan:

LimitFree PlanPaid Plans
Workflows per department328
Steps per workflow520
Credentials per department220
Max retry count (ceiling)55

Daily Send Limits

Outbound email and SMS messages sent via workflows are subject to daily limits:

ChannelFree PlanPaid Plans
Emails per day10500
SMS per day5200

When the daily limit is reached, further email/SMS steps will fail with a clear error. Limits reset at midnight UTC.

Recipient Caps

To prevent bulk messaging abuse, the number of recipients per outbound step is capped:

ActionFree PlanPaid Plans
Email To + CC1 (no CC)10
SMS To15

Interactions with Other Modules

ModuleInteraction
Dispatch & CallsCall Added, Call Updated, Call Closed events trigger workflows
UnitsUnit Status Changed, Unit Added events trigger workflows
PersonnelPersonnel Staffing/Status Changed, User Created, Role Changed events
Groups & StationsUser Assigned to Group, Group Added/Updated events
DocumentsDocument Added events trigger workflows
NotesNote Added events trigger workflows
LogsLog Added events trigger workflows
CalendarCalendar Event Added/Updated events trigger workflows
ShiftsShift Created/Updated, Trade Requested/Filled events
MessagesMessage Sent events trigger workflows
TrainingsTraining Added/Updated events trigger workflows
InventoryInventory Adjusted events trigger workflows
FormsForm Submitted events trigger workflows
NotificationsWorkflows complement notifications — notifications handle push/SMS to personnel, while workflows enable external integrations
Resource OrdersResource Order Added events trigger workflows
CertificationsCertification Expiring events trigger workflows (via daily scheduled check)