prefix . 'wpfmj_error_log'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, automation_id bigint(20) UNSIGNED NOT NULL, form_entry_id bigint(20) UNSIGNED NOT NULL, error_type varchar(50) NOT NULL, error_message text NOT NULL, retry_count int(11) NOT NULL DEFAULT 0, resolved tinyint(1) NOT NULL DEFAULT 0, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY automation_id (automation_id), KEY created_at (created_at), KEY resolved (resolved) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); // Register custom post type temporarily for flush_rewrite_rules require_once WPFMJ_PLUGIN_DIR . 'includes/class-wpfmj-cpt.php'; $cpt = new WPFMJ_CPT(); $cpt->register_post_type(); // Flush rewrite rules flush_rewrite_rules(); // Set plugin version add_option('wpfmj_version', WPFMJ_VERSION); // Generate encryption key if it doesn't exist // CRITICAL: This key is used to encrypt/decrypt API credentials // If this key is lost or changed, all saved automations will fail to decrypt credentials // ENTERPRISE DEPLOYMENT: Back up this key before any WordPress migration or database restore if (!get_option('wpfmj_encryption_key')) { $key = base64_encode(random_bytes(32)); add_option('wpfmj_encryption_key', $key, '', false); // Don't autoload // Log key generation for audit trail error_log('WPFMJ: New encryption key generated on activation. Ensure database backups include wp_options table.'); } // Schedule cleanup cron job (weekly cleanup of old error logs) if (!wp_next_scheduled('wpfmj_cleanup_error_logs')) { wp_schedule_event(time(), 'weekly', 'wpfmj_cleanup_error_logs'); } } }