PSA/docs/workflow/task-inbox-integration.md
Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

20 KiB

Task Inbox Integration Technical Specification

Overview

This document outlines the technical implementation for integrating a Task Inbox system with our distributed workflow engine. The integration will enable human interactions to be seamlessly incorporated into automated workflows through an event-driven architecture.

Core Architecture Principles

  1. Event-Driven Integration - All human tasks are driven by the event sourcing system
  2. Form-Based Interactions - Human interactions are structured around form submissions
  3. Workflow Continuity - Workflows continue execution after human tasks complete
  4. Metadata-Driven UI - UI components are dynamically generated from schema definitions

System Components

1. Task Inbox Data Model

The Task Inbox requires these primary data structures:

Task Definition

Metadata that describes a type of human task. Task definitions can be system-wide or tenant-specific:

  • System Task Definitions (system_workflow_task_definitions table):

    • task_type (TEXT, Primary Key): Identifier for the kind of system task (e.g., 'qbo_mapping_error').
    • Name and description.
    • form_id (TEXT): Name of the form definition (usually a system form).
    • form_type (TEXT): Indicates if the form is 'system' or 'tenant'. For system task definitions, this is typically 'system'.
    • Default assignment rules, priority, SLA/due date calculations.
    • No tenant column, as these are global.
  • Tenant-Specific Task Definitions (workflow_task_definitions table):

    • task_definition_id (UUID, Primary Key): Unique identifier for this tenant's custom task definition.
    • tenant (UUID): Tenant identifier.
    • task_type (TEXT): A type identifier, which could overlap with system task types if a tenant overrides a system behavior (though linkage is distinct).
    • Name and description.
    • form_id (TEXT): Name of the form definition (can be a system form or a tenant-specific form).
    • form_type (TEXT): Indicates if the form is 'system' or 'tenant'.
    • Default assignment rules, priority, SLA/due date calculations.

Task Instance (workflow_tasks table)

A specific task assigned to a user:

  • Task ID (unique identifier)
  • Execution ID (reference to workflow execution)
  • Task Definition Linkage:
    • task_definition_type (TEXT): Stores 'system' or 'tenant', indicating which type of definition this task instance uses.
    • tenant_task_definition_id (UUID, NULLABLE): Foreign key to workflow_task_definitions.task_definition_id. Populated if task_definition_type is 'tenant'.
    • system_task_definition_task_type (TEXT, NULLABLE): Foreign key to system_workflow_task_definitions.task_type. Populated if task_definition_type is 'system'.
  • Status (pending, claimed, completed, canceled)
  • Assignment information
  • Due date
  • Priority
  • Context data (information from the workflow)
  • Response data (form submission data)

2. Workflow Integration Points

Creating Tasks from Workflows

Workflows create human tasks by executing a task creation action:

// Within a workflow definition
async function approvalWorkflow(context) {
  // Create a human task
  const { taskId } = await context.actions.createHumanTask({
    taskType: 'approval',
    title: 'Approve Request',
    description: 'Please review and approve this request',
    priority: 'high',
    dueDate: '2 days', // Relative due date
    assignTo: {
      roles: ['manager'],
      users: [] // Optionally assign to specific users
    },
    contextData: {
      requestId: context.data.get('requestId'),
      amount: context.data.get('amount'),
      customerId: context.data.get('customerId')
    }
  });
  
  // Track the task ID for future reference
  context.data.set('approvalTaskId', taskId);
  
  // Wait for the task to be completed
  const taskComplete = await context.events.waitFor(`Task:${taskId}:Complete`);
  
  // Process the form submission data
  const { approved, comments } = taskComplete.payload;
  
  if (approved) {
    // Handle approval
    context.setState('approved');
  } else {
    // Handle rejection
    context.setState('rejected');
    context.data.set('rejectionReason', comments);
  }
}

Processing Form Submissions

When a user submits a form in the Task Inbox, it triggers this flow:

  1. Validate form data against schema
  2. Mark task as completed
  3. Create a workflow event with form data as payload
  4. Submit event to workflow engine
  5. Workflow resumes execution
// Task completion process (pseudocode)
async function completeTask(taskId, formData, userId) {
  // Start transaction
  const trx = await startTransaction();
  
  try {
    // Get task details
    const task = await getTaskById(taskId, trx); // task will have tenant_task_definition_id, system_task_definition_task_type, and task_definition_type
    
    // Get form schema
    let taskDef;
    if (task.task_definition_type === 'tenant') {
      taskDef = await getTenantTaskDefinition(task.tenant_task_definition_id, trx);
    } else if (task.task_definition_type === 'system') {
      taskDef = await getSystemTaskDefinition(task.system_task_definition_task_type, trx);
    }
    
    if (!taskDef) {
      throw new Error('Task definition not found for the task.');
    }
    
    // The taskDef object (from either system or tenant table) contains form_id and form_type
    const formSchema = await getFormSchema(taskDef.form_id, taskDef.form_type, task.tenant, trx); // getFormSchema might need tenant for tenant-specific forms
    
    // Validate form data
    const isValid = validateFormData(formSchema.jsonSchema, formData);
    if (!isValid) {
      throw new Error('Form data validation failed');
    }
    
    // Update task status
    await updateTaskStatus(taskId, 'completed', userId, trx);
    
    // Create workflow event
    const event = {
      execution_id: task.executionId,
      event_name: `Task:${taskId}:Complete`,
      event_type: 'task_completed',
      payload: formData,
      user_id: userId,
      tenant: task.tenant
    };
    
    // Create event in database
    await createWorkflowEvent(event, trx);
    
    // Publish to event stream
    await publishToEventStream(event, trx);
    
    // Commit transaction
    await trx.commit();
    
    return { success: true };
  } catch (error) {
    // Rollback transaction
    await trx.rollback();
    throw error;
  }
}

3. Extension to Workflow Interfaces

Task Action Result

Extend the existing IWorkflowActionResult to include task-specific properties:

export interface ITaskActionResult extends IWorkflowActionResult {
  task_id: string;
  task_status: string;
  form_id: string;
  assignment: {
    roles?: string[];
    users?: string[];
  };
}

Extend the workflow event system to recognize task-related events:

// Example of task event types
export enum WorkflowTaskEventType {
  TASK_CREATED = 'task_created',
  TASK_CLAIMED = 'task_claimed',
  TASK_UNCLAIMED = 'task_unclaimed',
  TASK_COMPLETED = 'task_completed',
  TASK_CANCELED = 'task_canceled',
  TASK_EXPIRED = 'task_expired'
}

4. User Interface Components

Task Inbox Dashboard

The main interface showing tasks assigned to or available to the user:

  • List of tasks with filters for status, priority, due date
  • Grouping by workflow type, task type, or assignment
  • Quick actions for claiming, completing, or delegating tasks
  • Search and sort capabilities
  • Integration with User Activities Screen: The Task Inbox will be embedded within the new "user activities" screen, providing a centralized location for users to view and interact with their workflow tasks
  • Dual Mode Support: The component will support both standalone mode (full-featured) and embedded mode (compact view for the activities dashboard)

Task Detail View

Displays comprehensive information about a task:

  • Task metadata (title, description, priority, due date)
  • Context information from the workflow
  • Form for user input
  • Task history (claim/unclaim actions, previous submissions)
  • Related workflow information

Form Renderer

Dynamic form generation based on JSON Schema:

  • Uses React JSONSchema Form (RJSF)
  • Custom widgets for specialized inputs
  • Validation based on schema
    • Conditional display logic
    • File attachment handling
Dynamic Content and Templating in Forms

To support dynamic information within forms (e.g., pre-filling fields with context-specific default values or displaying dynamic instructional text), the system utilizes a templating mechanism. This is particularly relevant for how defaultValues in form schemas or default properties of individual schema fields are processed.

The templating engine has been enhanced to use Parsimmon for parsing and safely evaluating a limited set of JavaScript-like expressions within ${...} syntax. This allows for more sophisticated dynamic content, such as:

  • Accessing contextData variables (e.g., ${contextData.userName}).
  • Using logical OR for fallbacks (e.g., ${contextData.optionalValue || 'Default Text'}).
  • Formatting dates (e.g., ${new Date(contextData.eventTime).toLocaleString()}).

This capability is leveraged by the Form Renderer when preparing forms for display, using the contextData associated with the task instance. The implementation ensures that only whitelisted expressions and operations are permitted, maintaining security even with user-influenced template expressions.

For a detailed technical design of this Parsimmon-based templating engine, refer to "docs/technical/parsimmon_templating_engine.md".

5. Database Schema

-- System Task Definitions table
CREATE TABLE system_workflow_task_definitions (
  task_type TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  description TEXT,
  form_id TEXT NOT NULL, -- Refers to system_workflow_form_definitions.name
  form_type TEXT NOT NULL DEFAULT 'system', -- Indicates the form is a system form
  default_priority TEXT DEFAULT 'medium',
  default_sla_days INTEGER DEFAULT 3,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
  -- No tenant column
  -- FOREIGN KEY (form_id) REFERENCES system_workflow_form_definitions(name) -- If desired, though form_id is a name string
);

-- Tenant-Specific Task Definitions table
CREATE TABLE workflow_task_definitions (
  task_definition_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Changed to UUID
  tenant UUID NOT NULL, -- Changed to UUID
  task_type TEXT NOT NULL,
  name TEXT NOT NULL,
  description TEXT,
  form_id TEXT NOT NULL, -- Can refer to system_workflow_form_definitions.name or workflow_form_definitions.name
  form_type TEXT NOT NULL, -- 'system' or 'tenant'
  default_priority TEXT DEFAULT 'medium',
  default_sla_days INTEGER DEFAULT 3,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE(tenant, task_type)
  -- FOREIGN KEY (form_id) ... depends on how you resolve form_id/form_type logic for FKs
);

-- Task Instances table
CREATE TABLE workflow_tasks (
  task_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Changed to UUID
  tenant UUID NOT NULL, -- Changed to UUID
  execution_id UUID NOT NULL, -- Assuming this is also UUID
  -- event_id VARCHAR(255) NOT NULL, -- Consider if this is still needed or how it relates
  
  task_definition_type TEXT NOT NULL, -- 'system' or 'tenant'
  tenant_task_definition_id UUID NULL,
  system_task_definition_task_type TEXT NULL,

  title TEXT NOT NULL,
  description TEXT,
  status VARCHAR(50) NOT NULL DEFAULT 'pending',
  priority VARCHAR(50) NOT NULL DEFAULT 'medium',
  due_date TIMESTAMPTZ,
  context_data JSONB,
  assigned_roles JSONB,
  assigned_users JSONB,
  created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  created_by UUID, -- Assuming user IDs are UUIDs
  claimed_at TIMESTAMPTZ,
  claimed_by UUID,
  completed_at TIMESTAMPTZ,
  completed_by UUID,
  response_data JSONB,

  FOREIGN KEY (tenant_task_definition_id) REFERENCES workflow_task_definitions(task_definition_id),
  FOREIGN KEY (system_task_definition_task_type) REFERENCES system_workflow_task_definitions(task_type),
  CONSTRAINT chk_task_def_type CHECK
    ((task_definition_type = 'tenant' AND tenant_task_definition_id IS NOT NULL AND system_task_definition_task_type IS NULL) OR
     (task_definition_type = 'system' AND system_task_definition_task_type IS NOT NULL AND tenant_task_definition_id IS NULL))
);

-- Task history table for audit trail
CREATE TABLE workflow_task_history (
  history_id VARCHAR(255) PRIMARY KEY,
  task_id VARCHAR(255) NOT NULL,
  tenant VARCHAR(255) NOT NULL,
  action VARCHAR(50) NOT NULL,
  from_status VARCHAR(50),
  to_status VARCHAR(50),
  user_id VARCHAR(255),
  timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  details JSONB,
  FOREIGN KEY (task_id) REFERENCES workflow_tasks(task_id)
);

Implementation Strategy

Handling Tasks with Inline Forms

While the primary mechanism described above involves tasks linked to pre-registered form definitions via taskType, the system also supports tasks created with "inline forms." Inline forms are defined directly within the workflow code at the point of task creation (e.g., using actions like create_task_with_inline_form or createInlineTaskAndWaitForResult).

Here's how these are integrated into the Task Inbox:

  1. Dynamic Definition Creation: When a task is initiated with an inline form:

    • The system dynamically creates a temporary, tenant-specific form definition in the workflow_form_definitions table. This definition is flagged (e.g., is_temporary: true).
    • The JSON and UI schemas provided inline are stored in workflow_form_schemas, linked to this temporary form definition.
    • A corresponding temporary, tenant-specific task definition is created in workflow_task_definitions. This task definition links to the temporary form ID and specifies form_type: 'tenant'.
  2. Task Instance Linking: The actual task instance created in workflow_tasks is then linked to this temporary tenant-specific task definition using:

    • task_definition_type: 'tenant'
    • tenant_task_definition_id: The ID of the dynamically created temporary task definition.
  3. Schema Retrieval by Task Inbox: Because the task instance points to a standard (though temporary) tenant-specific task definition, the Task Inbox can retrieve its form schema using the same logic as for pre-registered forms:

    • The inbox identifies the task_definition_type as 'tenant'.
    • It uses tenant_task_definition_id to fetch the temporary task definition.
    • This definition provides the form_id (of the temporary form) and form_type ('tenant').
    • The Form Registry service (or similar logic) then retrieves the schemas from workflow_form_definitions and workflow_form_schemas.
  4. Lifecycle and Cleanup: These temporary definitions are typically cleaned up by a background job, as detailed in the inline forms documentation (see docs/workflow/inline-form-example.md).

This approach allows workflows to flexibly define ad-hoc forms while ensuring the Task Inbox can consistently render and manage them without requiring separate logic for inline versus pre-registered forms at the retrieval stage.

Phase 1: Core Infrastructure

  1. Database Schema Implementation

    • Create database tables for task definitions and instances
    • Add indexes for query optimization
    • Implement database migration scripts
  2. Task Inbox Service

    • Develop core service for task management
    • Implement task creation, claiming, and completion
    • Create event integration with workflow engine
  3. Form Integration

    • Integrate Form Registry with Task Inbox
    • Implement form validation and submission
    • Connect form submission to event creation

Phase 2: UI Development

  1. Task Inbox Dashboard

    • Build list view of tasks with filtering
    • Implement task sorting and pagination
    • Create task action buttons (claim, complete)
    • Develop both standalone and embedded modes for the component
    • Create responsive design that adapts to the user activities screen context
  2. User Activities Screen Integration

    • Implement embedded version of Task Inbox for the user activities screen
    • Create compact view for the activities dashboard
    • Ensure consistent styling and interaction patterns with other activity types
    • Implement drawer-based navigation for task details within the activities context
  3. Task Detail View

    • Create task detail display
    • Integrate dynamic form renderer
    • Implement form submission handling
    • Support viewing task details both standalone and within the activities drawer system
  4. Notification System

    • Add real-time updates for new tasks
    • Implement due date notifications
    • Create alert system for high priority tasks
    • Ensure notifications work in both standalone and embedded contexts
    • Create alert system for high priority tasks

Phase 3: Workflow Integration

  1. Action Registry Extension

    • Add task-related actions to workflow action registry
    • Implement task creation action
    • Add task query and update actions
  2. Event Processing

    • Enhance event processing for task events
    • Implement event replay for task-related events
    • Create task status synchronization
  3. Workflow Runtime Updates

    • Update workflow runtime to process task events
    • Implement waiting for task completion
    • Add task timeout handling

Security Considerations

  1. Authorization

    • Task visibility based on user roles and permissions
    • Task claiming restrictions based on assignment rules
    • Form field visibility control based on user role
  2. Audit Trail

    • Comprehensive logging of all task interactions
    • Record of form submissions and task status changes
    • Timestamps and user information for all actions
  3. Data Protection

    • Encryption of sensitive form data
    • Tenant isolation for multi-tenant deployments
    • Proper validation to prevent injection attacks

Performance Optimization

  1. Indexing Strategy

    • Optimized indexes for task queries
    • Efficient filtering by status, priority, and assignment
  2. Caching Layer

    • Cache task definitions and form schemas
    • Implement result caching for frequent queries
  3. Batch Processing

    • Batch notifications for task updates
    • Optimized query patterns for task listing

Monitoring and Observability

  1. Metrics Collection

    • Task completion time tracking
    • SLA compliance monitoring
    • User efficiency metrics
  2. Logging

    • Structured logging for task operations
    • Error tracking for form validation issues
    • Performance logging for slow operations
  3. Alerting

    • Alerts for tasks approaching SLA deadlines
    • Notification for stalled workflows
    • System health monitoring

Future Enhancements

  1. Task Delegation and Reassignment

    • Allow users to delegate tasks to others
    • Implement task reassignment workflows
    • Add delegation history tracking
  2. Advanced Form Features

    • Multi-step forms with wizard interface
    • Conditional section visibility
    • Dynamic field generation based on context
  3. Collaborative Features

    • Comments and discussions on tasks
    • Shared editing of responses
    • Activity feed for task interactions
  4. Mobile Support

    • Responsive design for mobile devices
    • Push notifications for task assignments
    • Simplified mobile form interfaces