Restructure solution layout by module

This commit is contained in:
master
2025-10-28 15:10:40 +02:00
parent 95daa159c4
commit d870da18ce
4103 changed files with 192899 additions and 187024 deletions

View File

@@ -0,0 +1,79 @@
using System;
using StellaOps.Concelier.Connector.Common.Cursors;
namespace StellaOps.Concelier.Connector.CertCc.Configuration;
/// <summary>
/// Connector options governing CERT/CC fetch cadence and API endpoints.
/// </summary>
public sealed class CertCcOptions
{
public const string HttpClientName = "certcc";
/// <summary>
/// Root URI for the VINCE Vulnerability Notes API (must end with a slash).
/// </summary>
public Uri BaseApiUri { get; set; } = new("https://www.kb.cert.org/vuls/api/", UriKind.Absolute);
/// <summary>
/// Sliding window settings controlling which summary endpoints are requested.
/// </summary>
public TimeWindowCursorOptions SummaryWindow { get; set; } = new()
{
WindowSize = TimeSpan.FromDays(30),
Overlap = TimeSpan.FromDays(3),
InitialBackfill = TimeSpan.FromDays(365),
MinimumWindowSize = TimeSpan.FromDays(1),
};
/// <summary>
/// Maximum number of monthly summary endpoints to request in a single plan.
/// </summary>
public int MaxMonthlySummaries { get; set; } = 6;
/// <summary>
/// Maximum number of vulnerability notes (detail bundles) to process per fetch pass.
/// </summary>
public int MaxNotesPerFetch { get; set; } = 25;
/// <summary>
/// Optional delay inserted between successive detail requests to respect upstream throttling.
/// </summary>
public TimeSpan DetailRequestDelay { get; set; } = TimeSpan.FromMilliseconds(100);
/// <summary>
/// When disabled, parse/map stages skip detail mapping—useful for dry runs or migration staging.
/// </summary>
public bool EnableDetailMapping { get; set; } = true;
public void Validate()
{
if (BaseApiUri is null || !BaseApiUri.IsAbsoluteUri)
{
throw new InvalidOperationException("CertCcOptions.BaseApiUri must be an absolute URI.");
}
if (!BaseApiUri.AbsoluteUri.EndsWith("/", StringComparison.Ordinal))
{
throw new InvalidOperationException("CertCcOptions.BaseApiUri must end with a trailing slash.");
}
SummaryWindow ??= new TimeWindowCursorOptions();
SummaryWindow.EnsureValid();
if (MaxMonthlySummaries <= 0)
{
throw new InvalidOperationException("CertCcOptions.MaxMonthlySummaries must be positive.");
}
if (MaxNotesPerFetch <= 0)
{
throw new InvalidOperationException("CertCcOptions.MaxNotesPerFetch must be positive.");
}
if (DetailRequestDelay < TimeSpan.Zero)
{
throw new InvalidOperationException("CertCcOptions.DetailRequestDelay cannot be negative.");
}
}
}