Workflow engine API: make non-head workflow failures visible in status reads
- Dominant language
- C#
- Stars
- 169
- Forks
- 100
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 272
Description
## The gap
Process transitions schedule their non-critical side effects — Altinn Events registrations, instantiation notifications — as separate workflows enqueued with `IsHead=false`, deliberately invisible to the collection's head frontier so they can never gate a user's transition.
When one of those fails terminally, the outbound event is permanently lost, and no status lookup with the right shape reports it:
- `GET /collections/{key}` — the one endpoint shaped like "what is the status of X" — returns only head workflows, so it reports a clean transition.
- The app's read-path `workflow` annotation strips the same set, so the instance reads as `idle`.
- Only `GET /workflows?collectionKey=…&status=Failed` surfaces them, and only for a caller who already knows to ask.
The engine metric `engine.workflows.execution.failed` is already tagged `is_head`, but nothing alerts on it. Storage meanwhile records the transition as complete, so instance history and the Altinn Events stream disagree with no signal that they do.
Separately, the planned Studio admin view needs per-instance health at list scale — a green/orange/red summary across a page of instances, plus an "instances with errors" view. The engine has no shape for that: `GET /collections` returns every collection in a namespace unpaginated and carries no status rollup.
## Proposal
1. **`isHead` filter on `ListWorkflows`**, with visibility semantics. Turns the ops worklist into one precise call.
2. **Rework `GET /collections` into a health view**: cursor pagination (it is unbounded today), a per-collection workflow-count rollup, a repeatable `?key=` filter for bulk-annotating a page of instances the caller already holds, and a `?failures=` filter for discovery. The admin list stays Storage-driven — the engine annotates it, because the engine only knows instances with transition activity inside the retention window.
3. **Dashboard fixes**: the query status parser silently drops `DependencyFailed` and `Abandoned` — add them, plus an `isHead` facet.
4. **Wire the ops alert** that `docs/workflow-collections.md` already prescribes. This is the only part that prevents permanent event loss; the read APIs only help someone who is already looking.
**Explicit non-goal:** no rollup on `GET /collections/{key}`. It is a *frontier* view by contract, and it sits on the app's page-view-scale hot path. Its docs should say so and point at the filter instead.
Implementation detail — DTO shapes, predicates, mode matrix, query direction — is in a comment below rather than inline here.
Contributor guide
Research direction
Start with docs/workflow-collections.md, then trace the named collection and workflow status endpoints, the read-path workflow annotation, and the dashboard status parser. The implementation must cover non-head visibility, collection pagination and failure rollups, dashboard filters, and the prescribed operational alert; done means these failure paths become discoverable without changing the collection-key frontier view.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend-api-design, documentation, observability
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100