Files
James MaesandClaude Sonnet 5.5 8ced11cc1d
QRun-IO/ci-policy: ci / fork-guard (pull_request) Skipped
QRun-IO/ci-policy: native / fork-deny (pull_request) Skipped
QRun-IO/ci-policy: native / dotnet-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / Scoped workflow [workflow 60e5a80ed7a5a67877bfb3e129b1929c83464b6e] (pull_request) Successful in 10s
QRun-IO/ci-policy: ci / head-profile (pull_request) Skipped
QRun-IO/ci-policy: ci / repository-policy (pull_request) Skipped
QRun-IO/ci-policy: ci / application-template-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / gradle-1 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (pull_request) Skipped
QRun-IO/ci-policy: ci / node-8 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-9 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-10 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (pull_request) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-13 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-14 (pull_request) Skipped
QRun-IO/ci-policy: ci / android-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / original-business (pull_request) Skipped
QRun-IO/ci-policy: ci / original-mcp (pull_request) Skipped
QRun-IO/ci-policy: ci / original-voyage (pull_request) Skipped
QRun-IO/ci-policy: ci / original-cli (pull_request) Skipped
QRun-IO/ci-policy: ci / not-enrolled (pull_request) Skipped
QRun-IO/ci-policy: ci / shared-pipeline (pull_request) Skipped
QRun-IO/ci-policy: native / native-result (pull_request) Successful in 13s
Shared Java Maven CI / secrets (push) Successful in 40s
QRun-IO/ci-policy: Shared Java Maven CI / secrets (pull_request) Successful in 40s
Shared Java Maven CI / gate (push) Canceled after 0s
Shared Java Maven CI / verify (push) Canceled after 0s
qrun-release / release (push) Canceled after 5m50s
qrun-release / postpublish (push) Canceled after 0s
QRun-IO/ci-policy: Shared Java Maven CI / gate (pull_request) Canceled after 0s
QRun-IO/ci-policy: Shared Java Maven CI / verify (pull_request) Canceled after 0s
QRun-IO/ci-policy: ci / java-maven-6 (pull_request) Canceled after 30m32s
QRun-IO/ci-policy: ci / ci-result (pull_request) Canceled after 0s
fix: adapt workflows to the QQQ 4.1 API
Build against the published QQQ 4.1 core (qqq-bom-pom 4.1.0-RC.21), state
the minimum QQQ version as 4.1.0+, and port to the 4.1 API: build the
table API field lookup with GetTableApiFieldsInput and override
customizeInputPreQuery(RunBackendStepInput, QueryInput). Update BaseTest
and add WorkflowTestAssertionFormAdjusterTest.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 05:44:23 -06:00

3.8 KiB

qbit-workflows

State machine workflows for QQQ applications.

For: QQQ developers building approval flows, order pipelines, or any multi-step business processes
Status: Stable

Why This Exists

Business processes have states. Orders go from pending to approved to shipped. Support tickets move through triage, investigation, and resolution. Building these flows means tracking state, validating transitions, and triggering actions at each step.

This QBit provides a declarative workflow engine. Define states and transitions, and the system enforces valid paths, runs actions on transitions, and tracks history automatically.

Features

  • State Definitions - Define allowed states for any entity
  • Transition Rules - Control which states can move to which other states
  • Transition Actions - Execute code when moving between states
  • Role-Based Transitions - Restrict who can trigger which transitions
  • Transition History - Automatic audit log of all state changes
  • Dashboard Integration - Status badges and transition buttons in the UI

Quick Start

Prerequisites

  • QQQ application (v4.1.0+)
  • Database backend configured

Installation

Add to your pom.xml:

<dependency>
    <groupId>com.kingsrook.qbits</groupId>
    <artifactId>qbit-workflows</artifactId>
    <version>0.4.0</version>
</dependency>

Register the QBit

public class AppMetaProvider extends QMetaProvider {
    @Override
    public void configure(QInstance qInstance) {
        new WorkflowsQBit().configure(qInstance);
    }
}

Define a Workflow

new QWorkflowMetaData()
    .withName("orderWorkflow")
    .withTable("order")
    .withStatusField("status")
    .withStates(
        new QWorkflowState("pending", "Pending"),
        new QWorkflowState("approved", "Approved"),
        new QWorkflowState("shipped", "Shipped"),
        new QWorkflowState("cancelled", "Cancelled")
    )
    .withTransitions(
        new QWorkflowTransition("pending", "approved"),
        new QWorkflowTransition("pending", "cancelled"),
        new QWorkflowTransition("approved", "shipped"),
        new QWorkflowTransition("approved", "cancelled")
    );

Usage

Transition Actions

new QWorkflowTransition("approved", "shipped")
    .withAction(new ShipOrderAction());

public class ShipOrderAction implements WorkflowTransitionAction {
    @Override
    public void execute(WorkflowTransitionContext context) {
        // Send shipping notification
        // Update inventory
        // Generate tracking number
    }
}

Role-Based Transitions

// Only managers can approve
new QWorkflowTransition("pending", "approved")
    .withAllowedRoles("manager", "admin");

Transition Validation

new QWorkflowTransition("approved", "shipped")
    .withValidator((context) -> {
        if (context.getRecord().getValue("shippingAddress") == null) {
            throw new WorkflowException("Shipping address required");
        }
    });

Querying by State

// Find all pending orders
QueryInput query = new QueryInput()
    .withTableName("order")
    .withFilter(new QQueryFilter()
        .withCriteria("status", Operator.EQUALS, "pending"));

Configuration

The QBit creates a transition history table automatically:

Table Purpose
workflow_transition_log Audit trail of all state changes

Each log entry records: record ID, from state, to state, user, timestamp, and optional comments.

Project Status

Stable and production-ready.

Roadmap

  • Parallel state support (multiple active states)
  • Scheduled transitions (auto-expire after N days)
  • Workflow visualization in dashboard

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Run tests: mvn clean verify
  4. Submit a pull request

License

Proprietary - QRun.IO