-- WHP canonical database schema.
-- Generated by applying every versioned migration to a fresh MariaDB.
-- DO NOT manually edit individual statements unless you ALSO add a
-- corresponding migration under sql/migrations/staging/.
-- Regenerate: bash scripts/regenerate-canonical-schema.sh

USE whp;
ALTER DATABASE whp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

/*M!999999\- enable the sandbox mode */ 

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
SET @saved_cs_client     = @@character_set_client;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `active_delegated_users` AS SELECT
 1 AS `id`,
  1 AS `username`,
  1 AS `parent_username`,
  1 AS `display_name`,
  1 AS `email`,
  1 AS `can_manage_domains`,
  1 AS `can_manage_sites`,
  1 AS `can_manage_databases`,
  1 AS `can_manage_email`,
  1 AS `can_manage_files`,
  1 AS `can_manage_backups`,
  1 AS `can_view_terminal`,
  1 AS `can_manage_wordpress`,
  1 AS `allowed_domains`,
  1 AS `max_domains`,
  1 AS `max_databases`,
  1 AS `max_email_accounts`,
  1 AS `last_login`,
  1 AS `created_at`,
  1 AS `created_by`,
  1 AS `parent_max_domains`,
  1 AS `parent_max_email_accounts` */;
SET character_set_client = @saved_cs_client;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ai_monitor_email_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `subscription_id` int(11) NOT NULL,
  `issue_id` int(11) DEFAULT NULL COMMENT 'NULL for review-complete emails',
  `review_id` int(11) DEFAULT NULL COMMENT 'NULL for issue notification emails',
  `recipient_email` varchar(255) NOT NULL,
  `subject` varchar(255) NOT NULL,
  `body_html` text NOT NULL,
  `body_text` text NOT NULL,
  `status` enum('queued','sending','sent','failed') NOT NULL DEFAULT 'queued',
  `attempts` int(11) NOT NULL DEFAULT 0,
  `max_attempts` int(11) NOT NULL DEFAULT 3,
  `last_attempt_at` timestamp NULL DEFAULT NULL,
  `sent_at` timestamp NULL DEFAULT NULL,
  `error_message` text DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_status` (`status`),
  KEY `idx_created_at` (`created_at`),
  KEY `idx_subscription_batch` (`subscription_id`,`status`,`created_at`),
  CONSTRAINT `ai_monitor_email_queue_ibfk_1` FOREIGN KEY (`subscription_id`) REFERENCES `ai_monitor_subscriptions` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ai_monitor_ignore_hits` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `rule_id` int(10) unsigned NOT NULL,
  `site_id` int(11) DEFAULT NULL,
  `username` varchar(32) DEFAULT NULL,
  `matched_category` varchar(50) DEFAULT NULL,
  `matched_title` varchar(255) DEFAULT NULL,
  `matched_signature` varchar(64) DEFAULT NULL,
  `hit_at` timestamp NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_rule_time` (`rule_id`,`hit_at`),
  KEY `idx_user` (`username`),
  CONSTRAINT `fk_aimh_rule` FOREIGN KEY (`rule_id`) REFERENCES `ai_monitor_ignore_rules` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Per-hit audit trail for ai_monitor_ignore_rules. Drives the recent-hits drill-down in the admin UI.';
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ai_monitor_ignore_rules` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `scope` enum('global','user','site') NOT NULL,
  `username` varchar(32) DEFAULT NULL,
  `site_id` int(11) DEFAULT NULL,
  `match_category` varchar(50) DEFAULT NULL,
  `match_severity` varchar(20) DEFAULT NULL,
  `match_title_substr` varchar(255) DEFAULT NULL,
  `match_raw_regex` varchar(500) DEFAULT NULL,
  `reason` text NOT NULL,
  `enabled` tinyint(1) NOT NULL DEFAULT 1,
  `created_by` varchar(32) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `hit_count` int(10) unsigned NOT NULL DEFAULT 0,
  `last_hit_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_scope_enabled` (`scope`,`enabled`),
  KEY `idx_site` (`site_id`),
  KEY `idx_user` (`username`),
  CONSTRAINT `fk_aimr_site` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='AI Monitor ignore rules. match_* columns are AND-combined: every non-null match_* must match the finding for the rule to apply.';
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ai_monitor_issues` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `subscription_id` int(11) DEFAULT NULL,
  `site_id` int(11) DEFAULT NULL,
  `username` varchar(32) DEFAULT NULL,
  `container_name` varchar(100) DEFAULT NULL COMMENT 'Specific container e.g. domain.tld-01',
  `severity` enum('critical','warning','info') NOT NULL DEFAULT 'warning',
  `category` varchar(50) NOT NULL COMMENT 'oom, php_error, performance, security, resource_limit, crash',
  `subsystem` varchar(32) DEFAULT NULL,
  `source` varchar(32) NOT NULL DEFAULT 'logs',
  `sources` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`sources`)),
  `title` varchar(255) NOT NULL,
  `diagnosis` text NOT NULL,
  `recommendation` text NOT NULL,
  `raw_log_excerpt` text DEFAULT NULL COMMENT 'Sanitized log excerpt (server paths stripped)',
  `context_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`context_data`)),
  `signature` varchar(64) NOT NULL COMMENT 'SHA-256 hash for deduplication',
  `occurrence_count` int(11) NOT NULL DEFAULT 1,
  `email_sent` tinyint(1) NOT NULL DEFAULT 0,
  `email_sent_at` timestamp NULL DEFAULT NULL,
  `first_seen` timestamp NOT NULL DEFAULT current_timestamp(),
  `last_seen` timestamp NOT NULL DEFAULT current_timestamp(),
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `status` enum('open','fixed','ignored') NOT NULL DEFAULT 'open',
  `auto_resolved_at` datetime DEFAULT NULL,
  `status_changed_by` varchar(32) DEFAULT NULL,
  `status_changed_at` datetime DEFAULT NULL,
  `user_explanation` text DEFAULT NULL,
  `user_explanation_at` datetime DEFAULT NULL,
  `user_explanation_model` varchar(128) DEFAULT NULL,
  `evidence` text DEFAULT NULL,
  `evidence_observed_at` datetime DEFAULT NULL COMMENT 'Timestamp parsed from the log line that supports this issue. NULL when no parseable timestamp was present.',
  `auto_fix_command` varchar(500) DEFAULT NULL COMMENT 'AI-proposed wp-cli command for one-click remediation',
  `auto_fix_description` varchar(500) DEFAULT NULL COMMENT 'Human-readable description of what the auto-fix command does',
  `auto_fix_status` enum('none','available','running','applied','failed') NOT NULL DEFAULT 'none',
  `auto_fix_applied_at` datetime DEFAULT NULL,
  `auto_fix_applied_by` varchar(64) DEFAULT NULL,
  `auto_fix_output` text DEFAULT NULL COMMENT 'Captured stdout/stderr from the auto-fix execution (truncated)',
  PRIMARY KEY (`id`),
  KEY `idx_subscription_id` (`subscription_id`),
  KEY `idx_site_username` (`site_id`,`username`),
  KEY `idx_severity` (`severity`),
  KEY `idx_email_sent` (`email_sent`),
  KEY `idx_created_at` (`created_at`),
  KEY `idx_signature` (`signature`),
  KEY `idx_site_status` (`site_id`,`status`),
  KEY `idx_subsystem_status` (`subsystem`,`status`),
  KEY `idx_source` (`source`),
  CONSTRAINT `ai_monitor_issues_ibfk_1` FOREIGN KEY (`subscription_id`) REFERENCES `ai_monitor_subscriptions` (`id`) ON DELETE CASCADE,
  CONSTRAINT `ai_monitor_issues_ibfk_2` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ai_monitor_log_reviews` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `review_type` enum('log','traffic') NOT NULL DEFAULT 'log',
  `subscription_id` int(11) NOT NULL,
  `site_id` int(11) NOT NULL,
  `username` varchar(32) NOT NULL,
  `status` enum('pending','processing','completed','failed') NOT NULL DEFAULT 'pending',
  `request_type` enum('full','error_only','performance') NOT NULL DEFAULT 'full',
  `triggered_by` varchar(32) NOT NULL DEFAULT 'manual' COMMENT 'Source that queued this review: daily|initial|periodic|manual|traffic_request',
  `ai_model_used` varchar(50) DEFAULT NULL,
  `ai_tokens_used` int(11) NOT NULL DEFAULT 0,
  `result_summary` text DEFAULT NULL,
  `result_details` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'Structured JSON with findings' CHECK (json_valid(`result_details`)),
  `error_message` text DEFAULT NULL,
  `requested_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `completed_at` timestamp NULL DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL COMMENT 'Soft-delete timestamp; row counts toward daily quota even when hidden from user history.',
  PRIMARY KEY (`id`),
  KEY `idx_subscription_id` (`subscription_id`),
  KEY `idx_username_date` (`username`,`requested_at`),
  KEY `idx_status` (`status`),
  KEY `site_id` (`site_id`),
  KEY `idx_deleted_at` (`deleted_at`),
  CONSTRAINT `ai_monitor_log_reviews_ibfk_1` FOREIGN KEY (`subscription_id`) REFERENCES `ai_monitor_subscriptions` (`id`) ON DELETE CASCADE,
  CONSTRAINT `ai_monitor_log_reviews_ibfk_2` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ai_monitor_subscriptions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `username` varchar(32) NOT NULL,
  `notification_email` varchar(255) DEFAULT NULL COMMENT 'Email for issue notifications',
  `daily_review_limit` int(11) NOT NULL DEFAULT 3 COMMENT 'Max on-demand log reviews per day',
  `status` enum('active','suspended','cancelled') NOT NULL DEFAULT 'active',
  `activated_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `cancelled_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `daily_explain_limit` int(11) NOT NULL DEFAULT 10 COMMENT 'Max "Explain this" AI calls per user per 24h (0 disables)',
  `usage_day` date DEFAULT NULL COMMENT 'Date the daily_*_used counters currently apply to (server TZ).',
  `daily_reviews_used` int(11) NOT NULL DEFAULT 0 COMMENT 'On-demand log reviews started today.',
  `daily_explains_used` int(11) NOT NULL DEFAULT 0 COMMENT '"Explain this to me" AI calls today (cache hits do not count).',
  `http_checked_at` datetime DEFAULT NULL,
  `ssl_status` enum('ok','expiring','expired','unreachable','unknown') NOT NULL DEFAULT 'unknown',
  `ssl_expires_at` datetime DEFAULT NULL,
  `ssl_issuer` varchar(128) DEFAULT NULL,
  `ssl_checked_at` datetime DEFAULT NULL,
  `dns_status` enum('ok','cdn','mismatch','nxdomain','skipped','unknown') NOT NULL DEFAULT 'unknown',
  `dns_observed_ips` varchar(255) DEFAULT NULL COMMENT 'Comma-separated list of A records resolved at last check.',
  `dns_checked_at` datetime DEFAULT NULL,
  `whois_status` enum('ok','expiring','expired','unparsed','skipped','unknown') NOT NULL DEFAULT 'unknown',
  `whois_expires_at` datetime DEFAULT NULL,
  `whois_apex` varchar(255) DEFAULT NULL,
  `whois_checked_at` datetime DEFAULT NULL,
  `http_status` enum('ok','fail','unreachable','unknown') NOT NULL DEFAULT 'unknown' COMMENT 'Last HTTP probe outcome (set by scheduled-site-checks.php).',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_site_sub` (`site_id`),
  KEY `idx_username` (`username`),
  KEY `idx_status` (`status`),
  CONSTRAINT `ai_monitor_subscriptions_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ai_monitor_suppressions` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `site_id` int(11) DEFAULT NULL,
  `signature` varchar(64) NOT NULL,
  `scope` enum('site','server') NOT NULL,
  `suppressed_by_user` varchar(32) NOT NULL,
  `suppressed_at` datetime DEFAULT current_timestamp(),
  `reason` text DEFAULT NULL,
  `suppressed_occurrence_count` int(10) unsigned NOT NULL DEFAULT 0,
  `last_suppressed_event_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_suppression` (`site_id`,`signature`),
  KEY `idx_signature` (`signature`),
  CONSTRAINT `fk_aim_supp_site` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `announcements` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `markdown_content` text NOT NULL,
  `created_by` varchar(32) NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `active` tinyint(1) DEFAULT 1,
  `priority` int(11) DEFAULT 0,
  `pinned` tinyint(1) DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `idx_active` (`active`),
  KEY `idx_priority` (`priority`),
  KEY `idx_pinned` (`pinned`),
  KEY `idx_created_by` (`created_by`),
  KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `api_keys` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `key_name` varchar(255) NOT NULL,
  `api_key` varchar(64) NOT NULL,
  `api_secret` varchar(128) NOT NULL,
  `created_by` varchar(50) NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `last_used_at` timestamp NULL DEFAULT NULL,
  `is_active` tinyint(1) DEFAULT 1,
  `permissions` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`permissions`)),
  `rate_limit_per_hour` int(11) DEFAULT 1000,
  `usage_count` int(11) DEFAULT 0,
  `ip_whitelist` text DEFAULT NULL,
  `notes` text DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `api_key` (`api_key`),
  KEY `idx_api_key` (`api_key`),
  KEY `idx_created_by` (`created_by`),
  KEY `idx_active` (`is_active`),
  KEY `idx_last_used` (`last_used_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `api_tokens` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `token` varchar(128) NOT NULL,
  `username` varchar(50) NOT NULL,
  `expires_at` datetime NOT NULL,
  `ip_address` varchar(45) NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `token` (`token`),
  KEY `idx_token` (`token`),
  KEY `idx_username` (`username`),
  KEY `idx_expires` (`expires_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `api_usage_logs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `api_key_id` int(11) NOT NULL,
  `endpoint` varchar(255) NOT NULL,
  `method` varchar(10) NOT NULL,
  `ip_address` varchar(45) NOT NULL,
  `user_agent` text DEFAULT NULL,
  `request_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`request_data`)),
  `response_code` int(11) NOT NULL,
  `response_time_ms` int(11) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_api_key_id` (`api_key_id`),
  KEY `idx_endpoint` (`endpoint`),
  KEY `idx_created_at` (`created_at`),
  KEY `idx_ip_address` (`ip_address`),
  CONSTRAINT `api_usage_logs_ibfk_1` FOREIGN KEY (`api_key_id`) REFERENCES `api_keys` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `backup_history` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `target_id` int(11) NOT NULL,
  `user` varchar(50) NOT NULL,
  `backup_type` enum('site','userfiles','database','wordpress','postgres_database') NOT NULL,
  `backup_name` varchar(255) NOT NULL,
  `backup_path` varchar(500) NOT NULL,
  `local_path` varchar(500) DEFAULT NULL COMMENT 'Path to local backup file',
  `local_size` bigint(20) DEFAULT NULL COMMENT 'Size of local backup file',
  `backup_size` bigint(20) DEFAULT 0,
  `upload_method` enum('single','multipart') DEFAULT 'single',
  `multipart_upload_id` varchar(255) DEFAULT NULL,
  `status` enum('pending','claimed','running','completed','failed','deleted') NOT NULL DEFAULT 'pending',
  `creation_status` enum('pending','creating','created','failed') DEFAULT 'pending' COMMENT 'Status of local backup creation',
  `upload_status` enum('pending','uploading','uploaded','failed','skipped') DEFAULT NULL COMMENT 'Status of remote upload',
  `upload_started_at` timestamp NULL DEFAULT NULL,
  `upload_completed_at` timestamp NULL DEFAULT NULL,
  `upload_attempts` int(11) DEFAULT 0 COMMENT 'Number of upload attempts',
  `local_deleted_at` timestamp NULL DEFAULT NULL COMMENT 'When local file was deleted',
  `error_message` text DEFAULT NULL,
  `started_at` timestamp NULL DEFAULT current_timestamp(),
  `completed_at` timestamp NULL DEFAULT NULL,
  `metadata` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`metadata`)),
  PRIMARY KEY (`id`),
  KEY `idx_user` (`user`),
  KEY `idx_status` (`status`),
  KEY `idx_started_at` (`started_at`),
  KEY `idx_target_user` (`target_id`,`user`),
  KEY `idx_multipart_upload_id` (`multipart_upload_id`),
  KEY `idx_creation_status` (`creation_status`),
  KEY `idx_upload_status` (`upload_status`),
  KEY `idx_local_deleted` (`local_deleted_at`),
  CONSTRAINT `backup_history_ibfk_1` FOREIGN KEY (`target_id`) REFERENCES `backup_targets` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Backup history tracking - Fixed status default value to prevent null constraint violations';
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `backup_local_storage` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `storage_path` varchar(500) NOT NULL COMMENT 'Base path for local backup storage',
  `max_size_gb` int(11) DEFAULT 100 COMMENT 'Maximum storage size in GB',
  `current_size_bytes` bigint(20) DEFAULT 0 COMMENT 'Current used space in bytes',
  `cleanup_policy` enum('immediate','after_upload','age_based','size_based') DEFAULT 'after_upload',
  `retention_hours` int(11) DEFAULT 24 COMMENT 'Hours to keep local backups (for age_based)',
  `low_watermark_gb` int(11) DEFAULT 80 COMMENT 'Start cleanup when this size reached (for size_based)',
  `is_active` tinyint(1) DEFAULT 1,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_active` (`is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `backup_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `target_id` int(11) NOT NULL,
  `user` varchar(50) NOT NULL,
  `backup_type` enum('site','userfiles','database','wordpress','postgres_database') NOT NULL,
  `backup_name` varchar(255) NOT NULL,
  `priority` enum('low','normal','high') DEFAULT 'normal',
  `status` enum('queued','processing','completed','failed') DEFAULT 'queued',
  `attempts` int(11) DEFAULT 0,
  `error_message` text DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `started_at` timestamp NULL DEFAULT NULL,
  `completed_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `target_id` (`target_id`),
  KEY `idx_status_priority` (`status`,`priority`),
  KEY `idx_user` (`user`),
  CONSTRAINT `backup_queue_ibfk_1` FOREIGN KEY (`target_id`) REFERENCES `backup_targets` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `backup_schedules` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(255) NOT NULL,
  `target_id` int(11) NOT NULL,
  `backup_type` enum('site','userfiles','database','wordpress','postgres_database','all') NOT NULL,
  `resource_name` varchar(255) DEFAULT NULL COMMENT 'Optional: specific site domain or database name. If NULL, backs up first available resource',
  `schedule_type` enum('daily','weekly','monthly') NOT NULL,
  `schedule_time` time NOT NULL DEFAULT '02:00:00',
  `schedule_day` int(11) DEFAULT NULL,
  `max_retention` int(11) NOT NULL DEFAULT 30,
  `is_active` tinyint(1) DEFAULT 1,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `last_run_at` timestamp NULL DEFAULT NULL,
  `next_run_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_user` (`user`),
  KEY `idx_target_id` (`target_id`),
  KEY `idx_next_run` (`next_run_at`,`is_active`),
  CONSTRAINT `backup_schedules_ibfk_1` FOREIGN KEY (`target_id`) REFERENCES `backup_targets` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `backup_targets` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `type` enum('s3','ftp','sftp') NOT NULL DEFAULT 's3',
  `host` varchar(255) DEFAULT NULL,
  `port` int(11) DEFAULT NULL,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `remote_path` varchar(255) DEFAULT '/',
  `endpoint` varchar(255) DEFAULT NULL,
  `bucket` varchar(100) DEFAULT NULL,
  `access_key` varchar(100) DEFAULT NULL,
  `secret_key` varchar(255) DEFAULT NULL,
  `region` varchar(50) DEFAULT 'us-east-1',
  `path_prefix` varchar(255) DEFAULT '',
  `retention_days` int(11) DEFAULT 30,
  `max_backups` int(11) DEFAULT 10,
  `is_global` tinyint(1) DEFAULT 0,
  `owner` varchar(50) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_owner` (`owner`),
  KEY `idx_global` (`is_global`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `backup_upload_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `backup_id` int(11) NOT NULL,
  `priority` int(11) DEFAULT 5 COMMENT 'Upload priority (1=highest, 10=lowest)',
  `status` enum('queued','processing','completed','failed','cancelled') DEFAULT 'queued',
  `worker_id` varchar(100) DEFAULT NULL COMMENT 'ID of worker processing this upload',
  `started_at` timestamp NULL DEFAULT NULL,
  `completed_at` timestamp NULL DEFAULT NULL,
  `error_message` text DEFAULT NULL,
  `retry_count` int(11) DEFAULT 0,
  `next_retry_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_backup_id` (`backup_id`),
  KEY `idx_status_priority` (`status`,`priority`),
  KEY `idx_worker_id` (`worker_id`),
  KEY `idx_next_retry` (`next_retry_at`),
  CONSTRAINT `fk_upload_queue_backup` FOREIGN KEY (`backup_id`) REFERENCES `backup_history` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `client_allowances` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL,
  `max_cpu_allowance` decimal(4,2) DEFAULT 0.50,
  `max_memory_allowance` int(11) DEFAULT 512,
  `max_domains` int(11) DEFAULT 1,
  `max_disk_space` int(11) DEFAULT 1000,
  `max_email_accounts` int(11) DEFAULT 0,
  `api_enabled` tinyint(1) DEFAULT 0,
  `api_rate_limit` int(11) DEFAULT 100,
  `max_email_storage_mb` int(11) DEFAULT 1000,
  `account_type` enum('full','domain_dns','mail_dns') NOT NULL DEFAULT 'full' COMMENT 'Account type restricting feature access',
  `max_archived_mailboxes` int(11) NOT NULL DEFAULT 0 COMMENT 'Per-customer Bichon archival mailbox slots',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `container_crash_events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `container_name` varchar(100) NOT NULL DEFAULT 'haproxy-manager',
  `event_type` varchar(20) NOT NULL COMMENT 'die, oom, kill, restart',
  `exit_code` int(11) DEFAULT NULL,
  `oom_killed` tinyint(1) NOT NULL DEFAULT 0,
  `cause` varchar(50) NOT NULL COMMENT 'OOM_DOCKER, OOM_KERNEL, SEGFAULT, SIGKILL_EXTERNAL, PROCESS_ERROR, CLEAN_SHUTDOWN, ABORT, UNKNOWN_EXIT_N',
  `restart_count` int(11) DEFAULT NULL,
  `downtime_seconds` int(11) DEFAULT NULL,
  `memory_usage` varchar(100) DEFAULT NULL COMMENT 'Container memory usage at time of crash',
  `host_memory_free` varchar(100) DEFAULT NULL COMMENT 'Host memory state at time of crash',
  `dmesg_excerpt` text DEFAULT NULL COMMENT 'Relevant kernel log entries',
  `container_logs` text DEFAULT NULL COMMENT 'Last 50 lines of container logs before crash',
  `docker_inspect_json` text DEFAULT NULL COMMENT 'Full docker inspect State JSON',
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_container_crash_name` (`container_name`),
  KEY `idx_container_crash_cause` (`cause`),
  KEY `idx_container_crash_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `container_env_templates` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `variable_name` varchar(100) NOT NULL,
  `description` text DEFAULT NULL,
  `example_value` varchar(255) DEFAULT NULL,
  `category` enum('system','user','domain','path') DEFAULT 'system',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_variable` (`variable_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `container_types` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `description` text DEFAULT NULL,
  `base_image` varchar(255) NOT NULL,
  `min_cpu` decimal(3,2) DEFAULT 0.25,
  `min_memory` int(11) DEFAULT 256,
  `startup_env` text DEFAULT NULL COMMENT 'JSON object of startup environment variables',
  `user_variables` text DEFAULT NULL COMMENT 'JSON object of user-configurable variables',
  `mount_options` text DEFAULT NULL COMMENT 'JSON object of mount options and volumes',
  `last_image_pull` timestamp NULL DEFAULT NULL COMMENT 'Last time the base image was pulled',
  `image_digest` varchar(255) DEFAULT NULL COMMENT 'Current image digest/hash',
  `listen_port` int(11) DEFAULT 80 COMMENT 'Port that containers listen on for HAProxy backend configuration',
  `listen_port_tls` tinyint(1) DEFAULT 0 COMMENT 'If set, this port uses TLS/SSL for HAProxy backend',
  `active` tinyint(1) DEFAULT 1,
  `eol_date` date DEFAULT NULL COMMENT 'End of life date for this container type',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`),
  KEY `idx_name` (`name`),
  KEY `idx_active` (`active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `container_user_variables` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `container_type_id` int(11) NOT NULL,
  `domain_id` int(11) NOT NULL,
  `variable_name` varchar(100) NOT NULL,
  `variable_value` text DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_container_variable` (`container_type_id`,`domain_id`,`variable_name`),
  KEY `domain_id` (`domain_id`),
  CONSTRAINT `container_user_variables_ibfk_1` FOREIGN KEY (`container_type_id`) REFERENCES `container_types` (`id`) ON DELETE CASCADE,
  CONSTRAINT `container_user_variables_ibfk_2` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `containers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `container_id` varchar(255) NOT NULL,
  `domain_id` int(11) NOT NULL,
  `ip_address` varchar(45) DEFAULT NULL,
  `port` int(11) DEFAULT NULL,
  `status` varchar(20) DEFAULT 'stopped',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `container_id` (`container_id`),
  KEY `idx_container_id` (`container_id`),
  KEY `idx_domain_id` (`domain_id`),
  KEY `idx_status` (`status`),
  CONSTRAINT `containers_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `cpanel_imports` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `import_id` varchar(64) NOT NULL,
  `username` varchar(32) NOT NULL,
  `backup_file` varchar(512) NOT NULL,
  `status` enum('pending','running','completed','failed') NOT NULL DEFAULT 'pending',
  `progress` int(11) DEFAULT 0,
  `error_message` text DEFAULT NULL,
  `email_summary_to` varchar(255) DEFAULT NULL COMMENT 'Recipient for the post-import summary email; NULL means do not email',
  `log` longtext DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `completed_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `import_id` (`import_id`),
  KEY `idx_username` (`username`),
  KEY `idx_status` (`status`),
  KEY `idx_created` (`created_at`),
  KEY `idx_username_status` (`username`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `customer_valkey` (
  `username` varchar(32) NOT NULL,
  `enabled` tinyint(1) NOT NULL DEFAULT 0,
  `memory_mb` int(11) NOT NULL DEFAULT 0,
  `mode` enum('cache','snapshot') NOT NULL DEFAULT 'cache',
  `eviction_policy` varchar(32) NOT NULL DEFAULT 'allkeys-lru',
  `version` varchar(16) NOT NULL DEFAULT '8.0',
  `network_name` varchar(64) NOT NULL DEFAULT '',
  `container_name` varchar(64) NOT NULL DEFAULT '',
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `database_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL,
  `host` varchar(255) DEFAULT '%',
  `database_name` varchar(64) NOT NULL,
  `privileges` text NOT NULL,
  `created_by` varchar(32) NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_user_host_db` (`username`,`host`,`database_name`),
  KEY `idx_created_by` (`created_by`),
  KEY `idx_database` (`database_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `delegated_user_activity` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `delegated_user_id` int(11) NOT NULL,
  `action` varchar(100) NOT NULL,
  `resource_type` varchar(50) DEFAULT NULL COMMENT 'domain, database, email, etc.',
  `resource_id` varchar(100) DEFAULT NULL COMMENT 'specific resource identifier',
  `details` text DEFAULT NULL COMMENT 'JSON details about the action',
  `ip_address` varchar(45) NOT NULL,
  `user_agent` text DEFAULT NULL,
  `result` enum('success','failure','unauthorized') NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_delegated_user_id` (`delegated_user_id`),
  KEY `idx_action` (`action`),
  KEY `idx_resource_type` (`resource_type`),
  KEY `idx_created_at` (`created_at`),
  KEY `idx_result` (`result`),
  CONSTRAINT `delegated_user_activity_ibfk_1` FOREIGN KEY (`delegated_user_id`) REFERENCES `delegated_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `delegated_user_sessions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `session_id` varchar(128) NOT NULL,
  `delegated_user_id` int(11) NOT NULL,
  `ip_address` varchar(45) NOT NULL,
  `user_agent` text DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `last_activity` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `expires_at` timestamp NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `session_id` (`session_id`),
  KEY `idx_session_id` (`session_id`),
  KEY `idx_delegated_user_id` (`delegated_user_id`),
  KEY `idx_expires_at` (`expires_at`),
  CONSTRAINT `delegated_user_sessions_ibfk_1` FOREIGN KEY (`delegated_user_id`) REFERENCES `delegated_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!50003 SET @saved_cs_client      = @@character_set_client */ ;
/*!50003 SET @saved_cs_results     = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client  = utf8mb3 */ ;
/*!50003 SET character_set_results = utf8mb3 */ ;
/*!50003 SET collation_connection  = utf8mb3_general_ci */ ;
/*!50003 SET @saved_sql_mode       = @@sql_mode */ ;
/*!50003 SET sql_mode              = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER IF NOT EXISTS cleanup_expired_delegated_sessions_safe
    AFTER INSERT ON delegated_user_sessions
    FOR EACH ROW
BEGIN
    
    
    IF (RAND() * 100) < 10 THEN
        DELETE FROM delegated_user_sessions 
        WHERE expires_at < NOW() 
        AND id != NEW.id; 
    END IF;
END */;;
DELIMITER ;
/*!50003 SET sql_mode              = @saved_sql_mode */ ;
/*!50003 SET character_set_client  = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection  = @saved_col_connection */ ;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `delegated_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL,
  `password_hash` varchar(255) NOT NULL,
  `parent_username` varchar(32) NOT NULL,
  `display_name` varchar(100) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `can_manage_domains` tinyint(1) DEFAULT 0,
  `can_manage_sites` tinyint(1) DEFAULT 0,
  `can_manage_databases` tinyint(1) DEFAULT 0,
  `can_manage_email` tinyint(1) DEFAULT 0,
  `can_manage_files` tinyint(1) DEFAULT 0,
  `can_manage_backups` tinyint(1) DEFAULT 0,
  `can_view_terminal` tinyint(1) DEFAULT 0,
  `can_manage_wordpress` tinyint(1) DEFAULT 0,
  `allowed_domains` text DEFAULT NULL COMMENT 'JSON array of specific domains they can access (null = all parent domains)',
  `max_domains` int(11) DEFAULT NULL COMMENT 'Maximum domains they can create (null = unlimited within parent allowance)',
  `max_databases` int(11) DEFAULT NULL COMMENT 'Maximum databases they can create',
  `max_email_accounts` int(11) DEFAULT NULL COMMENT 'Maximum email accounts they can create',
  `is_active` tinyint(1) DEFAULT 1,
  `last_login` timestamp NULL DEFAULT NULL,
  `failed_login_attempts` int(11) DEFAULT 0,
  `locked_until` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `created_by` varchar(32) NOT NULL COMMENT 'Who created this delegated user',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  KEY `idx_parent_username` (`parent_username`),
  KEY `idx_username` (`username`),
  KEY `idx_is_active` (`is_active`),
  KEY `idx_created_by` (`created_by`),
  CONSTRAINT `chk_delegated_username_format` CHECK (`username` regexp '^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]$'),
  CONSTRAINT `chk_username_length` CHECK (char_length(`username`) >= 3 and char_length(`username`) <= 32)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `disk_usage_snapshot` (
  `id` int(11) NOT NULL DEFAULT 1,
  `snapshot_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `duration_ms` int(10) unsigned DEFAULT 0,
  `payload` longtext NOT NULL CHECK (json_valid(`payload`)),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `dns_challenges` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `domain_name` varchar(255) NOT NULL COMMENT 'Base domain (e.g., domain.tld)',
  `challenge_fqdn` varchar(255) NOT NULL COMMENT 'Full TXT record name (_acme-challenge.domain.tld)',
  `challenge_token` text NOT NULL COMMENT 'TXT record value from ACME',
  `status` enum('pending','created','verified','completed','failed') NOT NULL DEFAULT 'pending',
  `error_message` text DEFAULT NULL,
  `requested_at` timestamp NULL DEFAULT current_timestamp(),
  `verified_at` timestamp NULL DEFAULT NULL,
  `completed_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_site_id` (`site_id`),
  KEY `idx_domain_name` (`domain_name`),
  KEY `idx_status` (`status`),
  KEY `idx_requested_at` (`requested_at`),
  CONSTRAINT `dns_challenges_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `domains` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `domain_name` varchar(255) NOT NULL,
  `username` varchar(32) NOT NULL,
  `container_type_id` int(11) DEFAULT NULL,
  `cpu_allowance` decimal(4,2) DEFAULT 0.25,
  `memory_allowance` int(11) DEFAULT 256,
  `active` tinyint(1) DEFAULT 1,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `domain_name` (`domain_name`),
  KEY `idx_domain_name` (`domain_name`),
  KEY `idx_username` (`username`),
  KEY `idx_container_type` (`container_type_id`),
  KEY `idx_active` (`active`),
  CONSTRAINT `domains_ibfk_1` FOREIGN KEY (`container_type_id`) REFERENCES `container_types` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `email_accounts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email_address` varchar(255) NOT NULL,
  `username` varchar(32) NOT NULL,
  `domain_name` varchar(255) NOT NULL,
  `password_hash` varchar(255) NOT NULL,
  `quota_mb` int(11) DEFAULT 100,
  `active` tinyint(1) DEFAULT 1,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `archival_enabled` tinyint(1) NOT NULL DEFAULT 0,
  `bichon_account_id` varchar(64) DEFAULT NULL COMMENT 'Account ID returned by Bichon POST /api/v1/account',
  `archival_enabled_at` timestamp NULL DEFAULT NULL,
  `archival_paused_at` timestamp NULL DEFAULT NULL,
  `archival_last_error` varchar(255) DEFAULT NULL,
  `bichon_user_id` varchar(64) DEFAULT NULL COMMENT 'Bichon RBAC user id (POST /api/v1/users response.id) so the customer can log into the archive WebUI',
  `archival_purge_at` timestamp NULL DEFAULT NULL COMMENT 'After this time, the soft-disabled Bichon account should be deleted by the reconciliation cron',
  PRIMARY KEY (`id`),
  UNIQUE KEY `email_address` (`email_address`),
  KEY `idx_email_address` (`email_address`),
  KEY `idx_username` (`username`),
  KEY `idx_domain_name` (`domain_name`),
  KEY `idx_active` (`active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `email_aliases` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `alias_email` varchar(255) NOT NULL,
  `target_email` varchar(255) NOT NULL,
  `username` varchar(32) NOT NULL,
  `active` tinyint(1) DEFAULT 1,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_alias` (`alias_email`),
  KEY `idx_alias_email` (`alias_email`),
  KEY `idx_target_email` (`target_email`),
  KEY `idx_username` (`username`),
  KEY `idx_active` (`active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `email_archival_events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email_account_id` int(11) NOT NULL,
  `username` varchar(32) NOT NULL,
  `event_type` enum('enabled','disabled','paused','resumed','failed','deleted','soft_disabled','purged','password_reset') NOT NULL,
  `bichon_account_id` varchar(64) DEFAULT NULL,
  `actor` varchar(32) NOT NULL COMMENT 'username, "root", or "whmcs"',
  `details` text DEFAULT NULL,
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_email_account` (`email_account_id`),
  KEY `idx_username_created` (`username`,`created_at`),
  KEY `idx_event_type` (`event_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `email_forwarders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `source_email` varchar(255) NOT NULL,
  `destination_email` varchar(255) NOT NULL,
  `destination_type` enum('email','domain') DEFAULT 'email',
  `username` varchar(32) NOT NULL,
  `active` tinyint(1) DEFAULT 1,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_forward` (`source_email`,`destination_email`),
  KEY `idx_source_email` (`source_email`),
  KEY `idx_destination_email` (`destination_email`),
  KEY `idx_username` (`username`),
  KEY `idx_active` (`active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ftp_access_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `client_ip` varchar(45) DEFAULT NULL,
  `action` varchar(50) DEFAULT NULL,
  `filename` varchar(255) DEFAULT NULL,
  `filesize` bigint(20) DEFAULT 0,
  `timestamp` datetime DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_username` (`username`),
  KEY `idx_timestamp` (`timestamp`),
  KEY `idx_action` (`action`),
  KEY `idx_ftp_access_user_time` (`username`,`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ftp_groups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `groupname` varchar(50) NOT NULL,
  `gid` int(11) NOT NULL,
  `members` text DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `groupname` (`groupname`),
  KEY `idx_groupname` (`groupname`),
  KEY `idx_gid` (`gid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ftp_quotas` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `quota_type` enum('user','group','class','all') DEFAULT 'user',
  `per_session` enum('false','true') DEFAULT 'false',
  `limit_type` enum('soft','hard') DEFAULT 'soft',
  `bytes_in_avail` bigint(20) DEFAULT 0,
  `bytes_out_avail` bigint(20) DEFAULT 0,
  `bytes_xfer_avail` bigint(20) DEFAULT 0,
  `files_in_avail` int(11) DEFAULT 0,
  `files_out_avail` int(11) DEFAULT 0,
  `files_xfer_avail` int(11) DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  KEY `idx_username` (`username`),
  KEY `idx_quota_type` (`quota_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ftp_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(255) NOT NULL,
  `uid` int(11) NOT NULL,
  `gid` int(11) NOT NULL,
  `homedir` varchar(255) NOT NULL,
  `shell` varchar(50) DEFAULT '/bin/false',
  `count` int(11) DEFAULT 0,
  `accessed` datetime DEFAULT NULL,
  `modified` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `created` datetime DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  KEY `idx_username` (`username`),
  KEY `idx_uid` (`uid`),
  KEY `idx_ftp_users_login` (`username`,`password`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `haproxy_backend_servers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `backend_name` varchar(255) NOT NULL,
  `server_name` varchar(255) NOT NULL,
  `server_address` varchar(255) NOT NULL,
  `server_port` int(11) NOT NULL,
  `server_options` varchar(255) DEFAULT 'check',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_backend_server` (`backend_name`,`server_name`),
  KEY `idx_backend_name` (`backend_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `haproxy_domains` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `domain_name` varchar(255) NOT NULL,
  `backend_name` varchar(255) NOT NULL,
  `ssl_enabled` tinyint(1) DEFAULT 0,
  `ssl_certificate_path` varchar(255) DEFAULT NULL,
  `ssl_last_renewal` timestamp NULL DEFAULT NULL,
  `is_wildcard` tinyint(1) DEFAULT 0 COMMENT 'Whether this is a wildcard domain for HAProxy config generation',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `renewal_state` enum('ok','pending','transient_failure','unreachable','manual_review','deferred') NOT NULL DEFAULT 'pending' COMMENT 'State machine for renewal orchestrator. ok=current; pending=never-issued or freshly-scheduled; transient_failure=will retry with backoff; unreachable=domain DNS does not resolve to us; manual_review=retries exhausted, customer action required; deferred=excluded from auto-renewal (e.g. customer offboarded)',
  `last_renewal_error` text DEFAULT NULL COMMENT 'Most recent failure reason; empty when last attempt succeeded',
  `last_renewal_attempt_at` timestamp NULL DEFAULT NULL COMMENT 'When the orchestrator last tried to renew/issue this cert (success or failure)',
  `next_renewal_attempt_at` timestamp NULL DEFAULT NULL COMMENT 'Earliest time the orchestrator should retry this domain. NULL = pick on next sweep',
  `consecutive_failures` int(11) NOT NULL DEFAULT 0 COMMENT 'Resets to 0 on successful renewal; drives exponential backoff',
  `dns_validation` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Whether DNS-01 validation should be used. Forced 1 for is_wildcard=1',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_domain` (`domain_name`),
  KEY `idx_backend_name` (`backend_name`),
  KEY `idx_ssl_enabled` (`ssl_enabled`),
  KEY `idx_is_wildcard` (`is_wildcard`),
  KEY `idx_renewal_sweep` (`renewal_state`,`next_renewal_attempt_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `multipart_uploads` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `backup_id` int(11) NOT NULL,
  `upload_id` varchar(255) NOT NULL,
  `bucket` varchar(255) NOT NULL,
  `key` varchar(500) NOT NULL,
  `file_path` varchar(500) NOT NULL,
  `file_size` bigint(20) NOT NULL,
  `chunk_size` int(11) NOT NULL,
  `total_parts` int(11) NOT NULL,
  `completed_parts` text DEFAULT NULL COMMENT 'JSON array of completed part ETags',
  `status` enum('in_progress','completed','aborted','failed') DEFAULT 'in_progress',
  `started_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `completed_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_backup_id` (`backup_id`),
  KEY `idx_upload_id` (`upload_id`),
  KEY `idx_status` (`status`),
  KEY `idx_started_at` (`started_at`),
  KEY `idx_stale_uploads` (`status`,`updated_at`),
  CONSTRAINT `fk_multipart_backup` FOREIGN KEY (`backup_id`) REFERENCES `backup_history` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `permissions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `description` text DEFAULT NULL,
  `category` varchar(50) DEFAULT 'general',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `postgresql_databases` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `database_name` varchar(255) NOT NULL,
  `owner_username` varchar(100) NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `size_mb` decimal(10,2) DEFAULT 0.00,
  `encoding` varchar(50) DEFAULT 'UTF8',
  PRIMARY KEY (`id`),
  UNIQUE KEY `database_name` (`database_name`),
  KEY `idx_owner` (`owner_username`),
  KEY `idx_dbname` (`database_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `postgresql_user_database_access` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pg_user_id` int(11) NOT NULL,
  `pg_database_id` int(11) NOT NULL,
  `privileges` text DEFAULT NULL,
  `granted_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_user_db` (`pg_user_id`,`pg_database_id`),
  KEY `pg_database_id` (`pg_database_id`),
  CONSTRAINT `postgresql_user_database_access_ibfk_1` FOREIGN KEY (`pg_user_id`) REFERENCES `postgresql_users` (`id`) ON DELETE CASCADE,
  CONSTRAINT `postgresql_user_database_access_ibfk_2` FOREIGN KEY (`pg_database_id`) REFERENCES `postgresql_databases` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `postgresql_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) NOT NULL,
  `owner_username` varchar(100) NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `can_create_db` tinyint(1) DEFAULT 0,
  `connection_limit` int(11) DEFAULT -1,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  KEY `idx_owner` (`owner_username`),
  KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `site_builder_projects` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL COMMENT 'FK to sites.id - the WHP site this project belongs to',
  `username` varchar(32) NOT NULL COMMENT 'Owner username for quick lookups',
  `name` varchar(255) NOT NULL DEFAULT 'Untitled Site' COMMENT 'Project display name',
  `page_count` int(11) DEFAULT 1 COMMENT 'Number of pages in the project',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_site_project` (`site_id`),
  KEY `idx_username` (`username`),
  CONSTRAINT `site_builder_projects_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `site_containers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `container_id` varchar(255) NOT NULL,
  `container_number` int(11) NOT NULL COMMENT 'Container number within the site (1, 2, 3, etc.)',
  `ip_address` varchar(45) DEFAULT NULL,
  `port` int(11) DEFAULT NULL,
  `status` varchar(20) DEFAULT 'stopped',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `container_id` (`container_id`),
  UNIQUE KEY `unique_site_container_number` (`site_id`,`container_number`),
  KEY `idx_site_id` (`site_id`),
  KEY `idx_container_id` (`container_id`),
  KEY `idx_status` (`status`),
  KEY `idx_site_containers_site_status` (`site_id`,`status`),
  CONSTRAINT `site_containers_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `site_disable_audit` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `site_id` int(10) unsigned NOT NULL,
  `action` enum('disable','enable') NOT NULL,
  `reason` enum('unpaid','tos_violation','maintenance','admin_other') DEFAULT NULL,
  `actor` varchar(64) NOT NULL,
  `note` text DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_site_created` (`site_id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `site_domains` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `domain_id` int(11) NOT NULL,
  `fqdn` varchar(255) DEFAULT NULL,
  `is_primary` tinyint(1) DEFAULT 0,
  `is_wildcard` tinyint(1) DEFAULT 0 COMMENT 'Whether this domain entry is a wildcard',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_site_domain` (`site_id`,`domain_id`,`fqdn`),
  KEY `idx_site_id` (`site_id`),
  KEY `idx_domain_id` (`domain_id`),
  KEY `idx_is_primary` (`is_primary`),
  KEY `idx_site_domains_site_primary` (`site_id`,`is_primary`),
  CONSTRAINT `site_domains_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE,
  CONSTRAINT `site_domains_ibfk_2` FOREIGN KEY (`domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `site_log_positions` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `log_source` varchar(255) NOT NULL,
  `last_offset` bigint(20) unsigned DEFAULT 0,
  `last_inode` bigint(20) unsigned DEFAULT 0,
  `last_timestamp` bigint(20) DEFAULT 0,
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_site_source` (`site_id`,`log_source`),
  KEY `idx_site` (`site_id`),
  CONSTRAINT `fk_slp_site` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `sites` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_name` varchar(255) NOT NULL,
  `primary_domain_id` int(11) NOT NULL,
  `username` varchar(32) NOT NULL,
  `container_type_id` int(11) NOT NULL,
  `container_mode` enum('standalone','shared_httpd') NOT NULL DEFAULT 'standalone' COMMENT 'Container deployment mode',
  `container_count` int(11) DEFAULT 1,
  `cpu_per_container` decimal(4,2) DEFAULT 0.25,
  `memory_per_container` int(11) DEFAULT 256,
  `user_variables` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'User-configured variables for the container type' CHECK (json_valid(`user_variables`)),
  `active` tinyint(1) DEFAULT 1,
  `auto_recreate_on_update` tinyint(1) DEFAULT 0 COMMENT 'Automatically recreate containers when new image versions are available',
  `is_wildcard` tinyint(1) DEFAULT 0 COMMENT 'Whether this site handles wildcard subdomains',
  `ssl_enabled` tinyint(1) DEFAULT 0 COMMENT 'SSL certificate enabled (0=No, 1=Let''s Encrypt, 2=Custom)',
  `ssl_certificate_path` varchar(255) DEFAULT NULL COMMENT 'Path to SSL certificate file',
  `ssl_key_path` varchar(255) DEFAULT NULL COMMENT 'Path to SSL private key file',
  `ssl_force_https` tinyint(1) DEFAULT 0 COMMENT 'Force HTTPS redirects',
  `ssl_hsts_enabled` tinyint(1) DEFAULT 0 COMMENT 'Enable HSTS header',
  `ssl_last_renewal` timestamp NULL DEFAULT NULL COMMENT 'Last SSL certificate renewal date',
  `haproxy_backend_name` varchar(255) DEFAULT NULL COMMENT 'HAProxy backend name for this site',
  `haproxy_balance_method` varchar(50) DEFAULT 'roundrobin' COMMENT 'HAProxy load balancing method',
  `haproxy_health_check` varchar(255) DEFAULT NULL COMMENT 'HAProxy health check configuration',
  `haproxy_ssl_redirect` tinyint(1) DEFAULT 0 COMMENT 'HAProxy SSL redirect configuration',
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_site_name` (`site_name`),
  KEY `idx_username` (`username`),
  KEY `idx_primary_domain` (`primary_domain_id`),
  KEY `idx_container_type` (`container_type_id`),
  KEY `idx_active` (`active`),
  KEY `idx_ssl_enabled` (`ssl_enabled`),
  KEY `idx_haproxy_backend` (`haproxy_backend_name`),
  KEY `idx_auto_recreate` (`auto_recreate_on_update`),
  KEY `idx_is_wildcard` (`is_wildcard`),
  KEY `idx_sites_username_active` (`username`,`active`),
  CONSTRAINT `sites_ibfk_1` FOREIGN KEY (`primary_domain_id`) REFERENCES `domains` (`id`) ON DELETE CASCADE,
  CONSTRAINT `sites_ibfk_2` FOREIGN KEY (`container_type_id`) REFERENCES `container_types` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ssl_notification_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `domain_name` varchar(255) NOT NULL,
  `site_id` int(11) DEFAULT NULL COMMENT 'Owning site_id at time of send; NULL if domain not bound to a site',
  `customer_username` varchar(64) DEFAULT NULL COMMENT 'Owner username at time of send',
  `notification_type` enum('unreachable','manual_review','recovered','dns_validation_required') NOT NULL,
  `recipient_email` varchar(255) NOT NULL,
  `sent_at` timestamp NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_dedup` (`domain_name`,`notification_type`,`sent_at`),
  KEY `idx_customer_recent` (`customer_username`,`sent_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Per-(domain,type) email send history. Orchestrator queries this for 7d cooldown + per-customer digest grouping.';
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `ssl_renewal_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `domain_name` varchar(255) NOT NULL,
  `renewal_status` enum('success','failed','pending') NOT NULL,
  `renewal_date` timestamp NULL DEFAULT current_timestamp(),
  `error_message` text DEFAULT NULL,
  `certificate_expires` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_domain_name` (`domain_name`),
  KEY `idx_renewal_status` (`renewal_status`),
  KEY `idx_renewal_date` (`renewal_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `sso_tokens` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `token` varchar(64) NOT NULL,
  `username` varchar(50) NOT NULL,
  `api_key_id` int(11) NOT NULL,
  `redirect_url` varchar(500) DEFAULT NULL,
  `expires_at` timestamp NOT NULL,
  `used_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `ip_address` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `token` (`token`),
  KEY `idx_token` (`token`),
  KEY `idx_username` (`username`),
  KEY `idx_expires_at` (`expires_at`),
  KEY `idx_api_key_id` (`api_key_id`),
  CONSTRAINT `sso_tokens_ibfk_1` FOREIGN KEY (`api_key_id`) REFERENCES `api_keys` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `system_ssl_certificates` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `service_name` varchar(50) NOT NULL,
  `domain_name` varchar(255) NOT NULL,
  `certificate_path` varchar(255) NOT NULL,
  `private_key_path` varchar(255) NOT NULL,
  `ssl_enabled` tinyint(1) DEFAULT 0,
  `auto_renew` tinyint(1) DEFAULT 1,
  `last_renewal` timestamp NULL DEFAULT NULL,
  `expires_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_service_domain` (`service_name`,`domain_name`),
  KEY `idx_service_name` (`service_name`),
  KEY `idx_ssl_enabled` (`ssl_enabled`),
  KEY `idx_auto_renew` (`auto_renew`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `terminal_access_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `container_id` varchar(255) NOT NULL,
  `container_user` varchar(255) NOT NULL,
  `shell` varchar(50) NOT NULL DEFAULT 'bash',
  `connected_at` timestamp NULL DEFAULT current_timestamp(),
  `disconnected_at` timestamp NULL DEFAULT NULL,
  `commands_executed` int(11) DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `idx_username` (`username`),
  KEY `idx_container` (`container_id`),
  KEY `idx_connected` (`connected_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `terminal_preferences` (
  `username` varchar(255) NOT NULL,
  `default_shell` varchar(50) DEFAULT 'bash',
  `theme` varchar(50) DEFAULT 'dark',
  `font_size` int(11) DEFAULT 14,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `user_databases` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `database_name` varchar(64) NOT NULL,
  `owner_username` varchar(32) NOT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `size_bytes` bigint(20) DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `database_name` (`database_name`),
  KEY `idx_owner` (`owner_username`),
  KEY `idx_database` (`database_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `user_passwords` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL,
  `password_hash` varchar(255) NOT NULL,
  `mysql_password` varchar(255) NOT NULL,
  `postgresql_password` varchar(255) DEFAULT NULL,
  `last_updated` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  KEY `idx_username` (`username`),
  KEY `idx_user_passwords_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `user_permissions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL,
  `permission_id` int(11) NOT NULL,
  `granted_at` timestamp NULL DEFAULT current_timestamp(),
  `granted_by` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_user_permission` (`username`,`permission_id`),
  KEY `permission_id` (`permission_id`),
  KEY `idx_username` (`username`),
  CONSTRAINT `user_permissions_ibfk_1` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wordpress_sites` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` varchar(100) NOT NULL,
  `domain` varchar(255) NOT NULL,
  `container_name` varchar(255) NOT NULL,
  `site_path` varchar(500) DEFAULT '/home/{user}/public_html',
  `admin_email` varchar(255) DEFAULT NULL,
  `notification_email` varchar(255) DEFAULT NULL COMMENT 'Recipient for backup/update notifications. NULL = no email regardless of notify_* flags.',
  `notify_backup_complete` tinyint(1) NOT NULL DEFAULT 0,
  `notify_backup_failed` tinyint(1) NOT NULL DEFAULT 0,
  `notify_update_complete` tinyint(1) NOT NULL DEFAULT 0,
  `notify_update_failed` tinyint(1) NOT NULL DEFAULT 0,
  `admin_username` varchar(100) DEFAULT NULL,
  `database_name` varchar(64) DEFAULT NULL,
  `wp_version` varchar(20) DEFAULT NULL,
  `wp_version_checked_at` datetime DEFAULT NULL COMMENT 'Last time wp_version was refreshed (cron or inline event).',
  `status` enum('active','inactive','maintenance') DEFAULT 'active',
  `auto_update_core` tinyint(1) DEFAULT 0,
  `auto_update_plugins` tinyint(1) DEFAULT 0,
  `auto_update_themes` tinyint(1) DEFAULT 0,
  `auto_backup_before_update` tinyint(1) DEFAULT 1,
  `preferred_backup_target_id` int(11) DEFAULT NULL,
  `backup_target_id` int(11) DEFAULT NULL,
  `is_staging` tinyint(1) DEFAULT 0,
  `parent_site_id` int(11) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_domain` (`domain`),
  KEY `idx_user` (`user`),
  KEY `idx_database_name` (`database_name`),
  KEY `idx_backup_target` (`backup_target_id`),
  KEY `idx_preferred_backup_target` (`preferred_backup_target_id`),
  KEY `idx_container` (`container_name`),
  KEY `parent_site_id` (`parent_site_id`),
  CONSTRAINT `fk_wordpress_backup_target` FOREIGN KEY (`preferred_backup_target_id`) REFERENCES `backup_targets` (`id`) ON DELETE SET NULL,
  CONSTRAINT `fk_wp_backup_target` FOREIGN KEY (`backup_target_id`) REFERENCES `backup_targets` (`id`) ON DELETE SET NULL,
  CONSTRAINT `wordpress_sites_ibfk_1` FOREIGN KEY (`parent_site_id`) REFERENCES `wordpress_sites` (`id`) ON DELETE SET NULL,
  CONSTRAINT `wordpress_sites_ibfk_2` FOREIGN KEY (`preferred_backup_target_id`) REFERENCES `backup_targets` (`id`) ON DELETE SET NULL,
  CONSTRAINT `wordpress_sites_ibfk_3` FOREIGN KEY (`backup_target_id`) REFERENCES `backup_targets` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wp_cli_containers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `container_image` varchar(100) NOT NULL,
  `is_active` tinyint(1) DEFAULT 1,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `container_image` (`container_image`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wp_login_tokens` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `token` varchar(64) NOT NULL,
  `admin_username` varchar(100) NOT NULL,
  `expires_at` timestamp NOT NULL,
  `used` tinyint(1) DEFAULT 0,
  `used_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `token` (`token`),
  KEY `site_id` (`site_id`),
  KEY `idx_token` (`token`,`expires_at`),
  CONSTRAINT `wp_login_tokens_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `wordpress_sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wp_recommended_plugins` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `slug` varchar(100) NOT NULL,
  `name` varchar(255) NOT NULL,
  `description` text DEFAULT NULL,
  `category` varchar(50) DEFAULT NULL,
  `install_url` varchar(500) DEFAULT NULL,
  `is_active` tinyint(1) DEFAULT 1,
  `sort_order` int(11) DEFAULT 0,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wp_security_settings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `disable_file_editor` tinyint(1) DEFAULT 1,
  `disable_xmlrpc` tinyint(1) DEFAULT 1,
  `hide_wp_version` tinyint(1) DEFAULT 0,
  `disable_directory_browsing` tinyint(1) DEFAULT 1,
  `limit_login_attempts` tinyint(1) DEFAULT 1,
  `security_headers_enabled` tinyint(1) DEFAULT 1,
  `block_php_uploads` tinyint(1) DEFAULT 1,
  `force_strong_passwords` tinyint(1) DEFAULT 0,
  `two_factor_enabled` tinyint(1) DEFAULT 0,
  `change_login_url` varchar(50) DEFAULT NULL,
  `database_prefix` varchar(20) DEFAULT 'wp_',
  `last_security_scan` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `site_id` (`site_id`),
  CONSTRAINT `wp_security_settings_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `wordpress_sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wp_site_plugins` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `plugin_slug` varchar(100) NOT NULL,
  `plugin_name` varchar(255) DEFAULT NULL,
  `version` varchar(20) DEFAULT NULL,
  `is_active` tinyint(1) DEFAULT 1,
  `auto_update` tinyint(1) DEFAULT 0,
  `last_updated` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_site_plugin` (`site_id`,`plugin_slug`),
  KEY `idx_plugin` (`plugin_slug`),
  CONSTRAINT `wp_site_plugins_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `wordpress_sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wp_update_history` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `update_type` enum('core','plugin','theme','all') NOT NULL,
  `item_name` varchar(255) DEFAULT NULL,
  `old_version` varchar(20) DEFAULT NULL,
  `new_version` varchar(20) DEFAULT NULL,
  `status` enum('in_progress','completed','failed','rolled_back') NOT NULL,
  `error_message` text DEFAULT NULL,
  `backup_id` int(11) DEFAULT NULL,
  `started_at` timestamp NULL DEFAULT current_timestamp(),
  `completed_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_site_updates` (`site_id`,`started_at`),
  CONSTRAINT `wp_update_history_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `wordpress_sites` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `wp_update_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site_id` int(11) NOT NULL,
  `update_id` int(11) NOT NULL,
  `update_type` varchar(20) NOT NULL COMMENT 'core, plugins, themes, all',
  `backup_id` int(11) DEFAULT NULL COMMENT 'ID of backup that must complete first',
  `status` enum('waiting_for_backup','ready','processing','completed','failed') DEFAULT 'waiting_for_backup',
  `error_message` text DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT current_timestamp(),
  `started_at` timestamp NULL DEFAULT NULL,
  `completed_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_status` (`status`),
  KEY `idx_backup_id` (`backup_id`),
  KEY `idx_site_id` (`site_id`),
  KEY `idx_created_at` (`created_at`),
  KEY `update_id` (`update_id`),
  CONSTRAINT `wp_update_queue_ibfk_1` FOREIGN KEY (`site_id`) REFERENCES `wordpress_sites` (`id`) ON DELETE CASCADE,
  CONSTRAINT `wp_update_queue_ibfk_2` FOREIGN KEY (`update_id`) REFERENCES `wp_update_history` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!50001 DROP VIEW IF EXISTS `active_delegated_users`*/;
/*!50001 SET @saved_cs_client          = @@character_set_client */;
/*!50001 SET @saved_cs_results         = @@character_set_results */;
/*!50001 SET @saved_col_connection     = @@collation_connection */;
/*!50001 SET character_set_client      = utf8mb3 */;
/*!50001 SET character_set_results     = utf8mb3 */;
/*!50001 SET collation_connection      = utf8mb3_general_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED */
/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
/*!50001 VIEW `active_delegated_users` AS select `du`.`id` AS `id`,`du`.`username` AS `username`,`du`.`parent_username` AS `parent_username`,`du`.`display_name` AS `display_name`,`du`.`email` AS `email`,`du`.`can_manage_domains` AS `can_manage_domains`,`du`.`can_manage_sites` AS `can_manage_sites`,`du`.`can_manage_databases` AS `can_manage_databases`,`du`.`can_manage_email` AS `can_manage_email`,`du`.`can_manage_files` AS `can_manage_files`,`du`.`can_manage_backups` AS `can_manage_backups`,`du`.`can_view_terminal` AS `can_view_terminal`,`du`.`can_manage_wordpress` AS `can_manage_wordpress`,`du`.`allowed_domains` AS `allowed_domains`,`du`.`max_domains` AS `max_domains`,`du`.`max_databases` AS `max_databases`,`du`.`max_email_accounts` AS `max_email_accounts`,`du`.`last_login` AS `last_login`,`du`.`created_at` AS `created_at`,`du`.`created_by` AS `created_by`,`ca`.`max_domains` AS `parent_max_domains`,`ca`.`max_email_accounts` AS `parent_max_email_accounts` from (`delegated_users` `du` left join `client_allowances` `ca` on(`ca`.`username` = `du`.`parent_username`)) where `du`.`is_active` = 1 */;
/*!50001 SET character_set_client      = @saved_cs_client */;
/*!50001 SET character_set_results     = @saved_cs_results */;
/*!50001 SET collation_connection      = @saved_col_connection */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

