// ----------------------------------------------------------------------------- // VexGateServiceCollectionExtensions.cs // Sprint: SPRINT_20260106_003_002_SCANNER_vex_gate_service // Task: T028 - Add gate policy to tenant configuration // Description: Service collection extensions for registering VEX gate services. // ----------------------------------------------------------------------------- using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace StellaOps.Scanner.Gate; /// /// Extension methods for registering VEX gate services. /// public static class VexGateServiceCollectionExtensions { /// /// Adds VEX gate services with configuration from the specified section. /// /// The service collection. /// The configuration root. /// The service collection for chaining. public static IServiceCollection AddVexGate( this IServiceCollection services, IConfiguration configuration) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(configuration); // Bind and validate options services.AddOptions() .Bind(configuration.GetSection(VexGateOptions.SectionName)) .ValidateDataAnnotations() .ValidateOnStart(); // Register policy from options services.AddSingleton(sp => { var options = sp.GetRequiredService>(); if (!options.Value.Enabled) { // Return a permissive policy when disabled return new VexGatePolicy { DefaultDecision = VexGateDecision.Pass, Rules = [], }; } return options.Value.ToPolicy(); }); // Register core services services.AddSingleton(); // Register caching with configured limits services.AddSingleton(sp => { var options = sp.GetRequiredService>(); return new MemoryCache(new MemoryCacheOptions { SizeLimit = options.Value.Cache.MaxEntries, }); }); // Register VEX gate service services.AddSingleton(); return services; } /// /// Adds VEX gate services with explicit options. /// /// The service collection. /// The options configuration action. /// The service collection for chaining. public static IServiceCollection AddVexGate( this IServiceCollection services, Action configureOptions) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(configureOptions); // Configure and validate options services.AddOptions() .Configure(configureOptions) .ValidateDataAnnotations() .ValidateOnStart(); // Register policy from options services.AddSingleton(sp => { var options = sp.GetRequiredService>(); if (!options.Value.Enabled) { return new VexGatePolicy { DefaultDecision = VexGateDecision.Pass, Rules = [], }; } return options.Value.ToPolicy(); }); // Register core services services.AddSingleton(); // Register caching with configured limits services.AddSingleton(sp => { var options = sp.GetRequiredService>(); return new MemoryCache(new MemoryCacheOptions { SizeLimit = options.Value.Cache.MaxEntries, }); }); // Register VEX gate service services.AddSingleton(); return services; } /// /// Adds VEX gate services with default policy. /// /// The service collection. /// The service collection for chaining. public static IServiceCollection AddVexGateWithDefaultPolicy(this IServiceCollection services) { ArgumentNullException.ThrowIfNull(services); // Configure with default options services.AddOptions() .Configure(options => { options.Enabled = true; var defaultPolicy = VexGatePolicy.Default; options.DefaultDecision = defaultPolicy.DefaultDecision.ToString(); options.Rules = defaultPolicy.Rules .Select(VexGateRuleOptions.FromRule) .ToList(); }) .ValidateDataAnnotations() .ValidateOnStart(); // Register default policy services.AddSingleton(_ => VexGatePolicy.Default); // Register core services services.AddSingleton(); // Register caching with default limits services.AddSingleton(_ => new MemoryCache(new MemoryCacheOptions { SizeLimit = 10000, })); // Register VEX gate service services.AddSingleton(); return services; } }