| @@ -5,20 +5,10 @@ | ||
| 5 | 5 | use FluentSupport\App\Modules\PermissionManager; |
| 6 | 6 | use FluentSupport\App\Services\Helper; |
| 7 | 7 | |
| 8 | 8 | /** |
| 9 | - * Maps MCP abilities to Fluent Support's existing capability model. The MCP | |
| 10 | - * user IS a WordPress user with Fluent Support agent permissions (fst_*), | |
| 11 | - * stored in _fluent_support_permissions user meta. We never invent a parallel | |
| 12 | - * permission system — we reuse PermissionManager, the same check the admin | |
| 13 | - * REST routes use (AgentTicketPolicy calls the same methods for every ticket | |
| 14 | - * API request). | |
| 15 | - * | |
| 16 | - * Two layers: | |
| 17 | - * - transport(): can this user reach the Fluent Support MCP endpoint at all? | |
| 18 | - * - per-ability permission_callback: gating inside AbilitiesRegistrar. | |
| 19 | - * | |
| 20 | - * Annotations are UX hints only; this class is the transport enforcement boundary. | |
| 9 | + * MCP on/off state and the transport gate. Permissions reuse PermissionManager, | |
| 10 | + * the same fst_* checks the admin REST routes use. Per-ability checks run on top. | |
| 21 | 11 | */ |
| 22 | 12 | class PermissionGate |
| 23 | 13 | { |
| 24 | 14 | const OPTION_KEY = '_mcp_settings'; |
| @@ -23,11 +13,9 @@ | ||
| 23 | 13 | { |
| 24 | 14 | const OPTION_KEY = '_mcp_settings'; |
| 25 | 15 | |
| 26 | 16 | /** |
| 27 | - * Transport gate for the fluent-support MCP server. Runs on every request. | |
| 28 | - * Checks (a) MCP is enabled and (b) user holds at least a Fluent Support | |
| 29 | - * agent permission. Per-ability permission_callback still runs on top. | |
| 17 | + * Runs on every MCP request: MCP must be on and the user must have ticket access. | |
| 30 | 18 | * |
| 31 | 19 | * @param mixed $request |
| 32 | 20 | * @return true|\WP_Error |
| 33 | 21 | */ |
| @@ -39,12 +27,10 @@ | ||
| 39 | 27 | __('Fluent Support MCP is disabled. Enable it in Settings → MCP.', 'fluent-support') |
| 40 | 28 | ); |
| 41 | 29 | } |
| 42 | 30 | |
| 43 | - // Explicit login check for a clear error code; canAccessTicketRoutes() | |
| 44 | - // already returns false for unauthenticated users (user_id 0 → empty | |
| 45 | - // permissions), but the distinct code helps the agent distinguish | |
| 46 | - // "not logged in" from "logged in but no Fluent Support role". | |
| 31 | + // canAccessTicketRoutes() covers this too, but a separate code tells the | |
| 32 | + // agent "not logged in" apart from "no Fluent Support access". | |
| 47 | 33 | if (!is_user_logged_in()) { |
| 48 | 34 | return new \WP_Error( |
| 49 | 35 | 'fluent_support_mcp_unauthorized', |
| 50 | 36 | __('Authentication required to access the Fluent Support MCP server.', 'fluent-support') |
| @@ -50,9 +36,9 @@ | ||
| 50 | 36 | __('Authentication required to access the Fluent Support MCP server.', 'fluent-support') |
| 51 | 37 | ); |
| 52 | 38 | } |
| 53 | 39 | |
| 54 | - // Reuse the same check AgentTicketPolicy uses for all GET ticket routes. | |
| 40 | + // Same check AgentTicketPolicy uses for ticket routes. | |
| 55 | 41 | if (!PermissionManager::canAccessTicketRoutes()) { |
| 56 | 42 | return new \WP_Error( |
| 57 | 43 | 'fluent_support_mcp_forbidden', |
| 58 | 44 | __('Your account does not have Fluent Support access.', 'fluent-support') |
| @@ -62,10 +48,9 @@ | ||
| 62 | 48 | return true; |
| 63 | 49 | } |
| 64 | 50 | |
| 65 | 51 | /** |
| 66 | - * Whether the MCP server is enabled. Ships OFF; enabled via the | |
| 67 | - * fluent_kit/mcp_toggle_handlers filter (FluentHub) or a future settings UI. | |
| 52 | + * Off by default. | |
| 68 | 53 | */ |
| 69 | 54 | public static function isEnabled() |
| 70 | 55 | { |
| 71 | 56 | $settings = Helper::getOption(self::OPTION_KEY, []); |
| @@ -73,14 +58,11 @@ | ||
| 73 | 58 | return is_array($settings) && isset($settings['active']) && $settings['active'] === 'yes'; |
| 74 | 59 | } |
| 75 | 60 | |
| 76 | 61 | /** |
| 77 | - * Persist the master on/off switch. Called from the FluentHub toggle handler | |
| 78 | - * and any future settings controller. | |
| 62 | + * Re-checks manage_options because the FluentHub toggle path leaves auth to | |
| 63 | + * another plugin. | |
| 79 | 64 | * |
| 80 | - * Defense-in-depth: re-check manage_options here because the toolkit toggle | |
| 81 | - * path delegates auth to an external plugin. | |
| 82 | - * | |
| 83 | 65 | * @param bool $enabled |
| 84 | 66 | * @return bool |
| 85 | 67 | */ |
| 86 | 68 | public static function setEnabled($enabled) |
| @@ -101,9 +83,8 @@ | ||
| 101 | 83 | } |
| 102 | 84 | |
| 103 | 85 | /** |
| 104 | 86 | * SLA thresholds used by getSupportContext and getSupportInsights. |
| 105 | - * Written by McpSettingsController::saveSettings(). | |
| 106 | 87 | * |
| 107 | 88 | * @return array{first_response_hours: int, resolution_hours: int} |
| 108 | 89 | */ |
| 109 | 90 | public static function getSlaSettings() |
| @@ -117,10 +98,10 @@ | ||
| 117 | 98 | ]; |
| 118 | 99 | } |
| 119 | 100 | |
| 120 | 101 | /** |
| 121 | - * AI guidelines injected into getSupportContext. Sanitized at read time so | |
| 122 | - * anything stored raw before Phase 3 is cleaned on the way out. | |
| 102 | + * AI guidelines for getSupportContext. Sanitized on read, since older | |
| 103 | + * values may have been stored raw. | |
| 123 | 104 | * |
| 124 | 105 | * @return string Up to 2000 characters, no HTML. |
| 125 | 106 | */ |
| 126 | 107 | public static function getAiGuidelines() |