collective / collective/workflow-manager
DeleteState API allows deleting initial_state and corrupts workflow definition
- Dominant language
- TypeScript
- Stars
- 6
- Forks
- 14
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
Deleting a workflow state that is configured as the workflow `initial_state` succeeds, but leaves `workflow.initial_state` pointing to a non-existent state id. This corrupts the workflow definition and can break content creation / initialization.
## Repository / Location
- Repo: collective/workflow-manager
- File: `backend/src/workflow/manager/api/services/workflow/state.py`
- Service/Class: `DeleteState` (reply method)
## Environment
- workflow-manager (backend)
- Plone: 6.0+ (plone.restapi usage implied)
- Python: 3.x
- OS: Ubuntu 22.04 (WSL)
## Steps to reproduce
1. Create a new workflow definition or use an existing one (e.g. `simple_publication_workflow`).
2. Add a new state named `Draft` (or pick an existing state).
3. Set this state as the workflow initial state:
- `PATCH /@states/{workflow_id}/Draft`
- body: `{"is_initial_state": true}`
4. Delete the state:
- `DELETE /@states/{workflow_id}/Draft`
- Ensure it is not a destination for any transitions OR provide `replacement_state_id` if required.
5. Try to create a new content item assigned to this workflow (e.g. `POST /@content`).
## Expected behavior
The API should prevent deletion of a state if it is configured as the workflow `initial_state`, returning a clear error (e.g., 409 Conflict / 400 Bad Request) telling the user to assign a new initial state first.
## Actual behavior
The API deletes the state successfully, but the workflow definition’s `initial_state` continues to reference the deleted state id (e.g., `Draft`).
This leaves the workflow in an invalid/corrupted state and content initialization fails (e.g., workflow engine cannot initialize to a missing state).
## Why this is a bug (technical reasoning)
`DeleteState` appears to check referential integrity for transitions (whether transitions point to the state) but does not check the workflow’s global `initial_state` configuration. In DCWorkflow, `initial_state` is a string reference and must point to a valid state id. Deleting the referenced state without updating/blocking breaks workflow integrity.
## Impact
- **Correctness:** Workflow definition becomes invalid for new content.
- **Stability:** Runtime errors during content creation / workflow initialization.
- **UX/Safety:** Admins can perform a destructive action without warning.
## Suggested fix direction
In `DeleteState.reply()`:
1. Load `selected_workflow`
2. If `selected_workflow.initial_state == state_id`:
- Block deletion with a clear error (400/409) requiring the user to set a new initial state first.
3. Alternative: allow deletion only if request provides a `replacement_initial_state`, similar to `replacement_state_id` handling for transitions.
## Notes
This issue was discovered while reviewing backend state deletion logic. I am happy to work on a fix and submit a PR if this behavior is unintended.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.