: * * 1. Permission override form — a single checkbox that toggles * `override_abilities_permission` on the server row. When ON, every * ability exposed to this server via `wp_acrossai_mcp_server_abilities` * has its `permission_callback` swapped for `__return_true` at * ability-call time by `PermissionOverrideProcessor`. Gated by 6 * defensive layers documented in DEC-F030-PERMISSION-CALLBACK-OPERATOR- * OPT-IN-BYPASS. * 2. AbilitiesManagerPromoCard — recommends the sibling * `acrossai-abilities-manager` plugin for fine-grained per-ability * access-control rules; includes a "Prefer to use code?"
* block documenting the WP core filter (`wp_register_ability_args`, * P999999) for developers who don't want the sibling plugin. * * @package AcrossAI_MCP_Manager * @subpackage Admin/Partials/ServerTabs * @since 0.0.6 */ namespace AcrossAI_MCP_Manager\Admin\Partials\ServerTabs; use AcrossAI_MCP_Manager\Admin\Partials\ServerTabs\Partials\AbilitiesManagerPromoCard; // Exit if accessed directly. defined( 'ABSPATH' ) || exit; /** * Access Control tab — vendor React panel + F030 override form + promo card. * * @package AcrossAI_MCP_Manager * @subpackage Admin/Partials/ServerTabs * @since 0.0.6 */ final class AccessControlTab extends AbstractServerTab { /** * The tab's URL slug. * * @since 0.0.6 * @return string */ public function slug(): string { return 'access-control'; } /** * The tab's operator-visible label. * * @since 0.0.6 * @return string */ public function label(): string { return __( 'Access Control', 'acrossai-mcp-manager' ); } /** * Priority slot. * * @since 0.0.7 * @return int */ public function priority(): int { return 70; } /** * Renders the three sections: vendor React panel, F030 permission-override * form, F030 abilities-manager promo card. * * @since 0.0.6 * @param array $server Server row data (from Row::to_array()). * @return void */ protected function render_body( array $server ): void { // F042 — Explain the default admin-only policy above the vendor panel. $this->render_default_policy_notice(); // Section 1 — vendor wpb-access-control React panel (unchanged). \AcrossAI_MCP_Manager\Public\Renderers\AccessControlBlock::instance()->render( (int) $server['id'], array( 'context' => 'admin', 'cap' => 'manage_options', 'submit_target_url' => $this->server_edit_url( $server, 'access-control' ), 'nonce_action' => 'acrossai_mcp_manager_server_' . (int) $server['id'], ) ); // F030 — save notice. $this->render_save_notice(); // F030 — Permission Override section: one header + one form (toggle + // nested promo callout + footer) + a sibling
code block. echo '
'; $this->render_layout_styles(); echo '
'; $this->render_pom_header(); $this->render_permission_override_form( $server ); AbilitiesManagerPromoCard::instance()->render_code_details(); echo '
'; } /** * F042 — Info banner explaining the runtime-filter default policy. * * Enforced by {@see TransportPermissionDefault::filter_default_capability} * on `mcp_adapter_default_transport_permission_user_capability` — no DB * rules are seeded, and this banner describes the plugin's plugin-wide * policy, not per-server state. * * @return void */ private function render_default_policy_notice(): void { echo '

'; esc_html_e( 'Only administrators can reach this server until you add an access rule below.', 'acrossai-mcp-manager' ); echo '

'; } /** * Render the shared header (icon + H2 + intro paragraph) that sits * outside the main card. * * @return void */ private function render_pom_header(): void { echo '
'; echo '

' . esc_html__( 'Permission Override', 'acrossai-mcp-manager' ) . '

'; echo '
'; echo '

'; printf( /* translators: 1: permission_callback, 2: permission_callback. */ esc_html__( 'Control how MCP requests to this server evaluate each ability’s %1$s — either flip the coarse per-server override below, or install the AcrossAI Abilities Manager for a UI that edits every ability’s %2$s individually.', 'acrossai-mcp-manager' ), 'permission_callback', 'permission_callback' ); echo '

'; } /** * Emit the minimal structural layout stylesheet for the Permission * Override section. Layout-only (flex rows, badge, icon spacing) — * no backgrounds, borders, or shadows so it inherits the surrounding * WP admin visual style. * * @return void */ private function render_layout_styles(): void { static $emitted = false; if ( $emitted ) { return; } $emitted = true; echo <<<'CSS' CSS; } /** * Render the success notice when the operator has just saved the override * toggle. The `acrossai_mcp_manager_permission_saved=1` query flag is set * by the redirect in `Settings::handle_save_permission_override()`. * * The flag only gates a static translated string — no user-supplied text * is echoed from the GET param, so no XSS concern. * * @return void */ private function render_save_notice(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only flag, no state mutation. if ( empty( $_GET['acrossai_mcp_manager_permission_saved'] ) ) { return; } echo '

'; esc_html_e( 'Permission override setting saved.', 'acrossai-mcp-manager' ); echo '

'; } /** * Render the F030 permission-override form section. * * Structure per spec FR-003 / FR-005 / FR-016 / FR-017: * - Optional warning banner when the flag is currently ON (FR-016). * - Explanatory paragraph. * - Form with per-server nonce + hidden action + hidden server_id + * labelled checkbox + submit button. * - Inline ', wp_json_encode( $form_id ), wp_json_encode( $confirm_msg ) ); } }