Gaps fill up, fixes, ui restructuring

This commit is contained in:
master
2026-02-19 22:10:54 +02:00
parent b5829dce5c
commit 04cacdca8a
331 changed files with 42859 additions and 2174 deletions

View File

@@ -121,6 +121,18 @@ public static class IntegrationEndpoints
.WithName("CheckIntegrationHealth")
.WithDescription("Performs a health check on an integration.");
// Impact map
group.MapGet("/{id:guid}/impact", async (
[FromServices] IntegrationService service,
Guid id,
CancellationToken cancellationToken) =>
{
var result = await service.GetImpactAsync(id, cancellationToken);
return result is null ? Results.NotFound() : Results.Ok(result);
})
.WithName("GetIntegrationImpact")
.WithDescription("Returns affected workflows and severity impact for an integration.");
// Get supported providers
group.MapGet("/providers", ([FromServices] IntegrationService service) =>
{

View File

@@ -269,6 +269,31 @@ public sealed class IntegrationService
result.Duration);
}
public async Task<IntegrationImpactResponse?> GetImpactAsync(Guid id, CancellationToken cancellationToken = default)
{
var integration = await _repository.GetByIdAsync(id, cancellationToken);
if (integration is null)
{
return null;
}
var impactedWorkflows = BuildImpactedWorkflows(integration)
.OrderBy(workflow => workflow.Workflow, StringComparer.Ordinal)
.ToList();
var blockingCount = impactedWorkflows.Count(workflow => workflow.Blocking);
return new IntegrationImpactResponse(
IntegrationId: integration.Id,
IntegrationName: integration.Name,
Type: integration.Type,
Provider: integration.Provider,
Status: integration.Status,
Severity: DetermineSeverity(integration.Status, blockingCount),
BlockingWorkflowCount: blockingCount,
TotalWorkflowCount: impactedWorkflows.Count,
ImpactedWorkflows: impactedWorkflows);
}
public IReadOnlyList<ProviderInfo> GetSupportedProviders()
{
return _pluginLoader.Plugins.Select(p => new ProviderInfo(
@@ -277,6 +302,55 @@ public sealed class IntegrationService
p.Provider)).ToList();
}
private static IReadOnlyList<ImpactedWorkflow> BuildImpactedWorkflows(Integration integration)
{
var blockedByStatus = integration.Status is IntegrationStatus.Failed or IntegrationStatus.Disabled or IntegrationStatus.Archived;
return integration.Type switch
{
IntegrationType.Registry =>
[
new ImpactedWorkflow("bundle-materialization", "release-control", blockedByStatus, "Container digest fetch and verification path.", "restore-registry-connectivity"),
new ImpactedWorkflow("sbom-attachment", "evidence", blockedByStatus, "SBOM/image digest correlation during pack generation.", "re-run-bundle-sync"),
],
IntegrationType.Scm =>
[
new ImpactedWorkflow("bundle-changelog", "release-control", blockedByStatus, "Repository changelog enrichment for bundle versions.", "reconnect-scm-app"),
new ImpactedWorkflow("policy-drift-audit", "administration", blockedByStatus, "Policy governance change audit extraction.", "refresh-scm-access-token"),
],
IntegrationType.CiCd =>
[
new ImpactedWorkflow("promotion-preflight", "release-control", blockedByStatus, "Deployment signal and gate preflight signal stream.", "revalidate-ci-runner-credentials"),
new ImpactedWorkflow("ops-job-health", "platform-ops", blockedByStatus, "Pipeline lag/health insights for nightly report.", "replay-latest-ci-webhooks"),
],
IntegrationType.RepoSource =>
[
new ImpactedWorkflow("dependency-resolution", "security-risk", blockedByStatus, "Package advisory resolution and normalization.", "verify-repository-mirror"),
new ImpactedWorkflow("hot-lookup-projection", "security-risk", blockedByStatus, "Hot-lookup enrichment for findings explorer.", "resync-package-index"),
],
IntegrationType.RuntimeHost =>
[
new ImpactedWorkflow("runtime-reachability", "security-risk", blockedByStatus, "Runtime witness ingestion for reachability confidence.", "restart-runtime-agent"),
new ImpactedWorkflow("ops-confidence", "platform-ops", blockedByStatus, "Data-confidence score for approvals and dashboard.", "clear-runtime-dlq"),
],
IntegrationType.FeedMirror =>
[
new ImpactedWorkflow("advisory-freshness", "security-risk", blockedByStatus, "Advisory source freshness and conflict views.", "refresh-feed-mirror"),
new ImpactedWorkflow("rescore-pipeline", "platform-ops", blockedByStatus, "Nightly rescoring jobs and stale SBOM remediation.", "trigger-feed-replay"),
],
_ => []
};
}
private static string DetermineSeverity(IntegrationStatus status, int blockingCount)
{
if (status is IntegrationStatus.Failed or IntegrationStatus.Disabled or IntegrationStatus.Archived)
{
return "high";
}
return blockingCount > 0 ? "medium" : "low";
}
private static IntegrationConfig BuildConfig(Integration integration, string? resolvedSecret)
{
IReadOnlyDictionary<string, object>? extendedConfig = null;
@@ -321,3 +395,21 @@ public sealed class IntegrationService
/// Information about a supported provider.
/// </summary>
public sealed record ProviderInfo(string Name, IntegrationType Type, IntegrationProvider Provider);
public sealed record IntegrationImpactResponse(
Guid IntegrationId,
string IntegrationName,
IntegrationType Type,
IntegrationProvider Provider,
IntegrationStatus Status,
string Severity,
int BlockingWorkflowCount,
int TotalWorkflowCount,
IReadOnlyList<ImpactedWorkflow> ImpactedWorkflows);
public sealed record ImpactedWorkflow(
string Workflow,
string Domain,
bool Blocking,
string Impact,
string RecommendedAction);