-- Migration 143: Repair Mission Control schema on partially-initialized databases -- Safe to run multiple times. CREATE TABLE IF NOT EXISTS mission_events ( id BIGSERIAL PRIMARY KEY, event_type VARCHAR(64) NOT NULL, severity VARCHAR(16) NOT NULL DEFAULT 'info', title VARCHAR(255) NOT NULL, source VARCHAR(64), customer_name VARCHAR(255), payload JSONB NOT NULL DEFAULT '{}'::jsonb, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); ALTER TABLE mission_events ADD COLUMN IF NOT EXISTS event_type VARCHAR(64); ALTER TABLE mission_events ADD COLUMN IF NOT EXISTS severity VARCHAR(16) NOT NULL DEFAULT 'info'; ALTER TABLE mission_events ADD COLUMN IF NOT EXISTS title VARCHAR(255); ALTER TABLE mission_events ADD COLUMN IF NOT EXISTS source VARCHAR(64); ALTER TABLE mission_events ADD COLUMN IF NOT EXISTS customer_name VARCHAR(255); ALTER TABLE mission_events ADD COLUMN IF NOT EXISTS payload JSONB NOT NULL DEFAULT '{}'::jsonb; ALTER TABLE mission_events ADD COLUMN IF NOT EXISTS created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; CREATE INDEX IF NOT EXISTS idx_mission_events_created_at ON mission_events(created_at DESC); CREATE INDEX IF NOT EXISTS idx_mission_events_event_type ON mission_events(event_type); CREATE TABLE IF NOT EXISTS mission_call_state ( call_id VARCHAR(128) PRIMARY KEY, queue_name VARCHAR(128), caller_number VARCHAR(64), contact_name VARCHAR(255), company_name VARCHAR(255), customer_tag VARCHAR(64), state VARCHAR(32) NOT NULL, started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, answered_at TIMESTAMP, ended_at TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, last_payload JSONB NOT NULL DEFAULT '{}'::jsonb ); ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS call_id VARCHAR(128); ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS queue_name VARCHAR(128); ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS caller_number VARCHAR(64); ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS contact_name VARCHAR(255); ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS company_name VARCHAR(255); ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS customer_tag VARCHAR(64); ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS state VARCHAR(32) NOT NULL DEFAULT 'ringing'; ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS answered_at TIMESTAMP; ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS ended_at TIMESTAMP; ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE mission_call_state ADD COLUMN IF NOT EXISTS last_payload JSONB NOT NULL DEFAULT '{}'::jsonb; DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'mission_call_state_pkey' AND conrelid = 'mission_call_state'::regclass ) THEN ALTER TABLE mission_call_state ADD PRIMARY KEY (call_id); END IF; END $$; CREATE INDEX IF NOT EXISTS idx_mission_call_state_state ON mission_call_state(state); CREATE INDEX IF NOT EXISTS idx_mission_call_state_updated_at ON mission_call_state(updated_at DESC); CREATE TABLE IF NOT EXISTS mission_uptime_alerts ( alert_key VARCHAR(255) PRIMARY KEY, service_name VARCHAR(255) NOT NULL, customer_name VARCHAR(255), status VARCHAR(32) NOT NULL, is_active BOOLEAN NOT NULL DEFAULT FALSE, started_at TIMESTAMP, resolved_at TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, raw_payload JSONB NOT NULL DEFAULT '{}'::jsonb, normalized_payload JSONB NOT NULL DEFAULT '{}'::jsonb ); ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS alert_key VARCHAR(255); ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS service_name VARCHAR(255); ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS customer_name VARCHAR(255); ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS status VARCHAR(32); ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS is_active BOOLEAN NOT NULL DEFAULT FALSE; ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS started_at TIMESTAMP; ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS resolved_at TIMESTAMP; ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS raw_payload JSONB NOT NULL DEFAULT '{}'::jsonb; ALTER TABLE mission_uptime_alerts ADD COLUMN IF NOT EXISTS normalized_payload JSONB NOT NULL DEFAULT '{}'::jsonb; DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'mission_uptime_alerts_pkey' AND conrelid = 'mission_uptime_alerts'::regclass ) THEN ALTER TABLE mission_uptime_alerts ADD PRIMARY KEY (alert_key); END IF; END $$; CREATE INDEX IF NOT EXISTS idx_mission_uptime_active ON mission_uptime_alerts(is_active, updated_at DESC); INSERT INTO settings (key, value, category, description, value_type, is_public) VALUES ('mission_call_ring_timeout_seconds', '180', 'mission', 'Seconds before stale ringing calls auto-expire', 'integer', true) ON CONFLICT (key) DO NOTHING;