Skip to content

feat(workflow-definition-model): apply spec#382

Merged
rubenvdlinde merged 1 commit into
developmentfrom
feat/apply-workflow-definition-model
May 11, 2026
Merged

feat(workflow-definition-model): apply spec#382
rubenvdlinde merged 1 commit into
developmentfrom
feat/apply-workflow-definition-model

Conversation

@rubenvdlinde
Copy link
Copy Markdown
Contributor

Summary

Applies openspec change workflow-definition-model to Procest, exposing the existing workflowTemplate schema with a draft → published → deprecated lifecycle and a stable consumer contract for status-transition-engine and role-based-step-routingmanifest-first, without growing bespoke CRUD.

  • Schema gains lifecycleStatus enum + caseType.workflowDefinition pin; version bumped to 1.1.0. workflow_definition_schema alias added so consumer specs resolve the id independent of the legacy slug.
  • Manifest pages WorkflowDefinitions (index) + WorkflowDefinitionDetail (detail) + settings menu entry handle CRUD — no bespoke Vue controllers or list/edit components.
  • WorkflowDefinitionService owns the legitimate domain logic: publish (atomic — deprecates previous active, pins caseType.workflowDefinition, validates that transitions only reference statusTypes of the linked caseType), deprecate (refuses to strand open cases), cloneDefinition (version + 1). Read-only consumer methods: getActiveDefinitionFor, getDefinition, getDefinitionForCase, listVersions.
  • WorkflowDefinitionController exposes only action endpoints — no CRUD: POST /api/workflow-definitions/{id}/{publish|deprecate|clone}, GET /api/workflow-definitions/{active|for-case}/....
  • lib/Repair/MigrateWorkflowDefinitions.php backfills one published workflowTemplate per existing caseType from its statusType ordering, idempotent on re-run.

All errors logged via LoggerInterface; controller never returns raw exception messages — static error strings only.

Test plan

  • php -l and jq empty pass for all touched files (verified locally).
  • Run occ maintenance:repair and confirm the backfill produces one published workflowTemplate per existing caseType with lifecycleStatus: published and caseType.workflowDefinition pinned.
  • In the Procest UI, navigate to Settings → Workflow definitions; create a draft via the manifest renderer; verify it loads at /settings/workflow-definitions/:id with the overview / steps / transitions / audit tabs.
  • Call POST /api/workflow-definitions/{id}/publish on a draft; verify lifecycleStatus flips to published, the previously active version flips to deprecated, and caseType.workflowDefinition updates to the new id.
  • Call POST /api/workflow-definitions/{id}/clone on a published version; verify a new draft appears with version = previous + 1.
  • Attempt to publish a draft whose transitions reference a foreign statusType — request rejected, error logged.

Implements openspec change workflow-definition-model.

Expose the existing workflowTemplate schema with a draft → published →
deprecated lifecycle, version pinning, a consumer contract for
status-transition-engine + role-based-step-routing, and a backfill
repair step — without growing bespoke CRUD.

Schema (manifest-first; pure CRUD goes through the manifest renderer +
OpenRegister auto-routing):
- lib/Settings/procest_register.json — workflowTemplate gains a
  lifecycleStatus enum (draft|published|deprecated), version bumped to
  1.1.0; caseType gains a workflowDefinition uuid reference for the
  pinned active version.
- lib/Service/SettingsService.php — workflow_definition_schema alias
  mirrors workflow_template_schema so consumer specs can resolve the
  schema id without depending on the legacy slug.

Manifest pages (no bespoke Vue components):
- WorkflowDefinitions (index) at /settings/workflow-definitions
- WorkflowDefinitionDetail (detail) with overview / steps /
  transitions / audit-trail sidebar tabs and publish / deprecate /
  clone actions wired to the controller endpoints.
- Settings menu entry "Workflow definitions".

Backend services (legitimate domain logic, not CRUD):
- WorkflowDefinitionService — lifecycle (publish, deprecate,
  cloneDefinition) and read-only consumer contract
  (getActiveDefinitionFor, getDefinition, getDefinitionForCase,
  listVersions). Atomic publish deprecates the previously active
  version and pins caseType.workflowDefinition; deprecate refuses to
  strand open cases; clone increments version. Referential integrity
  check rejects publishing a draft whose transitions reference foreign
  statusType ids. All errors logged + static error strings returned —
  no raw exception leakage.
- WorkflowDefinitionController — five action-only endpoints (publish,
  deprecate, clone, active, for-case). No CRUD methods.

Routes (action endpoints only, /api/workflow-definitions/...):
- POST /{id}/publish, /{id}/deprecate, /{id}/clone
- GET  /active/{caseTypeId}, /for-case/{caseId}

Migration:
- lib/Repair/MigrateWorkflowDefinitions.php — idempotent backfill that
  synthesises one published workflowTemplate per existing caseType from
  its statusType ordering, pins caseType.workflowDefinition, and binds
  open cases to workflowVersion 1. Skips caseTypes that already have a
  workflowDefinition reference or any existing template.
- appinfo/info.xml — repair step registered.

Implements openspec change workflow-definition-model.
@rubenvdlinde rubenvdlinde merged commit 9ae3d54 into development May 11, 2026
13 of 16 checks passed
@rubenvdlinde rubenvdlinde deleted the feat/apply-workflow-definition-model branch May 11, 2026 11:45
@github-actions
Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ d9991f7

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 100/100
npm ✅ 407/407
PHPUnit ⏭️
Newman ⏭️
Playwright

Spec coverage: 3% (21 tests / 673 specs)


Quality workflow — 2026-05-11 11:59 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant