feat: IT Glue integration, workflow engine, pipelines, Zabbix WAN, notification channels, backup status UI improvements, nav alignment fixes

This commit is contained in:
lorentz 2026-02-27 14:52:14 -05:00
parent ed6c4a8b65
commit 19605f82aa
97 changed files with 17080 additions and 304 deletions

171
lib/types/pipeline.ts Normal file
View file

@ -0,0 +1,171 @@
/**
* Pipeline Engine Types
*/
export type TriggerSource = 'datto_rmm' | 'autotask' | 'veeam' | 'manual';
export type StepType =
| 'filter'
| 'transform'
| 'set_variable'
| 'delay'
| 'enrich_device'
| 'enrich_company'
| 'enrich_ticket'
| 'create_ticket'
| 'update_ticket'
| 'create_note'
| 'ai_analyze'
| 'notify'
| 'approval'
| 'rmm_quick_job'
| 'rmm_get_job_results';
export type ChannelType = 'teams' | 'telegram' | 'ntfy' | 'webhook';
export type PipelineStatus = 'pending' | 'running' | 'waiting' | 'completed' | 'failed' | 'skipped';
export type StepStatus = 'pending' | 'running' | 'completed' | 'failed' | 'waiting' | 'skipped';
export type ApprovalStatus = 'pending' | 'approved' | 'rejected' | 'timeout';
export type OnFailure = 'continue' | 'stop' | 'skip_to';
export interface TriggerCondition {
field: string;
operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'in' | 'not_in' | 'regex' | 'exists' | 'not_exists';
value: any;
}
// ============================================================================
// DB Row Types
// ============================================================================
export interface NotificationChannel {
id: number;
name: string;
channel_type: ChannelType;
config: Record<string, any>;
is_active: boolean;
created_at: Date;
updated_at: Date;
}
export interface WebhookPipeline {
id: number;
name: string;
description: string | null;
is_active: boolean;
trigger_source: TriggerSource;
trigger_conditions: TriggerCondition[];
sort_order: number;
created_at: Date;
updated_at: Date;
}
export interface PipelineStep {
id: number;
pipeline_id: number;
step_order: number;
step_type: StepType;
name: string;
config: Record<string, any>;
on_failure: OnFailure;
skip_to_step: number | null;
is_active: boolean;
timeout_ms: number | null;
created_at: Date;
updated_at: Date;
}
export interface PipelineExecution {
id: number;
pipeline_id: number;
trigger_source: string;
trigger_payload: Record<string, any> | null;
status: PipelineStatus;
current_step: number | null;
context: Record<string, any>;
started_at: Date;
completed_at: Date | null;
duration_ms: number | null;
error_message: string | null;
created_at: Date;
}
export interface PipelineExecutionStep {
id: number;
execution_id: number;
step_order: number;
step_type: string;
step_name: string | null;
status: StepStatus;
input_data: Record<string, any> | null;
output_data: Record<string, any> | null;
started_at: Date | null;
completed_at: Date | null;
duration_ms: number | null;
error_message: string | null;
}
export interface ApprovalRequest {
id: number;
execution_id: number;
step_order: number;
channel_id: number | null;
message: string;
options: string[];
status: ApprovalStatus;
responded_by: string | null;
responded_at: Date | null;
response_data: Record<string, any> | null;
expires_at: Date | null;
created_at: Date;
}
// ============================================================================
// Runtime Types
// ============================================================================
export interface PipelineContext {
[key: string]: any;
}
export interface StepExecutorResult {
success: boolean;
output?: Record<string, any>;
error?: string;
waiting?: boolean; // true if step is paused (e.g., approval)
}
export interface PipelineWithSteps extends WebhookPipeline {
steps: PipelineStep[];
}
// ============================================================================
// API Types
// ============================================================================
export interface PipelineInput {
name: string;
description?: string;
is_active?: boolean;
trigger_source: TriggerSource;
trigger_conditions?: TriggerCondition[];
sort_order?: number;
}
export interface PipelineStepInput {
step_order: number;
step_type: StepType;
name: string;
config?: Record<string, any>;
on_failure?: OnFailure;
skip_to_step?: number;
is_active?: boolean;
timeout_ms?: number;
}
export interface NotificationChannelInput {
name: string;
channel_type: ChannelType;
config: Record<string, any>;
is_active?: boolean;
}

View file

@ -0,0 +1,128 @@
/**
* Ticket Workflow Engine Types
* TypeScript definitions for the refactored table-driven workflow engine
*/
import { TicketData, WorkflowSettings } from './workflow';
// ============================================================================
// Database Row Types
// ============================================================================
export interface TicketWorkflow {
id: number;
name: string;
description: string | null;
is_active: boolean;
trigger_event: string;
trigger_conditions: TriggerCondition[];
sort_order: number;
created_at: Date;
updated_at: Date;
}
export interface TicketWorkflowStep {
id: number;
workflow_id: number;
step_order: number;
step_type: string;
name: string;
config: Record<string, any>;
on_failure: 'continue' | 'stop' | 'skip_to';
skip_to_step: number | null;
is_active: boolean;
condition: StepCondition | null;
created_at: Date;
updated_at: Date;
}
export interface TicketWorkflowExecution {
id: number;
workflow_id: number;
ticket_id: number;
ticket_number: string | null;
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
classification_method: 'robotic' | 'ai' | 'hybrid' | null;
branch: 'service_desk' | 'noc' | 'soc' | null;
context: Record<string, any>;
field_changes: Record<string, { before: any; after: any }> | null;
started_at: Date;
completed_at: Date | null;
duration_ms: number | null;
error_message: string | null;
created_at: Date;
}
export interface TicketWorkflowExecutionStep {
id: number;
execution_id: number;
step_order: number;
step_type: string;
step_name: string | null;
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
input_data: Record<string, any> | null;
output_data: Record<string, any> | null;
started_at: Date | null;
completed_at: Date | null;
duration_ms: number | null;
error_message: string | null;
}
// ============================================================================
// Workflow Execution Types
// ============================================================================
export interface TriggerCondition {
field: string;
operator: 'equals' | 'not_equals' | 'in' | 'not_in' | 'contains' | 'not_contains' | 'gt' | 'lt';
value: any;
}
export interface StepCondition {
field: string;
operator: 'equals' | 'not_equals' | 'in' | 'not_in' | 'contains' | 'not_contains' | 'gt' | 'lt' | 'is_null' | 'is_not_null';
value: any;
}
export interface WorkflowStepContext {
// Original ticket data
ticket: TicketData;
// Workflow settings (from workflow_settings table)
_settings: WorkflowSettings;
// Accumulated classification results from classify steps
classification?: Record<string, any>;
// Validation result from validate step
validation?: {
is_valid: boolean;
errors: Array<{ field: string; message: string; value: any }>;
};
// Field changes accumulated from all steps (will be written to Autotask)
field_changes?: Record<string, { before: any; after: any }>;
// Any other data accumulated by steps
[key: string]: any;
}
export interface WorkflowStepResult {
success: boolean;
output?: Record<string, any>;
error?: string;
}
export interface TicketWorkflowWithSteps extends TicketWorkflow {
steps: TicketWorkflowStep[];
}
// ============================================================================
// Step Executor Function Type
// ============================================================================
export type WorkflowStepExecutorFn = (
step: TicketWorkflowStep,
context: WorkflowStepContext,
executionId: number
) => Promise<WorkflowStepResult>;

View file

@ -109,8 +109,10 @@ export interface AutotaskWebhookPayload {
*/
const ENTITY_TYPE_MAP: Record<string, WebhookEntityType> = {
'Company': WebhookEntityType.COMPANIES,
'Account': WebhookEntityType.COMPANIES, // Autotask legacy name
'Contact': WebhookEntityType.CONTACTS,
'ConfigurationItem': WebhookEntityType.CONFIGURATION_ITEMS,
'InstalledProduct': WebhookEntityType.CONFIGURATION_ITEMS, // Autotask actual payload name
'Ticket': WebhookEntityType.TICKETS,
'TicketNote': WebhookEntityType.TICKET_NOTES,
};

81
lib/types/zabbix.ts Normal file
View file

@ -0,0 +1,81 @@
// Zabbix API Types
export interface ZabbixConfig {
apiUrl: string;
apiToken: string;
}
export interface ZabbixHost {
hostid: string;
host: string;
name: string;
status: string;
interfaces?: ZabbixHostInterface[];
groups?: ZabbixHostGroup[];
templates?: ZabbixTemplate[];
description?: string;
}
export interface ZabbixHostInterface {
type: number; // 1 = agent, 2 = SNMP, 3 = IPMI, 4 = JMX
main: number; // 1 = default
useip: number; // 1 = use IP, 0 = use DNS
ip: string;
dns: string;
port: string;
}
export interface ZabbixHostGroup {
groupid: string;
name: string;
}
export interface ZabbixTemplate {
templateid: string;
host: string;
name?: string;
}
export interface ZabbixHostMacro {
macro: string; // e.g. "{$AUTOTASK_COMPANY_ID}"
value: string;
description?: string;
}
export interface ZabbixHostTag {
tag: string; // e.g. "client"
value: string; // e.g. "TK Plastics"
}
export interface ZabbixHostCreateParams {
host: string;
name?: string;
description?: string;
interfaces: ZabbixHostInterface[];
groups: Array<{ groupid: string }>;
templates?: Array<{ templateid: string }>;
macros?: ZabbixHostMacro[];
tags?: ZabbixHostTag[];
}
export interface ZabbixHostUpdateParams {
hostid: string;
name?: string;
description?: string;
interfaces?: ZabbixHostInterface[];
groups?: Array<{ groupid: string }>;
templates?: Array<{ templateid: string }>;
macros?: ZabbixHostMacro[];
tags?: ZabbixHostTag[];
}
export interface ZabbixRpcResponse<T> {
jsonrpc: string;
result?: T;
error?: {
code: number;
message: string;
data?: string;
};
id: number;
}