From a6f8afaf84e6e6738d24b953de4febcffb74a933 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sat, 19 Sep 2026 19:52:18 +0200 Subject: [PATCH] Check revised plugins too, and only with a trusted enough provider --- .../AssistantAudit/AssistantAuditAgent.cs | 29 +++++++++++++++---- .../AssistantPluginRevisionDialog.razor.cs | 7 ++++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs b/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs index 0fd6fef8..aa1e600f 100644 --- a/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs +++ b/app/MindWork AI Studio/Agents/AssistantAudit/AssistantAuditAgent.cs @@ -124,12 +124,19 @@ public sealed class AssistantAuditAgent(ILogger logger, ILo /// Resolves and stores the provider configuration used for assistant plugin audits. /// /// The provider to use when no provider is configured for the audit agent. - /// The configured provider, or when no audit provider is configured. + /// The configured provider, or Provider.NONE when no audit provider is configured. + /// + /// A fallback is a provider somebody picked for something else: the assistant they were building, + /// the revision they asked for, the check they are standing in front of. Whether it may read a + /// plugin's source and its Lua files is decided by what this agent requires, not by what it was + /// picked under, so it has to clear this agent's confidence bar before it is used. Otherwise a + /// provider an organization ruled out for audits would see the very thing it was ruled out for. + /// public AIStudio.Settings.Provider ResolveProvider(AIStudio.Settings.Provider? fallbackProvider = null) { var provider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_ASSISTANT_PLUGIN_AUDIT, null, true); - if (provider == AIStudio.Settings.Provider.NONE && fallbackProvider is not null) - provider = fallbackProvider; + if (provider == AIStudio.Settings.Provider.NONE && fallbackProvider is { } candidate && this.SettingsManager.IsProviderConfident(candidate, Tools.Components.AGENT_ASSISTANT_PLUGIN_AUDIT)) + provider = candidate; this.ProviderSettings = provider; return provider; @@ -149,12 +156,24 @@ public sealed class AssistantAuditAgent(ILogger logger, ILo var provider = this.ResolveProvider(fallbackProvider); if (provider == AIStudio.Settings.Provider.NONE) { - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.SettingsSuggest, string.Format(TB("No provider is configured for the Security Audit Agent.")))); + // + // There are two ways to end up here, and they send the user to different places: nobody + // named a provider, or the one at hand is not trusted enough for an audit. Saying that + // none is configured while one sits right there would send them looking in vain. + // + var wasFallbackRejected = fallbackProvider is { UsedLLMProvider: not LLMProviders.NONE }; + var message = wasFallbackRejected + ? TB("The selected provider is not trusted enough for security checks. Pick one which meets the confidence required here, or choose a dedicated provider for security checks in the app settings.") + : TB("No provider is configured for the Security Audit Agent."); + + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.SettingsSuggest, message)); return new AssistantAuditResult { Level = nameof(AssistantAuditLevel.UNKNOWN), - Summary = TB("No audit provider is configured."), + Summary = wasFallbackRejected + ? TB("The provider is not trusted enough for security checks.") + : TB("No audit provider is configured."), }; } diff --git a/app/MindWork AI Studio/Dialogs/AssistantPluginRevisionDialog.razor.cs b/app/MindWork AI Studio/Dialogs/AssistantPluginRevisionDialog.razor.cs index d3664be5..5aaabdf7 100644 --- a/app/MindWork AI Studio/Dialogs/AssistantPluginRevisionDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/AssistantPluginRevisionDialog.razor.cs @@ -198,7 +198,12 @@ public partial class AssistantPluginRevisionDialog : MSGComponentBase await this.InvokeAsync(this.StateHasChanged); try { - var audit = await this.AssistantPluginAuditService.RunAuditAsync(updatedPlugin); + // + // The provider the user picked for the revision serves as the fallback: it is used only + // when nothing is configured for the audit agent, and only when it is trusted enough for + // an audit. Without it, a revised plugin could not be checked at all here. + // + var audit = await this.AssistantPluginAuditService.RunAuditAsync(updatedPlugin, fallbackProvider: this.providerSettings); if (audit.Level is AssistantAuditLevel.UNKNOWN) return audit;