Improved data security by enforcing provider filtering (#290)

This commit is contained in:
Thorsten Sommer 2025-02-23 15:05:29 +01:00 committed by GitHub
parent bfc9f2ea1d
commit 9bd79bd3a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 370 additions and 41 deletions

View File

@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MindWork AI Studio", "MindWork AI Studio\MindWork AI Studio.csproj", "{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceCodeRules", "SourceCodeRules\SourceCodeRules\SourceCodeRules.csproj", "{0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -12,6 +14,10 @@ Global
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{059FDFCC-7D0B-474E-9F20-B9C437DF1CDD}.Release|Any CPU.Build.0 = Release|Any CPU
{0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0976C1CB-D499-4C86-8ADA-B7A7A4DE0BF8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection

View File

@ -9,5 +9,6 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=agentic/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=groq/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mwais/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ollama/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=tauri_0027s/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -140,17 +140,7 @@ public sealed class AgentDataSourceSelection (ILogger<AgentDataSourceSelection>
//
// We start with the provider currently selected by the user:
var agentProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == provider.Id);
// If the user preselected an agent provider, we try to use this one:
if (this.SettingsManager.ConfigurationData.AgentDataSourceSelection.PreselectAgentOptions)
{
var configuredAgentProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.AgentDataSourceSelection.PreselectedAgentProvider);
// If the configured agent provider is available, we use it:
if (configuredAgentProvider != default)
agentProvider = configuredAgentProvider;
}
var agentProvider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_DATA_SOURCE_SELECTION, provider.Id, true);
// Assign the provider settings to the agent:
logger.LogInformation($"The agent for the data source selection uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()}).");

View File

@ -132,18 +132,8 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
public void SetLLMProvider(IProvider provider)
{
// We start with the provider currently selected by the user:
var agentProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == provider.Id);
// If the user preselected an agent provider, we try to use this one:
if (this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectAgentOptions)
{
var configuredAgentProvider = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectedAgentProvider);
// If the configured agent provider is available, we use it:
if (configuredAgentProvider != default)
agentProvider = configuredAgentProvider;
}
var agentProvider = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION, provider.Id, true);
// Assign the provider settings to the agent:
logger.LogInformation($"The agent for the retrieval context validation uses the provider '{agentProvider.InstanceName}' ({agentProvider.UsedLLMProvider.ToName()}, confidence={agentProvider.UsedLLMProvider.GetConfidence(this.SettingsManager).Level.GetName()}).");
this.ProviderSettings = agentProvider;
@ -163,11 +153,16 @@ public sealed class AgentRetrievalContextValidation (ILogger<AgentRetrievalConte
if (!this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
return [];
logger.LogInformation($"Validating {retrievalContexts.Count:###,###,###,###} retrieval contexts.");
// Prepare the list of validation tasks:
var validationTasks = new List<Task<RetrievalContextValidationResult>>(retrievalContexts.Count);
// Read the number of parallel validations:
var numParallelValidations = this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.NumParallelValidations;
var numParallelValidations = 3;
if(this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectAgentOptions)
numParallelValidations = this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.NumParallelValidations;
numParallelValidations = Math.Max(1, numParallelValidations);
// Use a semaphore to limit the number of parallel validations:

View File

@ -1,3 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using AIStudio.Provider;
using AIStudio.Settings;
@ -47,6 +49,7 @@ public partial class ConfigurationProviderSelection : ComponentBase, IMessageBus
#endregion
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private IEnumerable<ConfigurationSelectData<string>> FilteredData()
{
if(this.Component is not Tools.Components.NONE and not Tools.Components.APP_SETTINGS)

View File

@ -37,8 +37,12 @@
@if (this.areDataSourcesEnabled)
{
<MudTextSwitch Label="AI-based data source selection" Value="@this.aiBasedSourceSelection" LabelOn="Yes, let the AI decide which data sources are needed." LabelOff="No, I manually decide which data source to use." ValueChanged="@this.AutoModeChanged"/>
<MudTextSwitch Label="AI-based data validation" Value="@this.aiBasedValidation" LabelOn="Yes, let the AI validate & filter the retrieved data." LabelOff="No, use all data retrieved from the data sources." ValueChanged="@this.ValidationModeChanged"/>
@if (this.SettingsManager.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
{
<MudTextSwitch Label="AI-based data validation" Value="@this.aiBasedValidation" LabelOn="Yes, let the AI validate & filter the retrieved data." LabelOff="No, use all data retrieved from the data sources." ValueChanged="@this.ValidationModeChanged"/>
}
@if (this.aiBasedSourceSelection is false || this.DataSourcesAISelected.Count == 0)
{
<MudField Label="Available Data Sources" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.aiBasedSourceSelection">

View File

@ -1,3 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using AIStudio.Assistants;
using AIStudio.Provider;
using AIStudio.Settings;
@ -29,6 +31,7 @@ public partial class ProviderSelection : ComponentBase
await this.ProviderSettingsChanged.InvokeAsync(provider);
}
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private IEnumerable<AIStudio.Settings.Provider> GetAvailableProviders()
{
var minimumLevel = this.SettingsManager.GetMinimumConfidenceLevel(this.AssistantBase?.Component ?? Tools.Components.NONE);

View File

@ -59,11 +59,7 @@ public partial class ReadWebContent : ComponentBase
if(this.PreselectContentCleanerAgent)
this.useContentCleanerAgent = true;
if (this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider);
else
this.providerSettings = this.ProviderSettings;
this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(Tools.Components.AGENT_TEXT_CONTENT_CLEANER, this.ProviderSettings.Id, true);
await base.OnInitializedAsync();
}

View File

@ -1,3 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using AIStudio.Dialogs;
using AIStudio.Provider;
using AIStudio.Settings;
@ -26,6 +28,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
#endregion
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task AddLLMProvider()
{
var dialogParameters = new DialogParameters<ProviderDialog>
@ -48,6 +51,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
}
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task EditLLMProvider(AIStudio.Settings.Provider provider)
{
var dialogParameters = new DialogParameters<ProviderDialog>
@ -82,6 +86,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
}
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task DeleteLLMProvider(AIStudio.Settings.Provider provider)
{
var dialogParameters = new DialogParameters
@ -112,6 +117,7 @@ public partial class SettingsPanelProviders : SettingsPanelBase
return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName;
}
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
private async Task UpdateProviders()
{
this.AvailableLLMProviders.Clear();

View File

@ -137,7 +137,9 @@ public partial class ProviderDialog : ComponentBase, ISecretId
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
// Load the used instance names:
#pragma warning disable MWAIS0001
this.UsedInstanceNames = this.SettingsManager.ConfigurationData.Providers.Select(x => x.InstanceName.ToLowerInvariant()).ToList();
#pragma warning restore MWAIS0001
// When editing, we need to load the data:
if(this.IsEditing)

View File

@ -53,6 +53,10 @@
<PackageReference Include="ReverseMarkdown" Version="4.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SourceCodeRules\SourceCodeRules\SourceCodeRules.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
<!-- Read the meta data file -->
<Target Name="ReadMetaData" BeforeTargets="BeforeBuild">
<Error Text="The ../../metadata.txt file was not found!" Condition="!Exists('../../metadata.txt')" />

View File

@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
@ -141,7 +142,8 @@ public sealed class SettingsManager(ILogger<SettingsManager> logger)
return minimumLevel;
}
public Provider GetPreselectedProvider(Tools.Components component, string? chatProviderId = null)
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
public Provider GetPreselectedProvider(Tools.Components component, string? currentProviderId = null, bool usePreselectionBeforeCurrentProvider = false)
{
var minimumLevel = this.GetMinimumConfidenceLevel(component);
@ -149,17 +151,43 @@ public sealed class SettingsManager(ILogger<SettingsManager> logger)
if (this.ConfigurationData.Providers.Count == 1 && this.ConfigurationData.Providers[0].UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
return this.ConfigurationData.Providers[0];
// When there is a chat provider, and it has a confidence level that is high enough, we return it:
if (chatProviderId is not null && !string.IsNullOrWhiteSpace(chatProviderId))
// Is there a current provider with a sufficiently high confidence level?
Provider currentProvider = default;
if (currentProviderId is not null && !string.IsNullOrWhiteSpace(currentProviderId))
{
var chatProvider = this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == chatProviderId);
if (chatProvider.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
return chatProvider;
var currentProviderProbe = this.ConfigurationData.Providers.FirstOrDefault(x => x.Id == currentProviderId);
if (currentProviderProbe.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
currentProvider = currentProviderProbe;
}
// When there is a component-preselected provider, and it has a confidence level that is high enough, we return it:
var preselectedProvider = component.PreselectedProvider(this);
if(preselectedProvider != default && preselectedProvider.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
// Is there a component-preselected provider with a sufficiently high confidence level?
Provider preselectedProvider = default;
var preselectedProviderProbe = component.PreselectedProvider(this);
if(preselectedProviderProbe != default && preselectedProviderProbe.UsedLLMProvider.GetConfidence(this).Level >= minimumLevel)
preselectedProvider = preselectedProviderProbe;
//
// Case: The preselected provider should be used before the current provider,
// and the preselected provider is available and has a confidence level
// that is high enough.
//
if(usePreselectionBeforeCurrentProvider && preselectedProvider != default)
return preselectedProvider;
//
// Case: The current provider is available and has a confidence level that is
// high enough.
//
if(currentProvider != default)
return currentProvider;
//
// Case: The current provider should be used before the preselected provider,
// but the current provider is not available or does not have a confidence
// level that is high enough. The preselected provider is available and
// has a confidence level that is high enough.
//
if(preselectedProvider != default)
return preselectedProvider;
// When there is an app-wide preselected provider, and it has a confidence level that is high enough, we return it:

View File

@ -21,4 +21,8 @@ public enum Components
CHAT,
APP_SETTINGS,
AGENT_TEXT_CONTENT_CLEANER,
AGENT_DATA_SOURCE_SELECTION,
AGENT_RETRIEVAL_CONTEXT_VALIDATION,
}

View File

@ -1,3 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using AIStudio.Provider;
using AIStudio.Settings;
@ -12,6 +14,10 @@ public static class ComponentsExtensions
Components.BIAS_DAY_ASSISTANT => false,
Components.APP_SETTINGS => false,
Components.AGENT_TEXT_CONTENT_CLEANER => false,
Components.AGENT_DATA_SOURCE_SELECTION => false,
Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION => false,
_ => true,
};
@ -76,6 +82,7 @@ public static class ComponentsExtensions
_ => default,
};
[SuppressMessage("Usage", "MWAIS0001:Direct access to `Providers` is not allowed")]
public static AIStudio.Settings.Provider PreselectedProvider(this Components component, SettingsManager settingsManager) => component switch
{
Components.GRAMMAR_SPELLING_ASSISTANT => settingsManager.ConfigurationData.GrammarSpelling.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider) : default,
@ -95,6 +102,10 @@ public static class ComponentsExtensions
Components.CHAT => settingsManager.ConfigurationData.Chat.PreselectOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.Chat.PreselectedProvider) : default,
Components.AGENT_TEXT_CONTENT_CLEANER => settingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider) : default,
Components.AGENT_DATA_SOURCE_SELECTION => settingsManager.ConfigurationData.AgentDataSourceSelection.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.AgentDataSourceSelection.PreselectedAgentProvider) : default,
Components.AGENT_RETRIEVAL_CONTEXT_VALIDATION => settingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectAgentOptions ? settingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == settingsManager.ConfigurationData.AgentRetrievalContextValidation.PreselectedAgentProvider) : default,
_ => default,
};

View File

@ -35,7 +35,7 @@ public sealed class AugmentationOne : IAugmentationProcess
var numTotalRetrievalContexts = retrievalContexts.Count;
// Want the user to validate all retrieval contexts?
if (settings.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation)
if (settings.ConfigurationData.AgentRetrievalContextValidation.EnableRetrievalContextValidation && chatThread.DataSourceOptions.AutomaticValidation)
{
// Let's get the validation agent & set up its provider:
var validationAgent = Program.SERVICE_PROVIDER.GetService<AgentRetrievalContextValidation>()!;

View File

@ -77,6 +77,11 @@
"resolved": "31.0.3",
"contentHash": "ygck8DR4mG/VDA/LgIVVGpEtXXPDVaaNZNJGrOAJ4pckVw4MbAQ3n/u6YFDv3bwlQhlxTmPhCyk5E4hxe96Crg=="
},
"Humanizer.Core": {
"type": "Transitive",
"resolved": "2.14.1",
"contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
},
"Markdig": {
"type": "Transitive",
"resolved": "0.37.0",
@ -132,6 +137,56 @@
"resolved": "8.0.11",
"contentHash": "cy04xnMSTXTkRPjEwseRz57R5zjR/CWsdEOHH6NhWbNl97k+U1w6dSjqIOC7kv08tyzmM30FzIilSDtE5HdL/A=="
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "Hhaw6DKZHiR+vgOdIqvndfUntJhmDR7MjylUJ55EvWtDyJFLDf2eij8r9tcwXP35FLD+bVNNCO0+KIYuvJjNnA==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "3.3.3",
"System.Collections.Immutable": "6.0.0",
"System.Memory": "4.5.4",
"System.Reflection.Metadata": "5.0.0",
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"System.Text.Encoding.CodePages": "6.0.0",
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.CodeAnalysis.CSharp": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "0PU4a2h7L6N9SlF/oNHwj2A/+n0LK/7n6PEGvXyIZq8hc7r/TztB+47mhVLvapT6bWSV7nMT78cNxbQuC6tk6g==",
"dependencies": {
"Microsoft.CodeAnalysis.Common": "[4.3.0]"
}
},
"Microsoft.CodeAnalysis.CSharp.Workspaces": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "CH2kezeYUD9/+nGs7QZ6xpOqD6OH6000YkAyU8LbhqLp7W65Xb+HerBzDX9yfprmRwArlF887QhZd8nW6enHIg==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.CodeAnalysis.CSharp": "[4.3.0]",
"Microsoft.CodeAnalysis.Common": "[4.3.0]",
"Microsoft.CodeAnalysis.Workspaces.Common": "[4.3.0]"
}
},
"Microsoft.CodeAnalysis.Workspaces.Common": {
"type": "Transitive",
"resolved": "4.3.0",
"contentHash": "oFF7lU3dQIeEbAVF6Qq/YEA4jvys3oQKkDezP8NcQTFgD8uRUiIA4NimRxANaWxK2n2PT4DAQspIOtrAE2hSdA==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.Bcl.AsyncInterfaces": "6.0.0",
"Microsoft.CodeAnalysis.Common": "[4.3.0]",
"System.Composition": "6.0.0",
"System.IO.Pipelines": "6.0.3"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Transitive",
"resolved": "8.0.1",
@ -196,17 +251,117 @@
"resolved": "8.0.11",
"contentHash": "UYSbAkNGTWVUne3I04/9IRQel3Bt1Ww6Y5cjvZEZ89rWhBD1yWu7YDotvQS62V6mgSfFaXXPGrCUm1VG824QXw=="
},
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Composition": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "d7wMuKQtfsxUa7S13tITC8n1cQzewuhD5iDjZtK2prwFfKVzdYtgrTHgjaV03Zq7feGQ5gkP85tJJntXwInsJA==",
"dependencies": {
"System.Composition.AttributedModel": "6.0.0",
"System.Composition.Convention": "6.0.0",
"System.Composition.Hosting": "6.0.0",
"System.Composition.Runtime": "6.0.0",
"System.Composition.TypedParts": "6.0.0"
}
},
"System.Composition.AttributedModel": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "WK1nSDLByK/4VoC7fkNiFuTVEiperuCN/Hyn+VN30R+W2ijO1d0Z2Qm0ScEl9xkSn1G2MyapJi8xpf4R8WRa/w=="
},
"System.Composition.Convention": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "XYi4lPRdu5bM4JVJ3/UIHAiG6V6lWWUlkhB9ab4IOq0FrRsp0F4wTyV4Dj+Ds+efoXJ3qbLqlvaUozDO7OLeXA==",
"dependencies": {
"System.Composition.AttributedModel": "6.0.0"
}
},
"System.Composition.Hosting": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "w/wXjj7kvxuHPLdzZ0PAUt++qJl03t7lENmb2Oev0n3zbxyNULbWBlnd5J5WUMMv15kg5o+/TCZFb6lSwfaUUQ==",
"dependencies": {
"System.Composition.Runtime": "6.0.0"
}
},
"System.Composition.Runtime": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "qkRH/YBaMPTnzxrS5RDk1juvqed4A6HOD/CwRcDGyPpYps1J27waBddiiq1y93jk2ZZ9wuA/kynM+NO0kb3PKg=="
},
"System.Composition.TypedParts": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "iUR1eHrL8Cwd82neQCJ00MpwNIBs4NZgXzrPqx8NJf/k4+mwBO0XCRmHYJT4OLSwDDqh5nBLJWkz5cROnrGhRA==",
"dependencies": {
"System.Composition.AttributedModel": "6.0.0",
"System.Composition.Hosting": "6.0.0",
"System.Composition.Runtime": "6.0.0"
}
},
"System.IO.Pipelines": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw=="
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
},
"System.Text.Encoding.CodePages": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
},
"ZXing.Net": {
"type": "Transitive",
"resolved": "0.16.9",
"contentHash": "7WaVMHklpT3Ye2ragqRIwlFRsb6kOk63BOGADV0fan3ulVfGLUYkDi5yNUsZS/7FVNkWbtHAlDLmu4WnHGfqvQ=="
},
"sourcecoderules": {
"type": "Project",
"dependencies": {
"Microsoft.CodeAnalysis.CSharp": "[4.3.0, )",
"Microsoft.CodeAnalysis.CSharp.Workspaces": "[4.3.0, )"
}
}
},
"net8.0/osx-arm64": {}
"net8.0/osx-arm64": {
"System.Text.Encoding.CodePages": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
}
}
}
}

View File

@ -6,4 +6,5 @@
- Added an agent to validate whether a retrieval context makes sense for the given prompt. This preview feature is hidden behind the RAG feature flag.
- Added a generic RAG process to integrate possibly any data in your chats. Although the generic RAG process is now implemented, the retrieval part is working only with external data sources using the ERI interface. That means that you could integrate your company's data from the corporate network by now. The retrieval process for your local data is still under development and will take several weeks to be released. In order to use data through ERI, you (or your company) have to develop an ERI server. You might use the ERI server assistant within AI Studio to do so. This preview feature is hidden behind the RAG feature flag.
- Improved confidence card for small spaces.
- Improved data security by enforcing provider filtering based on the chosen confidence level. To ensure this in the future, source code analyzers have been added to warn developers about insecure code.
- Fixed a bug in which 'APP_SETTINGS' appeared as a valid destination in the "send to" menu.

View File

@ -0,0 +1,7 @@
## Release 1.0
### New Rules
Rule ID | Category | Severity | Notes
-----------|----------|----------|------------------------
MWAIS0001 | Usage | Error | ProviderAccessAnalyzer

View File

@ -0,0 +1,10 @@
### New Rules
Rule ID | Category | Severity | Notes
---------|----------|----------|-------
### Changed Rules
Rule ID | New Category | New Severity | Old Category | Old Severity | Notes
---------|--------------|--------------|--------------|--------------|-------

View File

@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace SourceCodeRules;
#pragma warning disable RS1038
[DiagnosticAnalyzer(LanguageNames.CSharp)]
#pragma warning restore RS1038
public class ProviderAccessAnalyzer : DiagnosticAnalyzer
{
private const string DIAGNOSTIC_ID = $"{Tools.ID_PREFIX}0001";
private static readonly string TITLE = "Direct access to `Providers` is not allowed";
private static readonly string MESSAGE_FORMAT = "Direct access to `SettingsManager.ConfigurationData.Providers` is not allowed. Instead, use APIs like `SettingsManager.GetPreselectedProvider`, etc.";
private static readonly string DESCRIPTION = MESSAGE_FORMAT;
private const string CATEGORY = "Usage";
private static readonly DiagnosticDescriptor RULE = new(DIAGNOSTIC_ID, TITLE, MESSAGE_FORMAT, CATEGORY, DiagnosticSeverity.Error, isEnabledByDefault: true, description: DESCRIPTION);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(RULE);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(this.AnalyzeMemberAccess, SyntaxKind.SimpleMemberAccessExpression);
}
private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context)
{
var memberAccess = (MemberAccessExpressionSyntax)context.Node;
// Prüfen, ob wir eine Kette von Zugriffen haben, die auf "Providers" endet
if (memberAccess.Name.Identifier.Text != "Providers")
return;
// Den kompletten Zugriffspfad aufbauen
var fullPath = this.GetFullMemberAccessPath(memberAccess);
// Prüfen, ob der Pfad unserem verbotenen Muster entspricht
if (fullPath.EndsWith("ConfigurationData.Providers"))
{
var diagnostic = Diagnostic.Create(RULE, memberAccess.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
private string GetFullMemberAccessPath(ExpressionSyntax expression)
{
var parts = new List<string>();
while (expression is MemberAccessExpressionSyntax memberAccess)
{
parts.Add(memberAccess.Name.Identifier.Text);
expression = memberAccess.Expression;
}
if (expression is IdentifierNameSyntax identifier)
parts.Add(identifier.Identifier.Text);
parts.Reverse();
return string.Join(".", parts);
}
}

View File

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
<RootNamespace>SourceCodeRules</RootNamespace>
<AssemblyName>SourceCodeRules</AssemblyName>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
namespace SourceCodeRules;
public static class Tools
{
public const string ID_PREFIX = "MWAIS";
}