// -----------------------------------------------------------------------------
// 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;
}
}