blackout = $blackout; $this->settings = $settings; } /** * Returns the check identifier. * * @return string Identifier. */ public function get_id(): string { return 'blackout'; } /** * Whether a loopback request is required. * * @return bool False. */ public function needs_loopback(): bool { return false; } /** * Runs the check. * * @return Result The finding. */ public function run(): Result { $label = __( 'AI inside WordPress', 'ai-blackout' ); $core_ai = $this->blackout->core_ai(); $mode = $this->blackout->firewall()->get_mode(); $detail = array( 'core_ai_present' => $core_ai->has_core_ai(), 'core_ai_active' => $core_ai->has_core_ai() && $core_ai->is_core_ai_active(), 'abilities_api' => $core_ai->has_abilities_api(), 'abilities_off' => $this->settings->is_blackout_enabled( Settings::BLACKOUT_ABILITIES ), 'connectors_ui' => $this->settings->is_blackout_enabled( Settings::BLACKOUT_CONNECTORS_UI ), 'outbound_mode' => $mode, 'integrations' => $this->describe_integrations(), 'environment_keys' => $core_ai->find_environment_keys(), ); if ( aiblackout_is_disabled() ) { return new Result( $this->get_id(), $label, Result::INACTIVE, __( 'AI Blackout is switched off in wp-config.php.', 'ai-blackout' ), __( 'WordPress AI features, the Abilities API and outgoing AI requests are all running normally.', 'ai-blackout' ), __( 'Remove the AIBLACKOUT_DISABLE line from wp-config.php to switch the plugin back on.', 'ai-blackout' ), $detail ); } if ( ! $this->blackout->is_active() ) { return new Result( $this->get_id(), $label, Result::INACTIVE, __( 'AI is switched on inside your WordPress.', 'ai-blackout' ), __( 'WordPress 7.0 ships with AI built in, and other plugins add their own. Nothing here is being turned off, and nothing is watching what your site sends to AI companies.', 'ai-blackout' ), __( 'Turn the switches on the AI inside WordPress screen on, to switch off the AI features built into WordPress and your other plugins.', 'ai-blackout' ), $detail ); } if ( Settings::OUTBOUND_MONITOR === $mode ) { return new Result( $this->get_id(), $label, Result::DECLARED, sprintf( /* translators: %s: A comma-separated list of what is switched off. */ __( 'AI features are switched off (%s), but outgoing AI requests are only being watched.', 'ai-blackout' ), $this->describe_enabled_switches() ), __( 'Your site can still send content to AI companies. Every attempt is being recorded so you can see who is doing it, but nothing is being stopped.', 'ai-blackout' ), __( 'Look at what has been recorded, then switch outgoing requests from "Watch only" to "Block them".', 'ai-blackout' ), $detail ); } if ( Settings::OUTBOUND_OFF === $mode ) { return new Result( $this->get_id(), $label, Result::DECLARED, sprintf( /* translators: %s: A comma-separated list of what is switched off. */ __( 'AI features are switched off (%s). Outgoing requests are not being watched.', 'ai-blackout' ), $this->describe_enabled_switches() ), __( 'Plugins on your site can still send your content to AI companies, and nothing is recording it.', 'ai-blackout' ), __( 'Turn watching for outgoing requests on, at least in "Watch only" mode, to find out what your site is sending.', 'ai-blackout' ), $detail ); } $keys = $core_ai->find_environment_keys(); if ( ! empty( $keys ) ) { return new Result( $this->get_id(), $label, Result::BROKEN, sprintf( /* translators: %s: A comma-separated list of constant or environment variable names. */ __( 'AI is blocked, but AI provider keys are still configured on the server (%s).', 'ai-blackout' ), implode( ', ', $keys ) ), __( 'Requests to AI companies are being refused, so the keys cannot currently be used. But they live in wp-config.php or your server environment, where no plugin can remove them. If this plugin is switched off or deleted, they work again immediately.', 'ai-blackout' ), __( 'Remove those lines from wp-config.php or your server environment if you no longer want AI keys on this site.', 'ai-blackout' ), $detail ); } return new Result( $this->get_id(), $label, Result::PROTECTED_STATE, sprintf( /* translators: %s: A comma-separated list of what is switched off. */ __( 'AI is switched off inside WordPress (%s), and outgoing AI requests are refused.', 'ai-blackout' ), $this->describe_enabled_switches() ), __( 'Plugins on your site cannot reach AI companies through WordPress. This covers anything using the normal WordPress way of making a request, which is nearly everything. A plugin that opens its own network connection would not be stopped.', 'ai-blackout' ), '', $detail ); } /** * Lists the switches currently on, in plain language. * * @return string Comma-separated description. */ private function describe_enabled_switches(): string { $on = array(); if ( $this->settings->is_blackout_enabled( Settings::BLACKOUT_CORE_AI ) ) { $on[] = __( "WordPress's own AI", 'ai-blackout' ); } if ( $this->settings->is_blackout_enabled( Settings::BLACKOUT_ABILITIES ) ) { $on[] = __( 'the AI agent interface', 'ai-blackout' ); } if ( $this->settings->is_blackout_enabled( Settings::BLACKOUT_CONNECTORS_UI ) ) { $on[] = __( 'the AI keys screen', 'ai-blackout' ); } foreach ( $this->blackout->get_active_integrations() as $id => $integration ) { if ( $this->blackout->is_integration_enabled( $id ) ) { $on[] = $integration->get_label(); } } if ( empty( $on ) ) { return __( 'nothing', 'ai-blackout' ); } return implode( ', ', $on ); } /** * Summarises each stripper for the detail payload. * * @return array Stripper states keyed by identifier. */ private function describe_integrations(): array { $out = array(); foreach ( $this->blackout->get_integrations() as $id => $integration ) { $out[ $id ] = array( 'label' => $integration->get_label(), 'target_active' => $integration->is_target_active(), 'enabled' => $this->blackout->is_integration_enabled( $id ), 'target_version' => $integration->get_target_version(), 'verified_version' => $integration->get_verified_version(), ); } return $out; } }