Expand advisory source catalog to 75 sources and add mirror management backend

Source catalog: add 28 sources across 6 new categories (Exploit, Container,
Hardware, ICS, PackageManager, additional CERTs) plus RU/CIS promotion and
threat intel frameworks. Register 25 new HTTP clients.

Source management API: 9 endpoints under /api/v1/sources for catalog browsing,
connectivity checks, and enable/disable controls.

Mirror domain API: 12 endpoints under /api/v1/mirror for domain CRUD, export
management, on-demand bundle generation, and connectivity testing.

Filter model: multi-value sourceVendor (comma-separated OR), sourceCategory
and sourceTag shorthand resolution via ResolveFilters(). Backward-compatible
with existing single-value filters. Deterministic query signatures.

Mirror export scheduler: BackgroundService with configurable refresh interval,
per-domain staleness detection, error isolation, and air-gap disable toggle.

VEX ingestion backoff: exponential backoff for failed sources (1hr → 24hr cap)
with jitter. New DB migration for tracking columns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
master
2026-03-15 13:26:52 +02:00
parent 27d27b1952
commit 3931b7e2cf
16 changed files with 2299 additions and 5 deletions

View File

@@ -35,6 +35,7 @@ using StellaOps.Concelier.Core.Observations;
using StellaOps.Concelier.Core.Orchestration;
using StellaOps.Concelier.Core.Raw;
using StellaOps.Concelier.Core.Signals;
using StellaOps.Concelier.Core.Sources;
using StellaOps.Concelier.Merge;
using StellaOps.Concelier.Merge.Services;
using StellaOps.Concelier.Models;
@@ -55,6 +56,7 @@ using StellaOps.Concelier.WebService.Results;
using StellaOps.Concelier.WebService.Services;
using StellaOps.Concelier.WebService.Telemetry;
using StellaOps.Configuration;
using StellaOps.Excititor.Core;
using StellaOps.Plugin.DependencyInjection;
using StellaOps.Plugin.Hosting;
using StellaOps.Provenance;
@@ -557,6 +559,20 @@ builder.Services.AddConcelierOrchestrationServices();
// Register federation snapshot coordination services (SPRINT_20260208_035)
builder.Services.AddConcelierFederationServices();
// Register advisory source registry and connectivity services
builder.Services.AddSourcesRegistry(builder.Configuration);
// Mirror domain management (in-memory store, future: DB-backed)
builder.Services.AddSingleton<InMemoryMirrorDomainStore>();
builder.Services.AddSingleton<IMirrorDomainStore>(sp => sp.GetRequiredService<InMemoryMirrorDomainStore>());
builder.Services.AddSingleton<IMirrorConfigStore>(sp => sp.GetRequiredService<InMemoryMirrorDomainStore>());
builder.Services.Configure<MirrorConfigOptions>(builder.Configuration.GetSection("Mirror"));
builder.Services.AddHttpClient("MirrorTest");
// Mirror distribution options binding and export scheduler (background bundle refresh, TASK-006b)
builder.Services.Configure<MirrorDistributionOptions>(builder.Configuration.GetSection(MirrorDistributionOptions.SectionName));
builder.Services.AddHostedService<MirrorExportScheduler>();
var features = concelierOptions.Features ?? new ConcelierOptions.FeaturesOptions();
if (!features.NoMergeEnabled)
@@ -931,6 +947,7 @@ app.MapConcelierMirrorEndpoints(authorityConfigured, enforceAuthority);
// Canonical advisory endpoints (Sprint 8200.0012.0003)
app.MapCanonicalAdvisoryEndpoints();
app.MapAdvisorySourceEndpoints();
app.MapSourceManagementEndpoints();
app.MapInterestScoreEndpoints();
// Federation endpoints for site-to-site bundle sync
@@ -945,6 +962,9 @@ app.MapFeedSnapshotEndpoints();
// Feed mirror management, bundles, version locks, offline status
app.MapFeedMirrorManagementEndpoints();
// Mirror domain management CRUD endpoints
app.MapMirrorDomainManagementEndpoints();
app.MapGet("/.well-known/openapi", ([FromServices] OpenApiDiscoveryDocumentProvider provider, HttpContext context) =>
{
var (payload, etag) = provider.GetDocument();