Levels live in core’s blog_public option: 1 and 0 are core’s own values, and the private levels are -1 (logged-in users), -2 (site users), -3 (administrators), -4 (password) and -5 (members). On multisite, core mirrors the option into the public column of the sites table, so a private site drops out of get_sites( array( 'public' => 1 ) ) listings. The values match those used by the old More Privacy Options plugin and LH Multisite Privacy Options, so sites already set by either keep their level and are enforced as soon as this plugin is active. An unrecognised negative value is treated as administrators only.
Core treats only 0 as noindex and only 0 in robots.txt, and leaves sitemaps on for any non-zero value, so the plugin adds noindex, a disallow-all robots.txt and turns sitemaps off for every private level.
wp_hash_password(). The Settings > Reading field is a registered setting whose value is handed to the password class and never stored as an option itself.template_redirect at priority 0, ahead of other plugins that serve responses there (lh-ai-legibility’s Markdown and llms.txt run at priority 1, and lh-oauth-server’s /authorize at 10). robots.txt and the favicon are left alone.rest_authentication_errors at priority 101, after core’s cookie and nonce check at 100, so the user is final. An earlier error (such as lh-oauth-server’s 401 challenge for a missing bearer token) is passed through untouched. In-process rest_do_request() calls do not pass through this filter.admin_init at priority 0. Ordinary wp-admin screens are already restricted by WordPress.X-Robots-Tag: noindex, nofollow and LiteSpeed’s no-cache control. A level change purges LiteSpeed, so pages cached while a site was public are not served once it is private.While Enable Mastodon Apps is active, LH_Site_Privacy_Compat lets the requests a Mastodon client makes before it has a token through the gate: the v1 and v2 instance routes, app registration, nodeinfo, the plugin’s own authorization-header diagnostic and /oauth/revoke. They match the routes LH Disable REST API for anonymous users leaves open on public sites, and none return posts or members. /oauth/token needs nothing here, because Enable Mastodon Apps reports the site as public to privacy plugins for that one request. /oauth/authorize is deliberately not exempt: the gate sends visitors to log in first, so only someone with access to the site can grant an app access. Once the app has a token, Enable Mastodon Apps sets the current user from it and the normal access check applies.
The instance responses include the site’s name, tagline and icon, so a logged-out visitor can see those on a private site that runs Enable Mastodon Apps. The admin email and user and post counts Enable Mastodon Apps would also include are blanked network-wide on LocalHero by LH Sites Specific.
Every site can use every level; there is deliberately no network setting to narrow the choice. The only exception is the members level, which is offered only where a membership plugin answers who is a member, since without one nobody could qualify. Saving a level that cannot be used, from the Reading screen or an ability alike, is refused and the stored value kept.
The one network setting is the level for new sites (lh_site_privacy_default_level, Network Admin > Settings). It is applied on wp_initialize_site to new sites created as public; a site cloned from a template may later overwrite it with the template’s own value.
LH Multisite Privacy Options, LH Private Site and LH Extra Multisite Privacy. Their behaviour of bouncing a logged-in user with no role on a site to their primary blog was deliberately dropped in favour of the no-access page.