wulf-pulse/migrations/030_create_workflow_engine_tables.sql

349 lines
30 KiB
SQL

-- Workflow Engine Tables
-- Supports robotic-first ticket triage with configurable rules and AI fallback
-- Classification rules: DB-driven keyword→classification mappings
-- Replaces hardcoded keyword lists from n8n AI prompts
CREATE TABLE IF NOT EXISTS classification_rules (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description TEXT,
rule_type VARCHAR(50) NOT NULL, -- 'branch_routing', 'ticket_type', 'issue_classification', 'priority', 'queue_routing'
sort_order INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT true,
-- Pattern matching
match_field VARCHAR(50) NOT NULL, -- 'title', 'description', 'title_or_description', 'ticket_category', 'policy_name', 'device_name', 'creator_resource_id', 'priority', 'ticket_type'
match_operator VARCHAR(50) NOT NULL, -- 'contains', 'starts_with', 'regex', 'equals', 'in', 'not_in'
match_value JSONB NOT NULL, -- string, string[], or regex pattern
match_case_sensitive BOOLEAN DEFAULT false,
-- Result: what to set when matched
result_field VARCHAR(50) NOT NULL, -- 'branch', 'ticket_type', 'issue_type', 'sub_issue_type', 'priority', 'queue_id', 'ticket_category'
result_value JSONB NOT NULL,
-- Optional secondary result (e.g., issue_type AND sub_issue_type together)
result_field_2 VARCHAR(50),
result_value_2 JSONB,
confidence VARCHAR(20) DEFAULT 'high', -- 'high', 'medium', 'low'
stop_on_match BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Workflow rules: configurable exclusion/inclusion filters
CREATE TABLE IF NOT EXISTS workflow_rules (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description TEXT,
is_active BOOLEAN DEFAULT true,
sort_order INTEGER DEFAULT 0,
trigger_event VARCHAR(50) NOT NULL, -- 'ticket.created', 'ticket.updated'
trigger_entity VARCHAR(50) DEFAULT 'ticket',
stop_processing BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Rule conditions (AND within group, OR between groups)
CREATE TABLE IF NOT EXISTS workflow_conditions (
id SERIAL PRIMARY KEY,
rule_id INTEGER NOT NULL REFERENCES workflow_rules(id) ON DELETE CASCADE,
condition_group INTEGER DEFAULT 0,
field VARCHAR(100) NOT NULL,
operator VARCHAR(50) NOT NULL,
value JSONB NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- Rule actions
CREATE TABLE IF NOT EXISTS workflow_actions (
id SERIAL PRIMARY KEY,
rule_id INTEGER NOT NULL REFERENCES workflow_rules(id) ON DELETE CASCADE,
sort_order INTEGER DEFAULT 0,
action_type VARCHAR(50) NOT NULL, -- 'set_field', 'classify', 'ai_enhance', 'create_note', 'update_autotask', 'delay', 'skip'
config JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMP DEFAULT NOW()
);
-- AI prompt templates (for cases where AI is needed)
CREATE TABLE IF NOT EXISTS ai_prompt_templates (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL,
purpose VARCHAR(50) NOT NULL, -- 'title_cleanup', 'description_rewrite', 'ambiguous_classification', 'troubleshooting_steps', 'noc_format', 'soc_analysis'
system_prompt TEXT NOT NULL,
user_prompt_template TEXT NOT NULL,
provider VARCHAR(50) DEFAULT 'openai',
model VARCHAR(100) DEFAULT 'gpt-4o',
temperature DECIMAL(3,2) DEFAULT 0.3,
max_tokens INTEGER DEFAULT 4000,
is_active BOOLEAN DEFAULT true,
version INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Workflow execution log
CREATE TABLE IF NOT EXISTS workflow_executions (
id SERIAL PRIMARY KEY,
trigger_event VARCHAR(50) NOT NULL,
entity_type VARCHAR(50) NOT NULL,
entity_id BIGINT NOT NULL,
ticket_number VARCHAR(50),
status VARCHAR(20) NOT NULL DEFAULT 'pending',
classification_method VARCHAR(20), -- 'robotic', 'ai', 'hybrid'
branch VARCHAR(20), -- 'service_desk', 'noc', 'soc'
started_at TIMESTAMP DEFAULT NOW(),
completed_at TIMESTAMP,
duration_ms INTEGER,
error_message TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
-- Execution step details
CREATE TABLE IF NOT EXISTS workflow_execution_steps (
id SERIAL PRIMARY KEY,
execution_id INTEGER NOT NULL REFERENCES workflow_executions(id) ON DELETE CASCADE,
step_name VARCHAR(100) NOT NULL,
step_order INTEGER NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
method VARCHAR(20), -- 'robotic', 'ai', 'skipped'
input_data JSONB,
output_data JSONB,
field_changes JSONB,
classification_rule_id INTEGER,
confidence VARCHAR(20),
ai_request JSONB,
ai_response TEXT,
attempt_number INTEGER DEFAULT 1,
error_message TEXT,
duration_ms INTEGER,
started_at TIMESTAMP,
completed_at TIMESTAMP
);
-- Workflow settings
CREATE TABLE IF NOT EXISTS workflow_settings (
key VARCHAR(100) PRIMARY KEY,
value JSONB NOT NULL,
description TEXT,
updated_at TIMESTAMP DEFAULT NOW()
);
INSERT INTO workflow_settings (key, value, description) VALUES
('workflow_engine_enabled', 'false', 'Master enable/disable for workflow engine'),
('default_ai_provider', '"openai"', 'Default AI provider (openai or anthropic)'),
('openai_api_key', '""', 'OpenAI API key'),
('openai_model', '"gpt-4o"', 'Default OpenAI model'),
('anthropic_api_key', '""', 'Anthropic API key'),
('anthropic_model', '"claude-sonnet-4-20250514"', 'Default Anthropic model'),
('ai_for_title_cleanup', 'true', 'Use AI to clean up messy ticket titles'),
('ai_for_description_rewrite', 'true', 'Use AI to restructure unstructured descriptions'),
('ai_for_ambiguous_classification', 'true', 'Use AI when robotic classifier has no match'),
('ai_for_troubleshooting', 'true', 'Generate AI troubleshooting steps for incidents'),
('autotask_update_delay_ms', '30000', 'Delay before writing back to Autotask (ms)'),
('max_ai_retries', '2', 'Max AI retry attempts on validation failure'),
('classification_confidence_threshold', '"medium"', 'Min confidence to skip AI (high, medium, low)'),
('log_retention_days', '90', 'Days to retain execution logs')
ON CONFLICT (key) DO NOTHING;
-- Indexes
CREATE INDEX idx_classification_rules_type ON classification_rules(rule_type, is_active, sort_order);
CREATE INDEX idx_workflow_rules_active ON workflow_rules(is_active, sort_order);
CREATE INDEX idx_workflow_conditions_rule ON workflow_conditions(rule_id);
CREATE INDEX idx_workflow_actions_rule ON workflow_actions(rule_id, sort_order);
CREATE INDEX idx_workflow_executions_entity ON workflow_executions(entity_type, entity_id);
CREATE INDEX idx_workflow_executions_status ON workflow_executions(status, created_at);
CREATE INDEX idx_workflow_executions_created ON workflow_executions(created_at);
CREATE INDEX idx_workflow_execution_steps_exec ON workflow_execution_steps(execution_id, step_order);
-- ============================================================================
-- SEED: Default workflow filter rules (port from n8n IF nodes)
-- ============================================================================
-- Rule 1: Exclude specific API users
INSERT INTO workflow_rules (name, description, is_active, sort_order, trigger_event, stop_processing) VALUES
('Exclude API Users', 'Skip tickets created by automation API users', true, 10, 'ticket.created', true);
INSERT INTO workflow_conditions (rule_id, condition_group, field, operator, value) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Exclude API Users'), 0, 'person_id', 'in', '[30861575]');
INSERT INTO workflow_actions (rule_id, sort_order, action_type, config) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Exclude API Users'), 0, 'skip', '{"reason": "API user exclusion"}');
-- Rule 2: Exclude specific technician creators
INSERT INTO workflow_rules (name, description, is_active, sort_order, trigger_event, stop_processing) VALUES
('Exclude Technician Creators', 'Skip tickets created by specific technicians', true, 20, 'ticket.created', true);
INSERT INTO workflow_conditions (rule_id, condition_group, field, operator, value) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Exclude Technician Creators'), 0, 'creator_resource_id', 'in', '[30861471]');
INSERT INTO workflow_actions (rule_id, sort_order, action_type, config) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Exclude Technician Creators'), 0, 'skip', '{"reason": "Technician creator exclusion"}');
-- Rule 3: Category filter - only process triageable categories
INSERT INTO workflow_rules (name, description, is_active, sort_order, trigger_event, stop_processing) VALUES
('Category Filter', 'Only process tickets in triageable categories (NOC, Service Desk, Triage, SOC)', true, 30, 'ticket.created', true);
INSERT INTO workflow_conditions (rule_id, condition_group, field, operator, value) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Category Filter'), 0, 'ticket_category', 'not_in', '[2, 3, 159, 161]');
INSERT INTO workflow_actions (rule_id, sort_order, action_type, config) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Category Filter'), 0, 'skip', '{"reason": "Ticket category not eligible for triage"}');
-- Rule 4: Company exclusions
INSERT INTO workflow_rules (name, description, is_active, sort_order, trigger_event, stop_processing) VALUES
('Company Exclusions', 'Skip tickets from excluded companies (tools-only clients)', true, 40, 'ticket.created', true);
INSERT INTO workflow_conditions (rule_id, condition_group, field, operator, value) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Company Exclusions'), 0, 'company_id', 'in', '[29861409, 29783545, 29861361, 29702433]');
INSERT INTO workflow_actions (rule_id, sort_order, action_type, config) VALUES
((SELECT id FROM workflow_rules WHERE name = 'Company Exclusions'), 0, 'skip', '{"reason": "Company excluded from triage"}');
-- ============================================================================
-- SEED: Branch routing classification rules
-- ============================================================================
-- NOC branch routing
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, confidence) VALUES
('Datto RMM alerts (email)', 'branch_routing', 10, 'description', 'contains', '["alerts@rmm.datto.com", "monitor alert", "alert was triggered", "aem alert"]', 'branch', '"noc"', 'high'),
('Datto RMM alerts (title)', 'branch_routing', 20, 'title', 'contains', '["datto", "rmm"]', 'branch', '"noc"', 'high'),
('Zoom monitoring alerts', 'branch_routing', 30, 'title_or_description', 'contains', '["zoom room", "zoom monitoring", "video device disconnected", "audio device disconnected", "controller (ipad)"]', 'branch', '"noc"', 'high');
-- SOC branch routing
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, confidence) VALUES
('Phishing reports', 'branch_routing', 40, 'title', 'contains', '["phishing:", "[phish alert]"]', 'branch', '"soc"', 'high'),
('Phishing indicators (headers)', 'branch_routing', 45, 'description', 'contains', '["received-spf: fail", "dkim=fail", "dmarc=fail", "# questionable urls detected"]', 'branch', '"soc"', 'high'),
('Blumira security alerts', 'branch_routing', 50, 'title_or_description', 'contains', '["from blumira", "blumira@messages.blumira.com", "suspect |", "critical |", "informational |"]', 'branch', '"soc"', 'high'),
('Security threat keywords', 'branch_routing', 60, 'title_or_description', 'contains', '["malware detected", "ransomware", "threat detected", "suspicious activity", "security breach", "unauthorized access", "compromised account", "attack detected", "exploit", "huntress detection", "duo security alert", "brute force", "stolen credentials", "credential harvesting", "account takeover", "indicator of compromise", "security alert", "security event", "malicious link", "suspicious attachment", "incident response"]', 'branch', '"soc"', 'high');
-- Default: service_desk (handled by code when no branch_routing rule matches)
-- ============================================================================
-- SEED: Ticket type classification rules
-- ============================================================================
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, confidence) VALUES
('Incident - was working language', 'ticket_type', 10, 'title_or_description', 'contains', '["was working", "stopped working", "quit working", "suddenly stopped", "used to work", "previously worked", "it broke"]', 'ticket_type', '2', 'high'),
('Incident - error/failure language', 'ticket_type', 20, 'title_or_description', 'contains', '["not working", "won''t open", "getting error", "unable to", "failed", "can''t access", "can''t send", "can''t receive", "disconnected", "crashes", "login failure", "access denied"]', 'ticket_type', '2', 'high'),
('Service Request - request language', 'ticket_type', 30, 'title_or_description', 'contains', '["how do i", "please set up", "please install", "can i have", "need account", "new user", "new hire", "schedule", "consultation", "review my", "following up", "shipment"]', 'ticket_type', '1', 'high'),
('Service Request - setup language', 'ticket_type', 40, 'title_or_description', 'contains', '["set up", "configure", "create new", "add new", "install", "deploy", "onboarding"]', 'ticket_type', '1', 'medium');
-- ============================================================================
-- SEED: Issue classification rules (keyword → issueType + subIssueType)
-- ============================================================================
-- Category overrides (highest priority)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('New User (category 127)', 'issue_classification', 1, 'ticket_category', 'equals', '127', 'issue_type', '55', 'sub_issue_type', '522', 'high'),
('User Separation (category 128)', 'issue_classification', 2, 'ticket_category', 'equals', '128', 'issue_type', '55', 'sub_issue_type', '526', 'high');
-- Email (issueType 34) - highest keyword priority per n8n rules
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Email - can''t send', 'issue_classification', 10, 'title_or_description', 'contains', '["can''t send email", "unable to send email", "email not sending"]', 'issue_type', '34', 'sub_issue_type', '312', 'high'),
('Email - can''t receive', 'issue_classification', 11, 'title_or_description', 'contains', '["can''t receive email", "not receiving email", "email not coming", "can''t access email", "unable to access email", "can''t get into email"]', 'issue_type', '34', 'sub_issue_type', '313', 'high'),
('Email - spam/junk', 'issue_classification', 12, 'title_or_description', 'contains', '["spam email", "junk email", "junk mail", "too many emails"]', 'issue_type', '34', 'sub_issue_type', '314', 'high'),
('Email - phishing', 'issue_classification', 13, 'title_or_description', 'contains', '["phishing email", "phishing attempt", "suspicious email"]', 'issue_type', '34', 'sub_issue_type', '316', 'high'),
('Email - Outlook', 'issue_classification', 14, 'title_or_description', 'contains', '["outlook crash", "outlook not opening", "outlook won''t open", "outlook freezing"]', 'issue_type', '34', 'sub_issue_type', '451', 'high'),
('Email - signatures', 'issue_classification', 15, 'title_or_description', 'contains', '["email signature"]', 'issue_type', '34', 'sub_issue_type', '568', 'high'),
('Email - Mimecast release', 'issue_classification', 16, 'title_or_description', 'contains', '["mimecast release", "release email"]', 'issue_type', '34', 'sub_issue_type', '706', 'high'),
('Email - Mimecast allow', 'issue_classification', 17, 'title_or_description', 'contains', '["mimecast allow", "allow sender", "whitelist sender"]', 'issue_type', '34', 'sub_issue_type', '707', 'high'),
('Email - Mimecast block', 'issue_classification', 18, 'title_or_description', 'contains', '["mimecast block", "block sender", "blacklist sender"]', 'issue_type', '34', 'sub_issue_type', '832', 'high'),
('Email - distribution group', 'issue_classification', 19, 'title_or_description', 'contains', '["distribution group", "distribution list", "email group"]', 'issue_type', '34', 'sub_issue_type', '771', 'high'),
('Email - shared mailbox', 'issue_classification', 20, 'title_or_description', 'contains', '["shared mailbox", "shared email"]', 'issue_type', '34', 'sub_issue_type', '814', 'high'),
('Email - forwarding', 'issue_classification', 21, 'title_or_description', 'contains', '["email forward", "forward setup", "forwarding"]', 'issue_type', '34', 'sub_issue_type', '862', 'high'),
('Email - out of office', 'issue_classification', 22, 'title_or_description', 'contains', '["out of office", "auto-reply", "vacation reply"]', 'issue_type', '34', 'sub_issue_type', '839', 'high'),
('Email - mailbox full', 'issue_classification', 23, 'title_or_description', 'contains', '["mailbox full", "mailbox size", "mailbox quota"]', 'issue_type', '34', 'sub_issue_type', '838', 'high'),
('Email - generic', 'issue_classification', 29, 'title_or_description', 'contains', '["email", "e-mail", "inbox", "mailbox"]', 'issue_type', '34', 'sub_issue_type', '317', 'medium');
-- Active Directory & Accounts (issueType 76)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('AD - password reset', 'issue_classification', 30, 'title_or_description', 'contains', '["password reset", "reset password", "forgot password", "password expired"]', 'issue_type', '76', 'sub_issue_type', '759', 'high'),
('AD - account lockout', 'issue_classification', 31, 'title_or_description', 'contains', '["account locked", "locked out", "account lockout"]', 'issue_type', '76', 'sub_issue_type', '795', 'high'),
('AD - DUO lockout', 'issue_classification', 32, 'title_or_description', 'contains', '["duo locked", "duo lockout", "mfa locked"]', 'issue_type', '76', 'sub_issue_type', '758', 'high'),
('AD - file permissions', 'issue_classification', 33, 'title_or_description', 'contains', '["file permission", "folder permission", "access to folder", "shared drive access"]', 'issue_type', '76', 'sub_issue_type', '760', 'high'),
('AD - drive mapping', 'issue_classification', 34, 'title_or_description', 'contains', '["drive mapping", "mapped drive", "network drive"]', 'issue_type', '76', 'sub_issue_type', '761', 'high'),
('AD - admin rights', 'issue_classification', 35, 'title_or_description', 'contains', '["admin rights", "local admin", "administrator access"]', 'issue_type', '76', 'sub_issue_type', '828', 'high'),
('AD - 365 license', 'issue_classification', 36, 'title_or_description', 'contains', '["365 license", "office license", "microsoft license"]', 'issue_type', '76', 'sub_issue_type', '829', 'high');
-- Peripheral Connectivity (issueType 51)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Peripheral - printer/printing', 'issue_classification', 40, 'title_or_description', 'contains', '["printer", "printing", "print job", "can''t print"]', 'issue_type', '51', 'sub_issue_type', '377', 'high'),
('Peripheral - scanner', 'issue_classification', 41, 'title_or_description', 'contains', '["scanner", "scanning", "can''t scan"]', 'issue_type', '51', 'sub_issue_type', '550', 'high'),
('Peripheral - scan to email', 'issue_classification', 42, 'title_or_description', 'contains', '["scan to email", "scan-to-email"]', 'issue_type', '51', 'sub_issue_type', '551', 'high'),
('Peripheral - docking station', 'issue_classification', 43, 'title_or_description', 'contains', '["docking station", "dock", "undocking"]', 'issue_type', '51', 'sub_issue_type', '769', 'high'),
('Peripheral - display/monitor', 'issue_classification', 44, 'title_or_description', 'contains', '["monitor", "display", "screen", "external display"]', 'issue_type', '51', 'sub_issue_type', '745', 'medium'),
('Peripheral - audio', 'issue_classification', 45, 'title_or_description', 'contains', '["audio", "speakers", "headset", "microphone", "sound"]', 'issue_type', '51', 'sub_issue_type', '804', 'medium'),
('Peripheral - fax', 'issue_classification', 46, 'title_or_description', 'contains', '["fax", "faxing"]', 'issue_type', '51', 'sub_issue_type', '847', 'high');
-- Software (issueType 46)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Software - MS Teams', 'issue_classification', 50, 'title_or_description', 'contains', '["microsoft teams", "ms teams", "teams meeting", "teams call"]', 'issue_type', '46', 'sub_issue_type', '798', 'high'),
('Software - SharePoint', 'issue_classification', 51, 'title_or_description', 'contains', '["sharepoint"]', 'issue_type', '46', 'sub_issue_type', '850', 'high'),
('Software - OneDrive', 'issue_classification', 52, 'title_or_description', 'contains', '["onedrive", "one drive"]', 'issue_type', '46', 'sub_issue_type', '345', 'high'),
('Software - Excel', 'issue_classification', 53, 'title_or_description', 'contains', '["excel", "spreadsheet"]', 'issue_type', '46', 'sub_issue_type', '842', 'high'),
('Software - Word', 'issue_classification', 54, 'title_or_description', 'contains', '["microsoft word", "ms word"]', 'issue_type', '46', 'sub_issue_type', '799', 'high'),
('Software - PowerPoint', 'issue_classification', 55, 'title_or_description', 'contains', '["powerpoint", "power point"]', 'issue_type', '46', 'sub_issue_type', '800', 'high'),
('Software - MS Project', 'issue_classification', 56, 'title_or_description', 'contains', '["ms project", "microsoft project"]', 'issue_type', '46', 'sub_issue_type', '836', 'high'),
('Software - Adobe', 'issue_classification', 57, 'title_or_description', 'contains', '["adobe", "acrobat", "photoshop", "illustrator"]', 'issue_type', '46', 'sub_issue_type', '541', 'high'),
('Software - Chrome', 'issue_classification', 58, 'title_or_description', 'contains', '["google chrome", "chrome browser"]', 'issue_type', '46', 'sub_issue_type', '542', 'high'),
('Software - QuickBooks', 'issue_classification', 59, 'title_or_description', 'contains', '["quickbooks", "quick books"]', 'issue_type', '46', 'sub_issue_type', '583', 'high'),
('Software - Bitwarden', 'issue_classification', 60, 'title_or_description', 'contains', '["bitwarden"]', 'issue_type', '46', 'sub_issue_type', '851', 'high'),
('Software - MS Office generic', 'issue_classification', 69, 'title_or_description', 'contains', '["microsoft sway", "onenote", "one note", "visio", "publisher", "ms access", "microsoft forms", "planner"]', 'issue_type', '46', 'sub_issue_type', '332', 'high');
-- Networking (issueType 25)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Network - WiFi', 'issue_classification', 70, 'title_or_description', 'contains', '["wifi", "wi-fi", "wireless", "wireless network"]', 'issue_type', '25', 'sub_issue_type', '548', 'high'),
('Network - VPN', 'issue_classification', 71, 'title_or_description', 'contains', '["vpn", "site to site"]', 'issue_type', '25', 'sub_issue_type', '358', 'medium'),
('Network - internet down', 'issue_classification', 72, 'title_or_description', 'contains', '["internet down", "internet outage", "no internet", "internet not working"]', 'issue_type', '25', 'sub_issue_type', '260', 'high'),
('Network - firewall', 'issue_classification', 73, 'title_or_description', 'contains', '["firewall"]', 'issue_type', '25', 'sub_issue_type', '244', 'high');
-- Hardware (issueType 31)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Hardware - slow PC', 'issue_classification', 80, 'title_or_description', 'contains', '["slow computer", "slow pc", "computer slow", "pc slow", "running slow"]', 'issue_type', '31', 'sub_issue_type', '560', 'high'),
('Hardware - laptop', 'issue_classification', 81, 'title_or_description', 'contains', '["laptop issue", "laptop problem", "laptop broken"]', 'issue_type', '31', 'sub_issue_type', '561', 'medium'),
('Hardware - desktop', 'issue_classification', 82, 'title_or_description', 'contains', '["desktop issue", "desktop problem", "desktop broken", "computer won''t turn on"]', 'issue_type', '31', 'sub_issue_type', '248', 'medium');
-- Remote Access (issueType 63)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Remote Access - VPN/Sophos', 'issue_classification', 90, 'title_or_description', 'contains', '["sophos vpn", "sophos connect"]', 'issue_type', '63', 'sub_issue_type', '494', 'high'),
('Remote Access - RDP', 'issue_classification', 91, 'title_or_description', 'contains', '["rdp", "remote desktop", "rds gateway"]', 'issue_type', '63', 'sub_issue_type', '495', 'high'),
('Remote Access - generic', 'issue_classification', 99, 'title_or_description', 'contains', '["remote access", "work from home", "remote work"]', 'issue_type', '63', 'sub_issue_type', '770', 'medium');
-- Collaboration (issueType 42) - for phone/video specific
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Collaboration - Nextiva', 'issue_classification', 100, 'title_or_description', 'contains', '["nextiva", "phone system"]', 'issue_type', '42', 'sub_issue_type', '563', 'high'),
('Collaboration - Teams Room', 'issue_classification', 101, 'title_or_description', 'contains', '["teams room", "conference room teams"]', 'issue_type', '42', 'sub_issue_type', '810', 'high');
-- Security (issueType 59)
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, result_field_2, result_value_2, confidence) VALUES
('Security - phishing', 'issue_classification', 110, 'title_or_description', 'contains', '["phishing", "phish"]', 'issue_type', '59', 'sub_issue_type', '910', 'high'),
('Security - malware', 'issue_classification', 111, 'title_or_description', 'contains', '["malware", "virus", "trojan"]', 'issue_type', '59', 'sub_issue_type', '554', 'high'),
('Security - ransomware', 'issue_classification', 112, 'title_or_description', 'contains', '["ransomware"]', 'issue_type', '59', 'sub_issue_type', '911', 'high'),
('Security - compromised account', 'issue_classification', 113, 'title_or_description', 'contains', '["compromised account", "account compromised", "account hacked"]', 'issue_type', '59', 'sub_issue_type', '552', 'high'),
('Security - 2FA/MFA setup', 'issue_classification', 114, 'title_or_description', 'contains', '["2fa setup", "mfa setup", "two factor", "multi factor"]', 'issue_type', '59', 'sub_issue_type', '860', 'high'),
('Security - DUO enrollment', 'issue_classification', 115, 'title_or_description', 'contains', '["duo enrollment", "duo setup", "enroll duo"]', 'issue_type', '59', 'sub_issue_type', '813', 'high');
-- ============================================================================
-- SEED: Priority classification rules
-- ============================================================================
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, confidence) VALUES
-- Category-based overrides (highest priority)
('Priority - User Separation = Critical', 'priority', 1, 'ticket_category', 'equals', '128', 'priority', '4', 'high'),
('Priority - New User = Minor Service', 'priority', 2, 'ticket_category', 'equals', '127', 'priority', '8', 'high'),
-- Security events
('Priority - Security keywords = Security Event', 'priority', 10, 'title_or_description', 'contains', '["security breach", "ransomware", "malware detected", "compromised", "attack"]', 'priority', '7', 'high'),
-- Impact-based
('Priority - Multiple users affected = Critical', 'priority', 20, 'title_or_description', 'contains', '["multiple users", "everyone", "all users", "company-wide", "entire office"]', 'priority', '4', 'high'),
-- Simple service requests
('Priority - How-to/consultation = Minor Service', 'priority', 30, 'title_or_description', 'contains', '["how do i", "how to", "schedule meeting", "consultation", "question about", "following up"]', 'priority', '8', 'medium');
-- ============================================================================
-- SEED: Queue routing classification rules
-- ============================================================================
INSERT INTO classification_rules (name, rule_type, sort_order, match_field, match_operator, match_value, result_field, result_value, confidence) VALUES
-- Critical priority override
('Queue - Critical = Level 2', 'queue_routing', 1, 'priority', 'equals', '4', 'queue_id', '29682969', 'high'),
-- Device name patterns (workstation)
('Queue - DT devices = Level 1', 'queue_routing', 10, 'title_or_description', 'regex', '"\\bDT-?\\d{2,}"', 'queue_id', '29682833', 'high'),
('Queue - LT devices = Level 1', 'queue_routing', 11, 'title_or_description', 'regex', '"\\bLT-?\\d{2,}"', 'queue_id', '29682833', 'high'),
('Queue - SP devices = Level 1', 'queue_routing', 12, 'title_or_description', 'regex', '"\\bSP-?\\d{2,}"', 'queue_id', '29682833', 'high'),
-- Policy name patterns
('Queue - Workstation policy = Level 1', 'queue_routing', 20, 'title_or_description', 'contains', '["windows workstation", "workstations"]', 'queue_id', '29682833', 'high'),
('Queue - Server policy = Level 2', 'queue_routing', 21, 'title_or_description', 'contains', '["windows server", "hypervisor", "esxi", "hyper-v"]', 'queue_id', '29682969', 'high');