Release Notes — v0.2.21 (September 19, 2026)


This release consolidates the work completed since v0.2.19: the new state-based workflow engine, the workflow hooks extension point, and the full-page navigation fix (recorded in the changelog under 0.2.20 but never given its own release note).

1. State-Based Workflow Engine (workflow_kind='state_based')

Status: Included in v0.2.21

A second workflow mode for enezaworkflowengine. States and transitions are defined by the developer and drawn by an administrator in the designer, including parallel Fork/Join branches. The existing approval workflow is unchanged: 'approval' remains the default, and a template is state-based only when WorkflowTemplate.workflow_kind = 'state_based'.

Approval workflow State-based workflow
Node types start, approval, condition, end start, state, fork, join, end
Routing Computed (conditions / next_step) Actor chooses an allowed transition
Parallel paths Not supported Fork / Join branches
Document field Approvalstatus workflowstate
Runtime unit One current step One or more active branches (tokens)

Models & Fields

Model / Field Purpose
WorkflowTemplate.workflow_kind approval (default) or state_based.
WorkflowTemplate.state_choices_path Optional per-template override pointing at a TextChoices class.
StepTemplate.state_code State code for state steps; validated against the state vocabulary.
StepTemplate.is_initial / is_terminal Marks start/end states.
StepTemplate.matched_join Links a Fork to its matching Join.
StateTransition Labelled, ordered edge (source_state → target_state).
WorkflowBranch One live path (token) through the workflow; siblings share a fork_scope UUID.

Runtime (enezaworkflowengine/services/state_workflow.py)

  • start_state_workflow, branch move, and completion services.
  • Fork fires all outgoing transitions, spawning one branch per target sharing a fork_scope.
  • Join waits until every sibling branch has been performed, then auto-continues; it has no assignees and is never shown by name.
  • A submitted document is pinned to the template version active at submission.
  • workflowstate mirrors the oldest active state branch; WorkflowBranch rows are authoritative.

State Vocabulary (services/state_choices.py)

  • Developer-owned via a workflowstate field and a WORKFLOW_STATE_CHOICES registry mapping workflow name → TextChoices path.
  • Resolution precedence: registry → per-template state_choices_path → auto-discovery from a document workflowstate field that declares choices.
  • Diagnostic command: python manage.py check_workflow_state_choices --workflowname <name>.

Validation, Designer & Activation

  • validate_state_workflow_template enforces rules S1–S16 (single START, valid transitions, state codes in vocabulary, matched joins, at least one effective assignee per state, …).
  • The workflow designer palette adds State, Fork and Join nodes with vertical ports and labelled transitions.
  • Saving always clones the loaded version into a new inactive version; activation runs the validator and refuses an invalid graph. Assignees only take effect on the active version.

Management Commands

  • assign_state_users, check_workflow_state_choices, create_sample_state_workflow, delete_workflow_template, workflow_instance_status, workflow_task_status.

Migrations

  • 0004_state_based_workflow.py, 0005_state_choices_and_start_end.py.

Documentation

  • state-based-workflow.md, state-based-workflow-architecture.md, state-based-workflow-reference.md, state-based-workflow-troubleshooting.md, and updates to the Workflow developer index.

2. Workflow Hooks System

Status: Included in v0.2.21

A registry-based extension point that runs developer callables on workflow engine events, for both approval and state-based workflows.

Events

Event Kind Fires when
submitted both A document is submitted and the instance starts.
step_entered approval An approval step is entered and approvers assigned.
approved approval An approval step reaches its threshold.
rejected approval A step is rejected (terminal).
changes_requested approval Changes are requested on a step.
state_entered state A branch arrives at a business state.
state_changed state A user successfully moves a branch.
completed both The workflow finishes with no active work left.
cancelled both The workflow is cancelled.

Registration

  • New WorkflowTypeConfig.WORKFLOW_HOOKS registry (workflowconfig/hooks.py), following the same pattern as WORKFLOW_TYPE_REGISTRY and WORKFLOW_STATE_CHOICES.
  • Entries are dotted callable paths or {'handler': path, ...filters} dicts with optional exact-match filters (from_state, to_state, step_name, document_model); the '*' key matches all workflows.
  • Handlers receive a context carrying document_model, document_id, get_document_id() and get_document().

Execution Semantics (services/workflow_hooks.py)

  • Hooks are scheduled with transaction.on_commit, so they can never roll back a transition.
  • Failures are caught, logged, and recorded as a hook WorkflowTransaction entry; remaining hooks still run and the document still moves.
  • WORKFLOW_HOOKS_ASYNC = True enqueues hooks through django_tasks (db_worker); enqueue failure falls back to inline. A WORKFLOW_HOOKS_MAX_DEPTH (default 10) guard stops runaway recursion.
  • Diagnostic command: python manage.py check_workflow_hooks --json.

Config Package Restructure

  • workflowconfig.py became a package: workflowconfig/__init__.py, hooks.py, state_choices.py, type_registry.py. The project template and this repository were migrated to the package form.

Samples & Migration

  • frameworkapp/workflow_hooks.py ships active samples for IncidentWorkflow (state-based) and CreditCardWorkflow (approval).
  • 0006_alter_workflowtransaction_action_type.py adds the hook history action type.
  • New docs: workflow-hooks.md and workflow-hooks-reference.md.

3. Fix: Full-page Navigations Rendered HTMX Partials

Status: Shipped in the 0.2.20 line, included in v0.2.21

Duplicating a tab, pressing Back/Forward, or refreshing a list URL could return the HTMX list fragment instead of the list page, rendering a layout-less document.

  • New HtmxVaryMiddleware (enezaframework/middleware/htmx_vary.py) appends HX-Request to every response's Vary header and sets Cache-Control: no-store on HTML responses in DEBUG.
  • List shells now request their partial from a distinct URL (?partial=1); list views accept HX-Request or partial=1.
  • New FullPageFallbackMixin renders core/full_page_template.html for non-HTMX requests to detail/parameter/inline views, and native POST now follows POST/Redirect/GET.
  • Layouts enable htmx getCacheBusterParam so GETs never share a cache slot with a page navigation.

See the [0.2.20] changelog entry for the complete file-level detail.


4. Version Bump & License

Version

  • setup.py: Version bumped from 0.2.20 → 0.2.21.
  • docs/Release note/CHANGELOG.md: Added a 0.2.21 entry.

License

  • License changed from MIT to the Enezatech Commercial License.
  • setup.py now declares license="Enezatech Commercial License" and uses the License :: Other/Proprietary License classifier instead of License :: OSI Approved :: MIT License.
  • New root LICENSE file: proprietary and confidential, Copyright (c) 2026 Enezatech Digital Solutions, all rights reserved; use requires a written commercial license agreement.
  • MANIFEST.in now includes LICENSE.

Summary

Area Description Scope
State-Based Workflow Developer-defined states/transitions, Fork/Join parallel branches, S1–S16 validator, designer, commands enezaworkflowengine
State Vocabulary WORKFLOW_STATE_CHOICES registry + auto-discovery, diagnostic command enezaworkflowengine, framework/workflowconfig
Workflow Hooks WORKFLOW_HOOKS registry, 9 events, on_commit execution, async mode, depth guard, hook history type enezaworkflowengine, framework/workflowconfig
Config Packaging workflowconfig.py → workflowconfig/ package (hooks, state_choices, type_registry) framework, project template
Navigation Fix Full-page fallback, HtmxVaryMiddleware, PRG on native POST, cache buster enezaframework, templates
Docs 6 new workflow guides, hooks/reference guides, index updates docs/Documentions/Workflow
Migrations 0004, 0005, 0006 enezaworkflowengine
Versioning setup.py → 0.2.21, CHANGELOG + this note root, docs

Note: The developer or agent does not run or claim test results. The user is solely responsible for testing and validating all outputs before committing or deploying.