Skip to content

feat(flow): visual flow builder engine — event catalog, NC Flow interop, object-CRUD actions - #2042

Merged
rubenvdlinde merged 7 commits into
developmentfrom
feat/visual-flow-builder
Jul 23, 2026
Merged

feat(flow): visual flow builder engine — event catalog, NC Flow interop, object-CRUD actions#2042
rubenvdlinde merged 7 commits into
developmentfrom
feat/visual-flow-builder

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Backend for the visual flow builder (companion to the nextcloud-vue feat/vue-3 UI).

What

  • Event catalog (EventCatalogService + GET /api/flow/event-catalog): flow triggers beyond CRUD — object created/updated/deleted (legacy aliases) + locked/unlocked/reverted/state-transitioned, routed by EventCatalogListener. FlowActionService matches via aliasesFor() so legacy flows keep firing.
  • NC Flow interop (Phase 3b): RegisterObjectEntity (IEntity) + RunFlowOperation (ISpecificOperation) register OR objects + a 'Run an OpenRegister flow' operation in native Nextcloud Flow. runNamedFlow() runs a flow by name. Guarded by class_exists.
  • Object-CRUD actions (Phase 4): object.set-field/object.create/object.delete + condition guard in runAction(); recursion-guarded via an activeObjects UUID set.

Verified live (8090)

  • Event-catalog endpoint returns 7 triggers; legacy created flows still fire.
  • NC Flow rule (OR object updated → Run flow) ran an OR flow end-to-end.
  • object.set-field on update stamped a Case title, persisted, no infinite loop.

Not in scope

  • Phase 3a (invoke arbitrary NC operation from our builder): deferred — OCP\WorkflowEngine has no public invoke API; would be a dead block.
  • Follow-up 3.5: frontend operator-settings component so the Flow-rule flow-name is UI-enterable (today via the workflows API).

OpenSpec: openspec/changes/visual-flow-builder (validates clean).

🤖 Generated with Claude Code

Conduction Release Bot added 6 commits July 23, 2026 09:04
…r + NC-Flow interop

Visual builder over the existing x-openregister-flows contract (CnGraphCanvas), an
event-catalog trigger model (object-CRUD → all NC events), object-CRUD action nodes,
and bidirectional Nextcloud Flow interop (NC operations as blocks; OR flows exposed
as an IOperation). Phased tasks 1–5.
Add EventCatalogService as the single source of truth for flow triggers,
exposed via GET /api/flow/event-catalog for the visual builder. Extends
the trigger set past created/updated/deleted to the object lifecycle
events OpenRegister already dispatches — locked, unlocked, reverted and
state-transitioned — routed to the flow runner by a new
EventCatalogListener (create/update/delete stay with FlowActionListener
to avoid double-firing).

FlowActionService now matches a flow's trigger via EventCatalogService::
aliasesFor(), so the canonical ids (object.created) and the pre-catalog
aliases (created) are interchangeable and existing flows keep firing
unchanged. Every catalog id is a real, dispatched, object-carrying event
— no declared-but-never-fired triggers.

Endpoint live-verified on 8090.
Register OpenRegister objects as a Nextcloud Flow (workflowengine)
entity and expose 'Run an OpenRegister flow' as a Flow operation, so the
visual flow builder and native Flow compose both ways:

- RegisterObjectEntity (IEntity): object created/updated/deleted become
  triggers in the Flow rule builder, reusing OR's own dispatched event
  classes so the engine wires them automatically.
- RunFlowOperation (ISpecificOperation, scoped to that entity): runs a
  named flow declared on the object's schema when a rule matches.
- FlowActionService::runNamedFlow() runs one flow's actions by name,
  ignoring its trigger, since the Flow rule already gated it — this is
  non-redundant with the always-on FlowActionListener because the admin
  can add Flow's checks (confidentiality, register, …) to decide when.

Registration guarded by class_exists so boot never fatals without the
soft-dependency workflowengine app.

Live-verified on 8090: 'Run an OpenRegister flow' appears in the Flow
admin UI and the trigger dropdown lists OpenRegister object
created/updated/deleted. (Full rule->fire->action e2e not yet run.)

Note: Phase 3a (invoking arbitrary NC Flow operations from our builder)
is intentionally not built — OCP\WorkflowEngine exposes no public
invoke-operation API, so it could only be a dead block.
Extend the flow engine's action set beyond notifications to act on the
object graph:

- object.set-field / object.update: merge templated fields onto the
  triggering object and persist (PUT-semantic — existing fields carried
  forward so nothing is dropped).
- object.create: create a new object in a target register/schema.
- object.delete: delete the triggering object (or a target UUID).
- condition: a guard that halts the flow when its expression is false
  (operators eq/ne/empty/notEmpty/contains); runAction now returns bool
  and the action loop breaks on a failed condition.

Guarded against unbounded recursion: an object-CRUD write re-dispatches a
lifecycle event back into run(); an activeObjects UUID set makes the
re-entry a no-op (try/finally) so a flow that writes its own object can't
loop. FlowActionService now depends on ObjectService; @register/@Schema
added to the template context.

Live-verified on 8090: an 'updated' flow with object.set-field stamped a
Case title on update, persisted, and did NOT loop; an invalid value was
correctly rejected by schema validation and logged without corrupting the
write.
Mark Phases 1, 2, 4 complete and 3b done (all live-verified on 8090);
record Phase 3a as intentionally deferred (no public NC WorkflowEngine
invoke API). openspec validate: change is valid.
…or-UI follow-up

A global NC Flow rule (OR object updated -> Run flow 'NC stamp', trigger
object.locked) stamped the object title on update — the NC Flow path ran
the OR flow. Follow-up 3.5: frontend operator-settings component so the
flow-name is enterable in the Flow admin UI (today via the workflows API).
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openregister @ a0a3d7c

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

Quality workflow — 2026-07-23 09:16 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 16a185a into development Jul 23, 2026
0 of 2 checks passed
@rubenvdlinde
rubenvdlinde deleted the feat/visual-flow-builder branch July 23, 2026 10:02
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