Workflow Definitions — Phase 1 Design
Date: 2026-08-20 Epic: Custom Workflow Feature for Axiom
Summary
Add workflow definition management and a visual editor to Axiom, powered by Apitomy Flow. Users create workflow definitions using a drag-and-drop editor, save drafts, and publish immutable versioned snapshots. This is Phase 1 of a multi-phase effort — later phases add execution, human tasks, event correlation, and wait node support.
Apitomy Flow provides:
- Java engine (io.apitomy:apitomy-flow-engine) — stateless workflow execution engine with
validation
- React UI (@apitomy/flow-ui) — WorkflowEditor (drag-and-drop editor) and
WorkflowViewer (read-only instance viewer)
Phase 1 uses the engine for server-side validation on publish, and the WorkflowEditor
component for the visual editor UI.
Data Model
workflow_definition table
Stores the mutable draft and metadata for each workflow definition. Workflow definitions are global to Axiom (not project-scoped).
| Column | Type | Constraints | Description |
|---|---|---|---|
id |
bigint |
PK, auto-generated | |
name |
varchar |
NOT NULL, UNIQUE | Human-readable name |
description |
text |
Optional description | |
content |
text |
Current draft workflow JSON (nodes, edges, positions) | |
current_version |
int |
Latest published version number; null if never published | |
created_on |
timestamp |
NOT NULL | |
updated_on |
timestamp |
NOT NULL |
workflow_definition_version table
Stores immutable published snapshots. All versions are kept indefinitely.
| Column | Type | Constraints | Description |
|---|---|---|---|
id |
bigint |
PK, auto-generated | |
definition_id |
bigint |
FK → workflow_definition, NOT NULL | |
version |
int |
NOT NULL | Version number (1, 2, 3...) |
content |
text |
NOT NULL | Frozen workflow JSON at publish time |
created_on |
timestamp |
NOT NULL | When published |
Constraints: Unique index on (definition_id, version).
Versioning model
- Each workflow definition has a single mutable draft (the
contentcolumn onworkflow_definition). - The user can publish the draft at any time, which copies the current
contentto a new row inworkflow_definition_versionwith an incremented version number. - Published versions are immutable — they cannot be edited or deleted.
- Running workflow instances (Phase 2) will be pinned to the version they started with.
API Design
All endpoints follow the contract-first approach: defined in openapi.json first, then
generated interfaces are implemented.
Workflow Definition endpoints
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/workflow-definitions |
List all definitions (paginated, searchable by name) |
POST |
/api/v1/workflow-definitions |
Create a new definition |
GET |
/api/v1/workflow-definitions/{id} |
Get a definition (returns draft content) |
PUT |
/api/v1/workflow-definitions/{id} |
Update definition metadata (name, description) |
DELETE |
/api/v1/workflow-definitions/{id} |
Delete a definition (reject if instances exist) |
PUT |
/api/v1/workflow-definitions/{id}/content |
Update draft workflow content |
POST |
/api/v1/workflow-definitions/{id}/publish |
Publish current draft as a new immutable version |
Workflow Definition Version endpoints
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/workflow-definitions/{id}/versions |
List all published versions |
GET |
/api/v1/workflow-definitions/{id}/versions/{version} |
Get a specific version's content |
Request/Response schemas
WorkflowDefinition (response):
{
"id": 1,
"name": "CVE Triage",
"description": "Standard CVE triage and remediation workflow",
"content": { "id": "...", "name": "...", "nodes": [...], "edges": [...] },
"currentVersion": 3,
"createdOn": "2026-08-20T12:00:00Z",
"updatedOn": "2026-08-20T14:30:00Z"
}
contentis the draft workflow JSON (the Apitomy FlowWorkflowobject).currentVersionis null if never published.
NewWorkflowDefinition (create request):
contentis not provided on create — the backend initializes an empty workflow containing a single start node and a single end node connected by a default edge, with sensible default positions.
UpdateWorkflowDefinition (update metadata request):
WorkflowDefinitionContent (update content request — PUT .../content):
The request body is the raw Apitomy Flow Workflow JSON object:
WorkflowDefinitionVersion (response):
{
"id": 10,
"definitionId": 1,
"version": 3,
"content": { "id": "...", "name": "...", "nodes": [...], "edges": [...] },
"createdOn": "2026-08-20T14:30:00Z"
}
Publish behavior
POST /api/v1/workflow-definitions/{id}/publish:
- Load the definition's current draft
content. - Run Apitomy Flow's
WorkflowValidatoragainst the content. - If there are ERROR-level validation problems, return 400 with the validation errors.
- Otherwise, create a new
workflow_definition_versionrow withversion = currentVersion + 1(or 1 if never published). - Update
workflow_definition.current_versionto the new version number. - Return the new
WorkflowDefinitionVersion.
Delete behavior
DELETE /api/v1/workflow-definitions/{id}:
- Returns 409 Conflict if any workflow instances reference this definition (Phase 2 will add this check). For now, deletes are always allowed.
- Deleting a definition also deletes all its published versions (cascade).
Backend Implementation
Entities
WorkflowDefinitionEntity — Panache entity in the core module:
- Maps to workflow_definition table
- content field is a String storing the raw JSON
WorkflowDefinitionVersionEntity — Panache entity in the core module:
- Maps to workflow_definition_version table
- content field is a String storing the frozen JSON
REST Resource
WorkflowDefinitionsResourceImpl implements WorkflowDefinitionsResource in the app
module's rest package. Follows the existing pattern: generated interface from OpenAPI, impl
class with no @Path annotations.
Validation on publish
The app module depends on io.apitomy:apitomy-flow-engine. On publish:
- Deserialize the draft
contentJSON into a FlowWorkflowobject using Jackson. - Call
WorkflowValidator.validate(workflow). - Filter for ERROR-severity problems.
- If any exist, return 400 with the problems as the response body.
Draft saves (PUT .../content) do not run server-side validation. The WorkflowEditor
component runs client-side validation in real time.
Maven dependency
Add to app/pom.xml:
<dependency>
<groupId>io.apitomy</groupId>
<artifactId>apitomy-flow-engine</artifactId>
<version>${flow.version}</version>
</dependency>
UI Implementation
Navigation
Add "Workflows" as a new item under the Components expandable nav section, alongside Action Types, Tools, Toolsets, etc.
Workflow Definitions List Page
Route: /components/workflows
- Table with columns: Name, Description, Current Version (show "Draft" if never published), Updated
- "Create Workflow" button opens a modal with Name and Description fields
- Click a row to navigate to the detail page
- Search/filter by name
Workflow Definition Detail Page
Route: /components/workflows/{id}
- Breadcrumb: Components > Workflows > {name}
- Header area:
- Name and description (editable via an edit button/modal)
- Current version badge (e.g., "v3" or "Draft")
- Save button — disabled when content is clean, enabled when dirty. Visual indicator (e.g., dot or "Unsaved changes") when dirty.
- Publish button — disabled when content is dirty (must save first) or when there are
ERROR-level validation problems. Calls
POST .../publish. - Delete button
- Main content: Embedded
WorkflowEditorcomponent from@apitomy/flow-ui - Fills the remaining viewport height (container with explicit dimensions)
workflowprop: the current draft contentonChangecallback: stores updated content in component state and sets dirty flagonValidationChangecallback: tracks validation problems to control Publish button statespi.actionTypes: async function that fetches Axiom action types from the existingGET /api/v1/action-typesendpoint and maps them toActionTypeDescriptorobjects. In Phase 1, all action types are provided. In Phase 2, this will be filtered to only those with anoutputSchema.theme: matched to Axiom's current light/dark mode setting- Version history: Collapsible section listing published versions with version number and timestamp.
- Unsaved changes guard: Browser
beforeunloadwarning if navigating away with dirty content.
npm dependencies
Add to ui/package.json:
- @apitomy/flow-ui — the visual editor and viewer components
- @xyflow/react — peer dependency required by @apitomy/flow-ui
Import in the application:
- @apitomy/flow-ui/style.css
- @xyflow/react/dist/style.css
Testing
Backend integration tests
WorkflowDefinitionsResourceTest — REST integration test (Quarkus @QuarkusTest),
following the same pattern as ProjectsResourceTest:
- Create a workflow definition — verify 200, returned fields
- Get a definition by ID — verify content matches
- List definitions — verify pagination and search by name
- Update metadata (name, description) — verify fields updated
- Update draft content — verify content persisted
- Publish a valid workflow — verify version created,
currentVersionincremented - Publish an invalid workflow — verify 400 with validation errors
- List versions — verify version history
- Get a specific version — verify frozen content matches
- Delete a definition — verify removed
- Delete cascades versions — verify version rows removed
Manual browser testing
- Create workflow, add nodes/edges in the editor, save, publish
- Verify dirty indicator and Save/Publish button states
- Verify validation problems block publish
- Verify version history updates after publish
- Verify light/dark theme consistency
Future phases
This spec covers Phase 1 only. Subsequent phases will add:
- Phase 2: Workflow execution — triggering, action node execution (async), instance viewer
- Phase 3: Human task nodes — inbox integration, task forms
- Phase 4: Event correlation — receive-event nodes, wait nodes
- Phase 5: Polish — audit/history view, error handling, edge cases