From 97ee1648df506b0886f792b975dbf2bb1322e716 Mon Sep 17 00:00:00 2001 From: sergeymitr Date: Wed, 22 Oct 2025 19:49:52 -0400 Subject: [PATCH 1/5] Atomic: Auto-adjust 'blog_public' property to match privacy model. --- .../update-atomic-site-endpoint-is-private | 4 +++ .../sal/class.json-api-site-jetpack.php | 10 ++++++++ .../update-atomic-site-endpoint-is-private | 4 +++ .../wpcomsh/private-site/private-site.php | 25 +++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 projects/plugins/jetpack/changelog/update-atomic-site-endpoint-is-private create mode 100644 projects/plugins/wpcomsh/changelog/update-atomic-site-endpoint-is-private diff --git a/projects/plugins/jetpack/changelog/update-atomic-site-endpoint-is-private b/projects/plugins/jetpack/changelog/update-atomic-site-endpoint-is-private new file mode 100644 index 0000000000000..db172453cab30 --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-atomic-site-endpoint-is-private @@ -0,0 +1,4 @@ +Significance: minor +Type: other + +Atomic: Modify `/sites/%s` endpoint to rely on the privacy model, and auto-adjust local 'blog_public' option to match privacy model. diff --git a/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php b/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php index c64d6f5925a5d..d756b85a02ab0 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php @@ -357,6 +357,16 @@ public function allowed_file_types() { * @return bool Is site private? */ public function is_private() { + if ( ! ( new Host() )->is_woa_site() ) { + return false; + } + + // Making sure wpcomsh plugin is available. + if ( function_exists( '\Private_Site\maybe_fix_private_site_option' ) && function_exists( '\Private_Site\site_is_private' ) ) { + Private_Site\maybe_fix_private_site_option(); + return Private_Site\site_is_private(); + } + return (int) $this->get_atomic_cloud_site_option( 'blog_public' ) === -1; } diff --git a/projects/plugins/wpcomsh/changelog/update-atomic-site-endpoint-is-private b/projects/plugins/wpcomsh/changelog/update-atomic-site-endpoint-is-private new file mode 100644 index 0000000000000..c62f56cecc637 --- /dev/null +++ b/projects/plugins/wpcomsh/changelog/update-atomic-site-endpoint-is-private @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Atomic: Auto-adjust 'blog_public' property to match privacy model. diff --git a/projects/plugins/wpcomsh/private-site/private-site.php b/projects/plugins/wpcomsh/private-site/private-site.php index d863cbde1fd18..45603ed9fd860 100755 --- a/projects/plugins/wpcomsh/private-site/private-site.php +++ b/projects/plugins/wpcomsh/private-site/private-site.php @@ -9,6 +9,7 @@ namespace Private_Site; use Automattic\Jetpack\Connection\Rest_Authentication; +use Automattic\Jetpack\Status\Host; use Jetpack; use WP_Error; use WP_REST_Request; @@ -260,6 +261,30 @@ function site_is_private() { return defined( 'AT_PRIVACY_MODEL' ) && AT_PRIVACY_MODEL === 'wp_uploads'; } +/** + * Update blog_private option to match the site's actual privacy status. + * Sets it to -1 for private sites, 1 for public sites. + */ +function maybe_fix_private_site_option() { + // Privacy model only applies to WordPress.com Atomic sites. + if ( ! ( new Host() )->is_woa_site() ) { + return; + } + + // Coming soon sites are a special case of public and private sites, so we skip them here. + if ( site_is_coming_soon() || site_is_public_coming_soon() ) { + return; + } + + $is_private = site_is_private(); + $expected_value = $is_private ? -1 : 1; + $current_value = (int) get_option( 'blog_public' ); + + if ( $current_value !== $expected_value ) { + update_option( 'blog_public', $expected_value ); + } +} + /** * Determine if site access should be blocked for various types of requests. * This function is cached for subsequent calls so we can use it gratuitously. From 5399786fd569a52cb1f0dc32ca98d39e99851249 Mon Sep 17 00:00:00 2001 From: sergeymitr Date: Thu, 23 Oct 2025 15:08:22 -0400 Subject: [PATCH 2/5] Save option updates to log2logstash. --- .../wpcomsh/private-site/private-site.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/projects/plugins/wpcomsh/private-site/private-site.php b/projects/plugins/wpcomsh/private-site/private-site.php index 45603ed9fd860..a876ccb1846ef 100755 --- a/projects/plugins/wpcomsh/private-site/private-site.php +++ b/projects/plugins/wpcomsh/private-site/private-site.php @@ -282,9 +282,37 @@ function maybe_fix_private_site_option() { if ( $current_value !== $expected_value ) { update_option( 'blog_public', $expected_value ); + register_shutdown_function( __NAMESPACE__ . '\private_site_log_option_adjusted', $current_value, $expected_value ); } } +/** + * Save a log entry when the blog_public option is adjusted. + * + * @param int $current_value Current option value. + * @param int $new_value New option value. + * + * @return void + */ +function private_site_log_option_adjusted( $current_value, $new_value ) { + $jetpack_options = get_option( 'jetpack_options' ); + $blog_id = ( is_array( $jetpack_options ) && ! empty( $jetpack_options['id'] ) ) ? $jetpack_options['id'] : 0; + + $data = wp_json_encode( + array( + 'feature' => 'atomic_private_site_blog_public_adjusted', + 'message' => 'Value of blog_public option adjusted according to the privacy model.', + 'blog_id' => $blog_id, + 'properties' => array( + 'current_value' => $current_value, + 'new_value' => $new_value, + ), + ) + ); + + wp_remote_post( 'https://public-api.wordpress.com/rest/v1.1/logstash', array( 'body' => array( 'params' => $data ) ) ); +} + /** * Determine if site access should be blocked for various types of requests. * This function is cached for subsequent calls so we can use it gratuitously. From 617362320dc12d8eebbd30f0aad0cbb72e8aa4b5 Mon Sep 17 00:00:00 2001 From: sergeymitr Date: Thu, 23 Oct 2025 15:09:45 -0400 Subject: [PATCH 3/5] Adjust namespace chain in function calls. --- projects/plugins/jetpack/sal/class.json-api-site-jetpack.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php b/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php index d756b85a02ab0..051620f8d5dda 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php @@ -363,8 +363,8 @@ public function is_private() { // Making sure wpcomsh plugin is available. if ( function_exists( '\Private_Site\maybe_fix_private_site_option' ) && function_exists( '\Private_Site\site_is_private' ) ) { - Private_Site\maybe_fix_private_site_option(); - return Private_Site\site_is_private(); + \Private_Site\maybe_fix_private_site_option(); + return \Private_Site\site_is_private(); } return (int) $this->get_atomic_cloud_site_option( 'blog_public' ) === -1; From d9c0b6373b037fe3e80dcfb3d16bbf8836cb068b Mon Sep 17 00:00:00 2001 From: sergeymitr Date: Thu, 23 Oct 2025 19:06:43 -0400 Subject: [PATCH 4/5] Silence phan false-positives. --- projects/plugins/jetpack/sal/class.json-api-site-jetpack.php | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php b/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php index 051620f8d5dda..fb242063069be 100644 --- a/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php +++ b/projects/plugins/jetpack/sal/class.json-api-site-jetpack.php @@ -355,6 +355,7 @@ public function allowed_file_types() { * Return site's privacy status. * * @return bool Is site private? + * @phan-suppress PhanUndeclaredFunction */ public function is_private() { if ( ! ( new Host() )->is_woa_site() ) { From 07490bb2f02c945a881d09d930e8a1d1966f573f Mon Sep 17 00:00:00 2001 From: sergeymitr Date: Wed, 29 Oct 2025 12:33:31 -0400 Subject: [PATCH 5/5] Do not update the '0' value. --- projects/plugins/wpcomsh/private-site/private-site.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/projects/plugins/wpcomsh/private-site/private-site.php b/projects/plugins/wpcomsh/private-site/private-site.php index a599000e341e4..1c2f6ec65c8a7 100755 --- a/projects/plugins/wpcomsh/private-site/private-site.php +++ b/projects/plugins/wpcomsh/private-site/private-site.php @@ -276,9 +276,15 @@ function maybe_fix_private_site_option() { return; } - $is_private = site_is_private(); + $is_private = site_is_private(); + $current_value = (int) get_option( 'blog_public' ); + + // No action needed if site is public and option is already set to 0 (discourage indexing). + if ( ! $is_private && $current_value === 0 ) { + return; + } + $expected_value = $is_private ? -1 : 1; - $current_value = (int) get_option( 'blog_public' ); if ( $current_value !== $expected_value ) { update_option( 'blog_public', $expected_value );