Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions CognitiveMesh.sln
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResearchAnalysis", "src\Bus
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ValueGeneration", "src\BusinessApplications\ValueGeneration\ValueGeneration.csproj", "{55ABF7B2-A718-4A0D-9B90-479D9D549E7D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyStore", "src\FoundationLayer\PolicyStore\PolicyStore.csproj", "{A0B1C2D3-E4F5-6789-ABCD-100000000001}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SelfHealing", "src\AgencyLayer\SelfHealing\SelfHealing.csproj", "{A0B1C2D3-E4F5-6789-ABCD-100000000002}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FoundationLayer", "FoundationLayer", "{A0B1C2D3-E4F5-6789-ABCD-100000000003}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyStore.Tests", "tests\FoundationLayer\PolicyStore\PolicyStore.Tests.csproj", "{A0B1C2D3-E4F5-6789-ABCD-100000000004}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SelfHealing.Tests", "tests\AgencyLayer\SelfHealing\SelfHealing.Tests.csproj", "{A0B1C2D3-E4F5-6789-ABCD-100000000005}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -559,6 +569,54 @@ Global
{55ABF7B2-A718-4A0D-9B90-479D9D549E7D}.Release|x64.Build.0 = Release|Any CPU
{55ABF7B2-A718-4A0D-9B90-479D9D549E7D}.Release|x86.ActiveCfg = Release|Any CPU
{55ABF7B2-A718-4A0D-9B90-479D9D549E7D}.Release|x86.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Debug|x64.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Debug|x64.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Debug|x86.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Debug|x86.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Release|Any CPU.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Release|x64.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Release|x64.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Release|x86.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000001}.Release|x86.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Debug|x64.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Debug|x64.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Debug|x86.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Debug|x86.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Release|Any CPU.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Release|x64.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Release|x64.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Release|x86.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000002}.Release|x86.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Debug|x64.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Debug|x64.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Debug|x86.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Debug|x86.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Release|Any CPU.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Release|x64.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Release|x64.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Release|x86.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000004}.Release|x86.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Debug|x64.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Debug|x64.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Debug|x86.ActiveCfg = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Debug|x86.Build.0 = Debug|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Release|Any CPU.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Release|x64.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Release|x64.Build.0 = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Release|x86.ActiveCfg = Release|Any CPU
{A0B1C2D3-E4F5-6789-ABCD-100000000005}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -607,5 +665,10 @@ Global
{4F909B40-E2A4-4344-BEF8-55555CEEA7A6} = {DDB468F9-AACD-4EAF-9EBB-8DB0972963EB}
{F9A0F61C-2CE5-4795-9040-9B01A6EC98B2} = {DDB468F9-AACD-4EAF-9EBB-8DB0972963EB}
{55ABF7B2-A718-4A0D-9B90-479D9D549E7D} = {DDB468F9-AACD-4EAF-9EBB-8DB0972963EB}
{A0B1C2D3-E4F5-6789-ABCD-100000000001} = {DDB468F9-AACD-4EAF-9EBB-8DB0972963EB}
{A0B1C2D3-E4F5-6789-ABCD-100000000002} = {DDB468F9-AACD-4EAF-9EBB-8DB0972963EB}
{A0B1C2D3-E4F5-6789-ABCD-100000000003} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{A0B1C2D3-E4F5-6789-ABCD-100000000004} = {A0B1C2D3-E4F5-6789-ABCD-100000000003}
{A0B1C2D3-E4F5-6789-ABCD-100000000005} = {3C4D5E6F-7A8B-9C0D-1E2F-A3B4C5D6E7F8}
EndGlobalSection
EndGlobal
2 changes: 2 additions & 0 deletions src/AgencyLayer/AgencyLayer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<Compile Remove="RealTime\**" />
<Compile Remove="RefactoringAgents\**" />
<Compile Remove="SecurityAgents\**" />
<Compile Remove="SelfHealing\**" />
<Compile Remove="ToolIntegration\**" />
</ItemGroup>

Expand Down Expand Up @@ -53,6 +54,7 @@
<ProjectReference Include=".\ToolIntegration\ToolIntegration.csproj" />
<ProjectReference Include=".\CognitiveSandwich\CognitiveSandwich.csproj" />
<ProjectReference Include=".\CognitiveSovereignty\CognitiveSovereignty.csproj" />
<ProjectReference Include=".\SelfHealing\SelfHealing.csproj" />
</ItemGroup>

</Project>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Microsoft.Extensions.Logging;

using CognitiveMesh.AgencyLayer.SelfHealing.Ports;
using CognitiveMesh.FoundationLayer.PolicyStore.Models;
using CognitiveMesh.FoundationLayer.PolicyStore.Ports;

namespace CognitiveMesh.AgencyLayer.SelfHealing.Engines;

/// <summary>
/// Decision engine that resolves remediation actions by consulting the policy store.
/// </summary>
public sealed class RemediationPolicyDecisionEngine : IRemediationDecisionPort
{
private readonly IRemediationPolicyPort _policyPort;
private readonly ILogger<RemediationPolicyDecisionEngine> _logger;

/// <summary>
/// Initialises a new instance of the <see cref="RemediationPolicyDecisionEngine"/> class.
/// </summary>
/// <param name="policyPort">The remediation policy port.</param>
/// <param name="logger">The logger instance.</param>
/// <exception cref="ArgumentNullException">Thrown when any argument is <see langword="null"/>.</exception>
public RemediationPolicyDecisionEngine(
IRemediationPolicyPort policyPort,
ILogger<RemediationPolicyDecisionEngine> logger)
{
ArgumentNullException.ThrowIfNull(policyPort);
ArgumentNullException.ThrowIfNull(logger);

_policyPort = policyPort;
_logger = logger;
}

/// <inheritdoc />
public async Task<(RemediationAction AllowedActions, Dictionary<string, double> RankingWeights)> GetAllowedActionsAsync(
string incidentCategory,
string severity,
CancellationToken ct = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(incidentCategory);
ArgumentException.ThrowIfNullOrWhiteSpace(severity);

var policy = await _policyPort.GetPolicyAsync(incidentCategory, severity, ct).ConfigureAwait(false);

_logger.LogInformation(
"Resolved policy {PolicyId} v{Version} for {Category}/{Severity} with actions {Actions}",
policy.Id,
policy.Version,
incidentCategory,
severity,
policy.AllowedActions);

return (policy.AllowedActions, policy.RankingWeights);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.Extensions.DependencyInjection;

using CognitiveMesh.AgencyLayer.SelfHealing.Engines;
using CognitiveMesh.AgencyLayer.SelfHealing.Ports;

namespace CognitiveMesh.AgencyLayer.SelfHealing.Extensions;

/// <summary>
/// Extension methods for registering self-healing services with the dependency injection container.
/// </summary>
public static class SelfHealingServiceExtensions
{
/// <summary>
/// Adds self-healing services, including the remediation policy decision engine,
/// to the specified <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The service collection to configure.</param>
/// <returns>The same <see cref="IServiceCollection"/> for chaining.</returns>
public static IServiceCollection AddSelfHealingServices(this IServiceCollection services)
{
ArgumentNullException.ThrowIfNull(services);

services.AddSingleton<IRemediationDecisionPort, RemediationPolicyDecisionEngine>();

return services;
}
}
25 changes: 25 additions & 0 deletions src/AgencyLayer/SelfHealing/Ports/IRemediationDecisionPort.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using CognitiveMesh.FoundationLayer.PolicyStore.Models;

namespace CognitiveMesh.AgencyLayer.SelfHealing.Ports;

/// <summary>
/// Defines the port for obtaining remediation decisions based on incident context.
/// </summary>
public interface IRemediationDecisionPort
{
/// <summary>
/// Retrieves the allowed remediation actions and their ranking weights for the
/// specified incident category and severity.
/// </summary>
/// <param name="incidentCategory">The category of the incident.</param>
/// <param name="severity">The severity level of the incident.</param>
/// <param name="ct">A cancellation token.</param>
/// <returns>
/// A tuple containing the allowed <see cref="RemediationAction"/> flags and
/// a dictionary of ranking weights keyed by action name.
/// </returns>
Task<(RemediationAction AllowedActions, Dictionary<string, double> RankingWeights)> GetAllowedActionsAsync(
string incidentCategory,
string severity,
CancellationToken ct = default);
}
20 changes: 20 additions & 0 deletions src/AgencyLayer/SelfHealing/SelfHealing.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\FoundationLayer\PolicyStore\PolicyStore.csproj" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions src/FoundationLayer/FoundationLayer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<ProjectReference Include=".\Security\Security.csproj" />
<ProjectReference Include=".\NISTEvidence\NISTEvidence.csproj" />
<ProjectReference Include=".\EvidenceArtifacts\EvidenceArtifacts.csproj" />
<ProjectReference Include=".\PolicyStore\PolicyStore.csproj" />
</ItemGroup>

</Project>
Loading
Loading