Restructure solution layout by module
This commit is contained in:
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user