Skip to content

Workflow configuration automation

The Workflow SDK (Moltaro.Package.NET.Workflow, contract 7.1.0) exposes Definition metadata, Subject CRUD and revision management through the same application services as the UI and Configuration API. Use the query and command services from API-hosted Action, Command, and HttpEndpoint functions. These are the currently supported execution contexts for configuration services. Trusted direct EF access is also available in Jobs and TriggerHandlers. Runtime command/query services additionally support those background contexts, using trusted host provenance.

Resolve every /api/workspace/... route against your installation’s WORKSPACE_API_BASE_URL, never against moltaro.com.

For a complete WebApp setup, follow Set up Workflows. The runtime guide covers instances, responses and administration; the process document reference covers every supported node and typed observation. Use the installed Configuration OpenAPI for exact schemas and the generated Configuration API reference for operation details. Public API visibility does not bypass module or resource permissions.

A Definition has a stable generated WorkflowDefinitionId, editable Key (64 characters), DisplayName (128), optional Description (512), creation and modification dates/authors, and RowVersion. Keys are trimmed and unique without regard to case. Renaming a key preserves the Id; callers using keys must update their own references. There are no key aliases.

These fields are global metadata. Creating a Definition does not create a graph, revision, execution instance or task. There is no active/inactive state on a Definition in this increment.

The WebApp calls this Context or Process context. HTTP and C# use the contract name Subject for that same business record or Board item.

Subject is optional on creation and can be assigned or cleared later. It is global to the Definition. WorkflowSubject and WorkflowSubjectKindEnum are in Moltaro.Workflow.Engine.Definitions (Engine contract 5.2.0):

  • EntityInstance: EntityDefinitionId identifies a standalone Data or Association definition; Board identities are null.
  • BoardItem: BoardId identifies the whole Board; EntityDefinitionId is null. There is no Workflow Target Definition selector. The same Definition applies to items of every target type on that Board, including Itself, subject to normal runtime authorization and activation.

No Board status restriction is configured here. Definition results include the stored contract, resolved names and availability information. An unavailable saved Subject remains visible. New Board choices require enabled Boards and available metadata; ordinary edits can retain an existing unavailable binding. Workflow configuration permission is sufficient to select metadata and does not grant access to Entity instances or Board items.

Actions.CanEditSubject indicates whether the current user can change Subject. The first revision, including a draft, requires an available Subject and permanently locks it. Removing revisions does not unlock it. Configuration services expose no operation to set or clear the lock.

Update replaces the Subject: use Subject = current.Subject?.Contract to retain it when changing only ordinary metadata. Null (including an omitted property) clears an unlocked Subject. The same Subject remains valid for metadata updates after locking. Subject changes participate in command retry identity.

The Board’s separate Workflow configuration section lists these Definitions automatically. You can change their order, visibility and Item signals flag. Item signals is off by default; when enabled for a visible process, its name, status and number appear with the status and state chips in the Board item’s header. The number opens the process. This does not change Kanban placement. The Board Definition summary counts all affiliated processes, including hidden ones. Drag processes or use the up/down keys on their drag handles to reorder them. Hiding a process does not disable execution, activation or DSL facts, and does not change access. This section requires the Board’s configuration permission; opening a Definition still requires Workflow configuration permission. Processes are not attached to Target Definitions and are not selected through Card Fields.

Contract 4 removes the former Target Definition member from WorkflowSubject and its result metadata. Rebuild dependent C# sources using the three-member Subject. Existing published YAML remains version 2 and is not rewritten. Board DevLog templates use item, data and status, not a bare target root.

The enabled module must have its security configuration applied. Its internal configuration-management role grants configuration.read and configuration.manage. Initial mappings include Admin, Configurator, and the preset Workflow Configuration Manager workspace role. Administrators may change or remove these mappings. Re-enabling the module preserves those changes.

The services use the function’s current runtime principal and recheck write authorization inside the protected application transaction. A removed mapping, revoked role or blocked principal does not retain access through a previously successful command or its retry. Ordinary Definition operations have no Owner/Admin authorization bypass. Definition Security also permits global administrators. Only an active Owner or built-in Admin administers module lifecycle and role mappings.

Each write requires a nonblank OperationId of at most 128 characters. Keep the same Id and payload only for an exact retry of the same command on the same Definition, by the same principal. An identical retry returns the original result with Replayed = true; a changed payload with the same operation identity fails. Update and delete also require the current ExpectedRowVersion.

Commands run in a separate application scope and own their transaction. They do not join a generated DbContext transaction injected into the function. Metadata, mandatory audit, command receipt and cache invalidation commit together.

Inject IWorkflowDefinitionAutomationQueryService and IWorkflowDefinitionAutomationCommandService from Moltaro.Package.NET.Workflow.Automation. Request/result models are in Moltaro.Package.NET.Workflow.Definitions. Generated workspace projects register the facades automatically; inject the supported interfaces into your function.

using Moltaro.Package.NET.Workflow.Automation;
using Moltaro.Package.NET.Workflow.Definitions;
using Moltaro.Workflow.Engine.Definitions;
public static async Task<string> CreateDefinitionAsync(
IWorkflowDefinitionAutomationCommandService commands,
string entityDefinitionId,
string operationId,
CancellationToken cancellationToken)
{
var result = await commands.CreateWorkflowDefinitionAsync(
new CreateWorkflowDefinitionRequest(
"order-review", "Order review", "Review incoming orders.", operationId)
{
Subject = new WorkflowSubject(
WorkflowSubjectKindEnum.EntityInstance, entityDefinitionId, null)
},
cancellationToken);
if (!result.Success)
throw new InvalidOperationException(string.Join(", ", result.Errors.Select(error => error.Code)));
return result.Data!.WorkflowDefinition.WorkflowDefinitionId;
}

Use ListWorkflowDefinitionsAsync and GetWorkflowDefinitionAsync for reads. Update with UpdateWorkflowDefinitionAsync(id, new UpdateWorkflowDefinitionRequest( key, name, description, current.RowVersion, operationId) { Subject = current.Subject?.Contract }). Delete with DeleteWorkflowDefinitionAsync(id, new DeleteWorkflowDefinitionRequest( current.RowVersion, operationId)). Handle failure results before accessing Data.

The installation-local HTTP equivalent is /api/workspace/workflow/configuration/workflow-definitions: GET collection or /{id}, POST collection, PUT/DELETE /{id}, and GET /{id}/audit. Metadata lookups are GET subject-options/entity-definitions?search=, subject-options/boards?search= under the same base route. Invalid bindings return errors for Subject.* fields. Conflict responses use HTTP 409; invalid input uses 400, inaccessible operations 403, and an unavailable Definition 404. Consult the installation’s generated Configuration OpenAPI at /openapi/moltaro-config-v1.json for exact envelopes and its developer surface for installed versions.

The Workflow module page links to the Definition catalog and can add its page to a Runtime Menu. Menu visibility follows current module availability and the same configuration permission; a visible menu is not an independent access grant. The catalog supports search, preview, create, detail, edit, audit and confirmed deletion on desktop and mobile. Create/edit uses a Basics and Context wizard; Context appears in the grid, mobile cards and existing Overview on preview/details.

Module lifecycle and configuration-role mappings are published under /api/workspace/admin/workflow in Configuration OpenAPI: read status/readiness, enable or disable, manage security/associations, and configure runtime-menu entries. These operations require module administration authority. They are separate from Definition-level runtime administrators and are not exposed as Definition automation commands.

Board presentation is read and replaced through /api/workspace/workflow/configuration/boards/{boardId}/presentation. Its snapshot has an independent version and OperationId; submit every affiliated Definition exactly once. It changes order, visibility and Item signals, not affiliation, activation, Definition RowVersion or permissions. Use the generated reference for each operation’s exact request and result.

Moltaro.Workflow.Engine supplies pure metadata rules and remains independent of persistence and HTTP. Workflow does not require Tasks or Work Schedule; Boards is needed only to configure a new Board Subject. Its internal persistence and application assemblies are not script libraries.

Every newly created Definition has a default outcome: completed, named Completed, with metatype Success. Additional outcomes have Key (1–64 characters), DisplayName (1–128), optional Description (up to 512), MetaType and SortOrder. WorkflowOutcomeMetaTypeEnum provides Success, Failed and Canceled.

Exactly one outcome must be both enabled and default. The generated Completed outcome follows the same editing rules as other outcomes. Create or update another enabled outcome with IsDefault = true to replace the default atomically. The current default cannot be unset, disabled or deleted before choosing its replacement. IsEnabled = false removes an outcome from new choices and blocks new publication that references it; already published processes may still finish with it. Create defaults to enabled and non-default; nullable flags on update preserve their stored values when omitted.

The first revision reference permanently locks Key, including references from Drafts. Removing that reference does not unlock the key. Current references prevent deletion; any published reference also locks MetaType. Presentation fields remain editable. Use the returned Actions.CanEditKey, CanEditMetaType and CanDelete in clients; the server enforces the same rules.

The workspace C# runtime registers IWorkflowOutcomeAutomationQueryService and IWorkflowOutcomeAutomationCommandService. Inject these supported interfaces into the function; the host registers them. The same configuration permissions apply.

using Moltaro.Package.NET.Workflow.Automation;
using Moltaro.Package.NET.Workflow.Outcomes;
using Moltaro.Workflow.Engine.Outcomes;
var outcomeQueries = services.GetRequiredService<IWorkflowOutcomeAutomationQueryService>();
var outcomeCommands = services.GetRequiredService<IWorkflowOutcomeAutomationCommandService>();
var outcomes = await outcomeQueries.ListWorkflowOutcomesAsync(definitionId, ct);
if (!outcomes.Success) throw new InvalidOperationException("Cannot read outcomes.");
var created = await outcomeCommands.CreateWorkflowOutcomeAsync(definitionId,
new CreateWorkflowOutcomeRequest("rejected", "Rejected", "Request was declined",
WorkflowOutcomeMetaTypeEnum.Failed, 10, outcomes.Data!.DefinitionRowVersion,
operationId), ct);
if (!created.Success)
throw new InvalidOperationException(string.Join(", ", created.Errors.Select(e => e.Code)));

Query services also provide GetWorkflowOutcomeAsync; command services provide UpdateWorkflowOutcomeAsync and DeleteWorkflowOutcomeAsync. All writes require OperationId and ExpectedDefinitionRowVersion. Update/delete additionally require ExpectedOutcomeRowVersion. Mutations return Outcome and DefinitionRowVersion; delete returns the deleted identity and new parent version. Actual outcome changes advance the Definition version. Exact retries return the original result; changed payloads and stale versions return conflicts. Key uniqueness errors bind to Key. Deleting a Definition without revisions removes its own outcomes.

HTTP operations use the workspace API base URL and the nested resource /api/workspace/workflow/configuration/workflow-definitions/{definitionId}/outcomes: GET lists, POST creates, and GET/PUT/DELETE /{outcomeId} read/update/delete.

The Definition detail page has a Revisions section. A Definition can have several Drafts and at most one Active revision. Publishing a Draft makes the previous Active Deprecated atomically. Once published, a revision can never be deleted, even before any process instances exist. Description corrections are permitted in every state; the process content does not change. Copy any state to a new independent Draft of the same Definition. Its source Id and Number remain visible even if the source Draft is later deleted.

Every revision has a server-assigned Number, required Description (up to 512 characters), Status, provenance, timestamps/authors and RowVersion. Numbers are never reused. A null creation Description requests a localized default such as “Revision #1”; a null copy Description defaults to “Based on revision #1”. The first revision requires an available Subject and permanently locks it, including when that first revision is a Draft. Deleting all Drafts does not unlock Subject. A Definition can only be deleted after explicit deletion of all revisions.

Inject IWorkflowRevisionAutomationQueryService and IWorkflowRevisionAutomationCommandService from Moltaro.Package.NET.Workflow.Automation. Request/result models are in Moltaro.Package.NET.Workflow.Revisions.

using Moltaro.Package.NET.Workflow.Automation;
using Moltaro.Package.NET.Workflow.Revisions;
public static async Task<WorkflowRevisionMutation> CreateDraftAsync(
IWorkflowRevisionAutomationQueryService queries,
IWorkflowRevisionAutomationCommandService commands,
string definitionId,
string operationId,
CancellationToken cancellationToken)
{
var current = await queries.ListWorkflowRevisionsAsync(definitionId, cancellationToken);
if (!current.Success)
throw new InvalidOperationException(string.Join(", ", current.Errors.Select(e => e.Code)));
var result = await commands.CreateWorkflowRevisionAsync(definitionId,
new CreateWorkflowRevisionRequest(null, current.Data!.WorkflowDefinition.RowVersion, operationId),
cancellationToken);
if (!result.Success)
throw new InvalidOperationException(string.Join(", ", result.Errors.Select(e => e.Code)));
return result.Data!;
}

Queries expose ListWorkflowRevisionsAsync, GetWorkflowRevisionAsync, GetWorkflowRevisionContentAsync and ListWorkflowRevisionAuditAsync. Commands expose CreateWorkflowRevisionAsync, UpdateWorkflowRevisionAsync, CopyWorkflowRevisionAsync, PublishWorkflowRevisionAsync and DeleteWorkflowRevisionAsync. Publication and deletion take their named request types; description update takes UpdateWorkflowRevisionRequest.

All writes require OperationId. Description update checks the revision’s ExpectedRowVersion. Creation checks ExpectedDefinitionRowVersion; copying, publication and deletion check both. Refresh state and explicitly reconfirm publication after 409. Reusing an OperationId with changed input conflicts; an exact retry returns the original result with Replayed=true. Current authorization is checked again even for a retry. Creation, copying, deletion and publication advance the Definition version; description update advances the revision version.

The nested HTTP resource is /api/workspace/workflow/configuration/workflow-definitions/{definitionId}/revisions:

MethodSuffixOperation
GETcollectionMetadata and available actions
POSTcollectionCreate generated Draft
GET/{revisionId}Revision, parent Definition and current Active
PUT/{revisionId}Update Description only
DELETE/{revisionId}Delete Draft only
POST/{revisionId}/copyCreate independent Draft
POST/{revisionId}/publishPublish and replace the current Active
GET/{revisionId}/contentConsistent YAML/hash/RowVersion/CanEditContent snapshot
PUT/{revisionId}/contentSave supported Draft document
POST/{revisionId}/content/validateValidate without writing
GET/{revisionId}/auditLocalized history

Activation is stored on Definition and is independent of revision YAML. Explicit means manual activation and requires context permissions; Implicit means automatic activation and has no permission settings. Both have an optional Boolean precondition using Subject data, without the current user or security predicates. A precondition can check related records with ANY, ALL, EXISTS and COUNT, including nested collections and the related records’ configured Board or Workflow facts; see Collections and related records. A new Definition created through services defaults to Explicit with inherited Update for Entity or EditBoardData for Board. Trusted EF creation can use WorkflowActivationDefaults.CreateExplicitPermission. Existing settings are not reset; a missing permission rule still grants no access.

The complete Security and business-condition profiles describe roots, actor restrictions, temporal functions, target selectors and complexity limits. Use the setting-specific authoring description and validation, including item-scoped path discovery for nested collections. Workflow HTTP configuration is published in the installation’s Configuration OpenAPI; operational commands and reads are in Runtime OpenAPI. The installed SDK and HTTP schemas determine the signatures available in that release.

The Definition query facade provides GetActivationAsync, GetActivationAuthoringAsync and ValidateActivationAsync. The command facade provides UpdateActivationAsync, with ExpectedRowVersion and OperationId. These methods use the same configuration permissions, audit and transaction as the Activation tab. Configuring Entity or Board security is not required.

Explicit uses ContextPermissionRule from Moltaro.Package.NET.Security: select one or more Responsibility Definition keys and resource scopes (item or status), inherited permissions with All/Any, or Security DSL. Any selected responsibility grants eligibility. Multiple selections use AnyOf references with ResourcePath and ResponsibilityKey, mutually exclusive with the single-reference fields. These are the same choices as User Input. The Activation tab and preview drawer share a read-only panel and an Edit dialog with Save/Cancel. Direct EF exposes ActivationMode, ActivationPrecondition and ActivationExplicitPermissionJson on WorkflowDefinitions; use services for catalog validation, concurrency, audit and idempotency.

Saving configuration does not start a process. Implicit without a condition reacts to Created only; with a condition it evaluates Created and Updated against current record data. Changing settings does not scan or start existing records. Switching to Implicit clears the manual rule.

See Runtime commands from C#.

See Runtime HTTP and administration.

See Instance numbers.

See Direct EF access.

See Generated process document.

See Draft content and Designer.

See Draft versus publication validity.

See Delay, DevLog and User Input.

See If and Wait Event and Wait Until.

Use POST {definitionId}/move-on-board-authoring or SDK GetMoveOnBoardAuthoringAsync for admitted source paths, target types, Boards and statuses. Save, copy, publication and YAML use the same validation. Incomplete Draft settings may be omitted; supplied stale/invalid values are rejected. See Move on Board.

See DevLog message templates.