Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 24 additions & 32 deletions docs/meta/backlog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This backlog is prioritized by user impact and frequency of complaints
based on gap analysis from 161 issues across elsa-studio and
elsa-gitbook.

## Slice Inventory (2026-06-19)
## Slice Inventory (2026-06-20)

This inventory reflects the current GitBook contents before selecting the
next automation slice. "Covered" means the repository now includes a
Expand Down Expand Up @@ -35,7 +35,7 @@ acceptance criterion below is already complete.
- `DOC-022` Scaling and performance
- `DOC-024` MassTransit communication
- `DOC-040` Timer and scheduled workflows
- `DOC-042` Bulk dispatch workflows activity
- `DOC-053` Alterations operational guide hardening
- `DOC-028` Studio customization
- `DOC-029` Custom UI hints
- `DOC-030` Custom UI components
Expand All @@ -52,25 +52,25 @@ acceptance criterion below is already complete.
- `DOC-027` Execution model
- `DOC-038` Distributed tracing
- `DOC-039` Performance tuning
- `DOC-042` Bulk dispatch workflows activity
- `DOC-043` Hangfire integration
- `DOC-047` API reference
- `DOC-048` Activity reference
- `DOC-053` Alterations operational guide hardening

### Current run selection

- `DOC-042` Bulk dispatch workflows activity: add a release-backed guide that
explains fan-out child workflow dispatch, item-to-input mapping,
`WaitForCompletion`, per-child ports, and how the activity differs from the
REST bulk-dispatch endpoint.
- `DOC-053` Alterations operational guide hardening: rewrite the alterations
pages around the actual `release/3.8.0` execution modes, built-in alteration
types, plan lifecycle, Studio surfaces, persistence options, and shipped HTTP
endpoints including bulk retry.

### Recommended next slice

- `DOC-025` Long-running workflows: the new scheduling guide now explains
timers and durable resumes, but the docs still lack one release-backed guide
that connects bookmarks, timers, incidents, cancellation, persistence,
background execution, and operator troubleshooting into a full workflow
lifecycle narrative.
- `DOC-019` HTTP endpoint security: the HTTP workflow guides now explain how
to build endpoints, but the auth surface is still spread across multiple
pages. A single release-backed guide should connect `Authorize`,
`HttpEndpoint`, API permissions, public vs authenticated endpoints, and
Studio-facing troubleshooting.

### Newly discovered follow-on topics

Expand All @@ -84,35 +84,27 @@ acceptance criterion below is already complete.
- `DOC-052` Workflow state and journal API cookbook: add an operations-facing
guide for inspecting workflow state, filtered journal entries, activity
executions, and variable mutation endpoints when diagnosing live instances.
- `DOC-054` Messaging transport decision guide: document when to use
MassTransit message-type activities, the Azure Service Bus activity module,
or MassTransit-backed workflow dispatching so teams do not conflate three
different messaging integration paths.
- `DOC-054` Messaging transport selection and topology guide: add a focused
cross-cutting guide that helps architects choose between MassTransit,
Azure Service Bus, and Kafka extensions, and explains when to use
workflow-trigger activities vs runtime dispatchers vs custom consumers.

### Current run result

- `DOC-040` Timer and scheduled workflows: completed in this run by adding a
dedicated guide for `Delay`, `StartAt`, `Timer`, and `Cron`, and grounding
the scheduling model in `DefaultBookmarkScheduler`, `ResumeWorkflowTask`,
`LocalScheduler`, and Quartz-backed scheduler configuration from
`release/3.8.0`.
- `DOC-042` Bulk dispatch workflows activity: completed in this run by adding
a dedicated guide for `BulkDispatchWorkflows`, clarifying item input mapping,
wait-vs-fire-and-forget behavior, per-child completion and fault ports,
channel dispatch, and the difference between in-workflow bulk dispatch and
the `/workflow-definitions/{definitionId}/bulk-dispatch` API endpoint.
- `DOC-053` Alterations operational guide hardening: completed in this run by
aligning the overview, alteration plans, and immediate execution guides with
`release/3.8.0` behavior, including Studio's alterations module, the
built-in `Cancel` alteration, persistence and dispatcher configuration, the
`run:alterations` permission surface, and the shipped `/alterations/run`,
`/alterations/submit`, `/alterations/dry-run`, and
`/alterations/workflows/retry` endpoints.

## Critical Priority (Must Have - Block Users)

### Current slice note

- `DOC-053` Alterations operational guide hardening:
`features/alterations` is present, but the current pages are not fully
release-backed. Examples still use pre-filter plan payloads, omit the built-in
`Cancel` alteration, describe `/alterations/run` as requiring manual resume
dispatch even though the endpoint already dispatches successful instances with
scheduled work, and do not explain the Studio alterations surface or the
persistence/dispatcher options available in `release/3.8.0`.
completed on 2026-06-20.

### DOC-001: V2 to V3 Migration Guide
- **Persona**: Backend Integrator, Architect
Expand Down
44 changes: 42 additions & 2 deletions features/alterations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ An [alteration](../../getting-started/concepts/#alteration) represents a change

Using alterations, you can change the state of a running workflow instance without republishing the workflow definition. In `release/3.8.0`, Elsa exposes alterations through server APIs and Elsa Studio.

## What Elsa ships in `release/3.8.0`

Enabling `UseAlterations()` adds:

* the built-in `Elsa.Alterations.ExecuteAlterationPlan` system workflow used to execute submitted plans
* REST endpoints under `/alterations`
* in-memory alteration plan and job stores by default
* an in-memory background dispatcher for alteration jobs by default

All alteration APIs shown on this page require the `run:alterations` permission.

## When to use alterations

Use alterations when you need to correct or steer existing workflow instances. Typical examples include:
Expand Down Expand Up @@ -35,15 +46,34 @@ Use these pages for each mode:
* [Alteration Plans](alteration-plans/README.md)
* [Applying Alterations](applying-alterations/README.md)

### Which mode fits which job

| Situation | Use |
| --- | --- |
| You already know the exact workflow instance IDs and need the response now | `POST /alterations/run` or `IAlterationRunner` |
| You need Elsa to find matching workflow instances from filters and process them in the background | alteration plans |
| You need to retry faulted activities across one or more instances | `POST /alterations/workflows/retry` |
| You want designers or operators to stage a bulk plan visually in Studio | Elsa Studio alterations module |

## Elsa Studio

Elsa Studio in `release/3.8.0` includes an alterations module. When the backend Alterations feature is enabled, Studio shows an **Alterable instances** page and adds **Alter** actions for running workflow instances.

Studio currently focuses on altering individual running instances. For bulk operations across many instances, use alteration plans and their filter-based API.
Studio exposes:

* an **Alterations** top-level menu with plan and instance views
* an **Alterable instances** page that lists non-system running workflow instances
* an alteration designer for staging the five built-in alteration types against an instance
* plan details pages that show plan status, generated jobs, and per-job logs
* quick **Alter** actions from workflow-instance screens

Studio currently focuses on staging or inspecting plans around individual running instances. For cross-instance bulk operations, use alteration plans and their filter-based API.

## Persistence and dispatch options

By default, Alterations uses in-memory stores and an in-memory background dispatcher. For durable or multi-node deployments, configure persistence for alteration plans and jobs:
By default, Alterations uses in-memory stores and an in-memory background dispatcher. That is fine for local development, but plans and jobs are not durable across process restarts.

For durable or multi-node deployments, configure persistence for alteration plans and jobs:

```csharp
services.AddElsa(elsa => elsa.UseAlterations(alterations =>
Expand All @@ -69,3 +99,13 @@ services.AddElsa(elsa => elsa.UseAlterations(alterations =>
alterations.UseMassTransitDispatcher();
}));
```

Use the MassTransit dispatcher when alteration jobs should survive node boundaries or be processed by worker nodes connected through MassTransit. The dispatcher replaces the default in-memory background queue for alteration jobs only; it does not change how the immediate `/alterations/run` endpoint executes.

## Operational notes

* Submitted plans create one alteration job per matched workflow instance.
* If a submitted plan matches no instances, Elsa still stores the plan but generates no jobs.
* `/alterations/run` dispatches successful workflow instances that still have scheduled work after the alterations finish.
* `IAlterationRunner` by itself does not dispatch scheduled work; pair it with `IAlteredWorkflowDispatcher` when you call the service directly.
* The built-in bulk retry endpoint schedules faulted activities by creating `ScheduleActivity` alterations and then dispatching the affected instances.
53 changes: 53 additions & 0 deletions features/alterations/alteration-plans/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ In `release/3.8.0`, `IAlterationPlanScheduler` accepts `AlterationPlanParams`, w
* `filter`: an `AlterationWorkflowInstanceFilter` describing which workflow instances to target
* `id`: an optional plan ID; Elsa generates one when omitted

## What happens when you submit a plan

Submitting a plan does not run the alterations inline with the request. Elsa instead:

1. stores or generates the plan ID
2. dispatches the built-in `Elsa.Alterations.ExecuteAlterationPlan` system workflow
3. stores the plan
4. finds matching workflow instances from the filter
5. creates one alteration job per matching instance
6. dispatches those jobs through the configured alteration job dispatcher

This is why alteration plans are the right fit for bulk operational work, scheduled worker processing, and cases where you need job-level inspection later.

### Creating Alteration Plans <a href="#creating-alteration-plans" id="creating-alteration-plans"></a>

To create an alteration plan in code, create an `AlterationPlanParams` instance:
Expand All @@ -39,6 +52,19 @@ var plan = new AlterationPlanParams

The workflow-instance filter supports more than explicit instance IDs. In `release/3.8.0`, you can also filter by correlation IDs, names, search term, definition IDs, definition version IDs, statuses, sub-statuses, incidents, system-workflow flag, activity filters, and timestamp filters.

### Filter guidance

Use explicit `workflowInstanceIds` when you already know the exact targets but still want background execution and plan tracking.

Use broader filters when you are operating on a live slice of runtime state, for example:

* all running instances of a specific workflow definition
* instances with incidents
* instances waiting in a specific sub-status
* instances created, updated, or finished in a specific time range

Use `POST /alterations/dry-run` before submitting a broad filter so you can confirm which instance IDs Elsa would target.

### Submitting Alteration Plans <a href="#submitting-alteration-plans" id="submitting-alteration-plans"></a>

To submit an alteration plan, use the `IAlterationPlanScheduler` service. For example:
Expand All @@ -65,3 +91,30 @@ var jobs = (await store.FindManyAsync(new AlterationJobFilter { PlanId = planId
```

If the filter matches no workflow instances, Elsa still stores the plan, but it does not create jobs.

## Plan status and job status

The plan and job records are separate on purpose:

* the plan tells you whether Elsa accepted and processed the bulk request
* the jobs tell you what happened for each targeted workflow instance

Use plan timestamps plus per-job logs to answer operational questions such as:

* did Elsa find any matching instances
* which instances failed
* which alteration inside the plan failed for a specific instance
* whether a plan has finished creating and dispatching its jobs

## Elsa Studio workflow

In Studio, the alterations designer submits the same `AlterationPlanParams` payload used by the server API.

After submission, Studio navigates to a plan details page that shows:

* the stored plan payload
* current plan status
* generated jobs
* per-job log entries

This is the fastest path for operators who want plan visibility without scripting the REST API directly.
19 changes: 19 additions & 0 deletions features/alterations/alteration-plans/rest-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

The Alterations module exposes a REST API for submitting, inspecting, and dry-running alteration plans.

All endpoints on this page require the `run:alterations` permission.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Wrong read permission The status endpoint on this page does not use run:alterations. In release/3.8.0, GET /alterations/{id} is guarded by read:alterations, while submit and dry-run use run:alterations. An operator following this note can grant only run:alterations and still get authorization failures when trying to inspect plan/job status.

Artifacts

Repro: executable authorization metadata harness for alteration endpoints

  • Contains supporting evidence from the run (text/x-python; charset=utf-8).

Repro: harness output showing endpoint permissions and HTTP status mappings

  • Keeps the command output available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: features/alterations/alteration-plans/rest-api.md
Line: 5

Comment:
**Wrong read permission** The status endpoint on this page does not use `run:alterations`. In `release/3.8.0`, `GET /alterations/{id}` is guarded by `read:alterations`, while submit and dry-run use `run:alterations`. An operator following this note can grant only `run:alterations` and still get authorization failures when trying to inspect plan/job status.

How can I resolve this? If you propose a fix, please make it concise.


## Submit a plan

Send `POST /alterations/submit` with `alterations` plus a `filter`:
Expand Down Expand Up @@ -68,6 +70,21 @@ Example response:
}
```

The dry-run endpoint accepts the same `AlterationWorkflowInstanceFilter` model that `POST /alterations/submit` uses inside `filter`. In `release/3.8.0`, that includes:

* `workflowInstanceIds`
* `correlationIds`
* `names`
* `searchTerm`
* `definitionIds`
* `definitionVersionIds`
* `statuses`
* `subStatuses`
* `hasIncidents`
* `isSystem`
* `activityFilters`
* `timestampFilters`

## Get plan and job status

Use the plan ID to query the current plan and its jobs:
Expand Down Expand Up @@ -132,3 +149,5 @@ The response includes the stored plan and any generated jobs:
```

`status` values are serialized from Elsa's plan and job status enums. Use the plan timestamps and per-job logs to understand whether Elsa found matching instances, whether jobs have started, and which alterations succeeded or failed.

If a plan matches no workflow instances, the response still returns the stored plan, but `jobs` remains empty.
31 changes: 31 additions & 0 deletions features/alterations/applying-alterations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Use immediate execution when you already know which workflow instance IDs you want to alter and you want the results in the current request.

This execution mode is synchronous from the caller's point of view: Elsa runs the requested alterations against the specified workflow instances and returns one result per instance.

At the service level, immediate execution uses `IAlterationRunner`:

```csharp
Expand All @@ -21,6 +23,17 @@ var results = await runner.RunAsync(workflowInstanceIds, alterations, cancellati

This updates the specified workflow instances synchronously and returns one `RunAlterationsResult` per instance.

## What the result tells you

Each `RunAlterationsResult` contains:

* `workflowInstanceId`
* `log`
* `workflowHasScheduledWork`
* `isSuccessful`

Use the log entries to see which alteration succeeded or failed for each targeted instance.

## Resuming scheduled work

When you use `IAlterationRunner` directly, successful alterations may leave workflow instances with scheduled work waiting to be dispatched. In that case, resume them with `IAlteredWorkflowDispatcher`:
Expand All @@ -40,3 +53,21 @@ This distinction matters:
* `POST /alterations/run` runs the alterations and then automatically dispatches successful instances that have scheduled work.

If you are using the HTTP API, you do not need a separate resume step after a successful `/alterations/run` request.

## When to use immediate execution

Use immediate execution when:

* an operator already has one or more concrete workflow instance IDs
* you want the alteration log in the same request
* you do not need durable plan and job records

Use alteration plans instead when Elsa should discover the target instances for you or when you need persistent plan and job tracking.

## Retrying faulted workflow instances

`release/3.8.0` also ships a bulk retry endpoint for faulted instances: `POST /alterations/workflows/retry`.

That endpoint builds `ScheduleActivity` alterations for the specified activity IDs, or for all incident activity IDs when you omit `activityIds`, then dispatches the updated workflow instances.

Use the retry endpoint when your operational goal is specifically "retry the faulted work" rather than "apply an arbitrary alteration set".
38 changes: 38 additions & 0 deletions features/alterations/applying-alterations/rest-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ The Alterations module exposes `POST /alterations/run` for immediate execution a

Use this endpoint when you already know the target instance IDs and want the results immediately. If you want Elsa to select instances from a filter and process them in the background, use [alteration plans](../alteration-plans/rest-api.md) instead.

All endpoints on this page require the `run:alterations` permission.

For example, to apply an alteration that modifies a variable, migrates the workflow instance to a new version, and schedules an activity, use the following request:

```http
Expand Down Expand Up @@ -68,3 +70,39 @@ The response includes one result per targeted workflow instance:
```

After the runner finishes, the endpoint automatically dispatches any successful workflow instance that still has scheduled work.

## Retry faulted activities

`release/3.8.0` also exposes `POST /alterations/workflows/retry` for retrying faulted activities across one or more workflow instances.

If you omit `activityIds`, Elsa retries all incident activity IDs recorded on each specified workflow instance.

```http
POST /alterations/workflows/retry HTTP/1.1
Host: localhost:5001

{
"workflowInstanceIds": [
"88ce68d00e824c78a53af04f16d276ea"
]
}
```

To retry only specific activities, include `activityIds`:

```http
POST /alterations/workflows/retry HTTP/1.1
Host: localhost:5001

{
"workflowInstanceIds": [
"88ce68d00e824c78a53af04f16d276ea"
],
"activityIds": [
"ShipOrder",
"CapturePayment"
]
}
```

The response shape matches `/alterations/run` by returning one result per targeted workflow instance.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Retry results multiply The shipped retry endpoint does not always return one result per targeted workflow instance. In release/3.8.0, it loops over each loaded workflow instance, then calls the alteration runner with the full requested workflowInstanceIds collection each time. With two workflow IDs and omitted activityIds, callers can receive four results, and incident activity IDs from one instance can be applied to the other instance. The docs should describe this release behavior or recommend one workflow instance ID per retry request when relying on incident-derived activity IDs.

Artifacts

Repro: executable retry endpoint harness

  • Contains supporting evidence from the run (text/x-python; charset=utf-8).

Repro: harness output showing 200 OK and multiplied results

  • Keeps the command output available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: features/alterations/applying-alterations/rest-api.md
Line: 108

Comment:
**Retry results multiply** The shipped retry endpoint does not always return one result per targeted workflow instance. In `release/3.8.0`, it loops over each loaded workflow instance, then calls the alteration runner with the full requested `workflowInstanceIds` collection each time. With two workflow IDs and omitted `activityIds`, callers can receive four results, and incident activity IDs from one instance can be applied to the other instance. The docs should describe this release behavior or recommend one workflow instance ID per retry request when relying on incident-derived activity IDs.

How can I resolve this? If you propose a fix, please make it concise.