using System.IO; using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using StellaOps.Plugin; using StellaOps.Excititor.Connectors.Abstractions; using StellaOps.Excititor.Core; using StellaOps.Excititor.Core.Aoc; using StellaOps.Excititor.Core.Storage; using StellaOps.Excititor.Core.Orchestration; using StellaOps.Excititor.Formats.CSAF; using StellaOps.Excititor.Formats.CycloneDX; using StellaOps.Excititor.Formats.OpenVEX; using StellaOps.Excititor.Persistence.Extensions; using StellaOps.Excititor.Worker.Auth; using StellaOps.Excititor.Worker.Options; using StellaOps.Excititor.Worker.Orchestration; using StellaOps.Excititor.Worker.Plugins; using StellaOps.Excititor.Worker.Scheduling; using StellaOps.Excititor.Worker.Signature; using StellaOps.Excititor.Attestation.Extensions; using StellaOps.Excititor.Attestation.Verification; using StellaOps.IssuerDirectory.Client; var builder = Host.CreateApplicationBuilder(args); var services = builder.Services; var configuration = builder.Configuration; var workerConfig = configuration.GetSection("Excititor:Worker"); var workerConfigSnapshot = workerConfig.Get() ?? new VexWorkerOptions(); services.AddOptions() .Bind(workerConfig) .ValidateOnStart(); services.Configure(configuration.GetSection("Excititor:Worker:Plugins")); services.Configure(configuration.GetSection("Excititor:Authority")); services.AddSingleton, TenantAuthorityOptionsValidator>(); services.PostConfigure(options => { if (options.DisableConsensus) { options.Refresh.Enabled = false; } }); // VEX connectors are loaded via plugin catalog below // Direct connector registration removed in favor of plugin-based loading services.AddOptions() .Bind(configuration.GetSection("Excititor:Storage")) .ValidateOnStart(); services.AddExcititorPersistence(configuration); services.TryAddSingleton(); services.TryAddScoped(); services.TryAddSingleton(); services.AddCsafNormalizer(); services.AddCycloneDxNormalizer(); services.AddOpenVexNormalizer(); services.AddSingleton(); services.AddVexAttestation(); services.Configure(configuration.GetSection("Excititor:Attestation:Verification")); var issuerDirectorySection = configuration.GetSection("Excititor:IssuerDirectory"); if (issuerDirectorySection.Exists()) { services.AddIssuerDirectoryClient(issuerDirectorySection); } else { services.AddIssuerDirectoryClient(configuration); } services.PostConfigure(options => { // Workers operate in offline-first environments; allow verification to succeed without Rekor. options.AllowOfflineTransparency = true; if (!configuration.GetSection("Excititor:Attestation:Verification").Exists()) { options.RequireTransparencyLog = false; } }); services.AddExcititorAocGuards(); services.AddSingleton, VexWorkerOptionsValidator>(); services.AddSingleton(TimeProvider.System); services.TryAddSingleton(); services.PostConfigure(options => { if (!options.Providers.Any(provider => string.Equals(provider.ProviderId, "excititor:redhat", StringComparison.OrdinalIgnoreCase))) { options.Providers.Add(new VexWorkerProviderOptions { ProviderId = "excititor:redhat", }); } }); // Load VEX connector plugins services.AddSingleton(); services.AddSingleton(provider => provider.GetRequiredService().Load().Catalog); // Orchestrator worker SDK integration services.AddOptions() .Bind(configuration.GetSection("Excititor:Worker:Orchestrator")) .ValidateOnStart(); services.AddHttpClient(TenantAuthorityClientFactory.AuthorityClientName); services.AddHttpClient((provider, client) => { var opts = provider.GetRequiredService>().Value; if (opts.BaseAddress is not null) { client.BaseAddress = opts.BaseAddress; } client.Timeout = opts.RequestTimeout; }); services.AddSingleton(); services.AddSingleton(); services.AddHostedService(); if (!workerConfigSnapshot.DisableConsensus) { services.AddSingleton(); services.AddSingleton(static provider => provider.GetRequiredService()); services.AddHostedService(static provider => provider.GetRequiredService()); } services.AddSingleton(); var host = builder.Build(); await host.RunAsync(); // Make Program class file-scoped to prevent it from being exposed to referencing assemblies file sealed partial class Program;