-- Veeam RPO shadow-mode tables for the parallel validation period. -- The RPO service runs without creating real Autotask tickets; all actions -- are logged here so they can be compared against Datto RMM ticket output. -- Shadow log: one row per check cycle per job for every action the live service -- *would* have taken (would_create, would_escalate, would_resolve, would_skip_too_old). -- Offline suppressions continue to go to veeam_rpo_offline_log (migration 066). CREATE TABLE IF NOT EXISTS veeam_rpo_shadow_log ( id SERIAL PRIMARY KEY, job_instance_uid VARCHAR(255) NOT NULL, job_name TEXT NOT NULL, org_name TEXT NOT NULL, rmm_hostname TEXT, rmm_site_name TEXT, action TEXT NOT NULL, -- 'would_create' | 'would_escalate' | 'would_resolve' | 'would_skip_too_old' priority_level TEXT, -- medium | high | critical (null for would_resolve) hours_overdue INTEGER, -- null for would_resolve failure_category TEXT, checked_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_shadow_log_job ON veeam_rpo_shadow_log(job_instance_uid); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_shadow_log_checked ON veeam_rpo_shadow_log(checked_at); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_shadow_log_hostname ON veeam_rpo_shadow_log(rmm_hostname); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_shadow_log_action ON veeam_rpo_shadow_log(action); -- Shadow ticket state: mirrors veeam_rpo_tickets but without Autotask ticket IDs. -- Tracks open/resolved state so the shadow service can distinguish would_create -- from would_escalate across check cycles. CREATE TABLE IF NOT EXISTS veeam_rpo_shadow_tickets ( job_instance_uid VARCHAR(255) PRIMARY KEY, job_name TEXT NOT NULL, org_name TEXT NOT NULL, rmm_hostname TEXT, priority_level TEXT NOT NULL, hours_overdue INTEGER NOT NULL, failure_category TEXT, opened_at TIMESTAMPTZ DEFAULT NOW(), resolved_at TIMESTAMPTZ, last_checked_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_shadow_tickets_open ON veeam_rpo_shadow_tickets(resolved_at) WHERE resolved_at IS NULL; CREATE INDEX IF NOT EXISTS idx_veeam_rpo_shadow_tickets_hostname ON veeam_rpo_shadow_tickets(rmm_hostname); -- Datto RMM backup tickets captured from Autotask webhooks. -- Populated whenever a ticket.created event arrives that matches the Datto -- backup monitor signature (issue_type=38, Veeam-related title, not [Veeam RPO]). -- Updated on ticket.updated events to track resolution. CREATE TABLE IF NOT EXISTS veeam_rpo_datto_tickets ( id SERIAL PRIMARY KEY, at_ticket_id BIGINT UNIQUE NOT NULL, at_ticket_number TEXT, title TEXT NOT NULL, company_id BIGINT, company_name TEXT, extracted_hostname TEXT, -- parsed from title (e.g. "DT061" from "DT061 - Veeam...") issue_type INTEGER, sub_issue_type INTEGER, status INTEGER, priority INTEGER, ticket_created_at TIMESTAMPTZ, ticket_resolved_at TIMESTAMPTZ, captured_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_datto_tickets_company ON veeam_rpo_datto_tickets(company_id); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_datto_tickets_hostname ON veeam_rpo_datto_tickets(extracted_hostname); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_datto_tickets_created ON veeam_rpo_datto_tickets(ticket_created_at); CREATE INDEX IF NOT EXISTS idx_veeam_rpo_datto_tickets_resolved ON veeam_rpo_datto_tickets(ticket_resolved_at) WHERE ticket_resolved_at IS NULL;