using System; using System.Collections.Generic; using System.Text.Json.Serialization; using StellaOps.Configuration; namespace StellaOps.Concelier.WebService.Options; public sealed class ConcelierOptions { [Obsolete("Legacy storage has been removed; use PostgresStorage.")] public LegacyStorageOptions LegacyStorage { get; set; } = new(); public PostgresStorageOptions? PostgresStorage { get; set; } = new PostgresStorageOptions { Enabled = true }; public PluginOptions Plugins { get; set; } = new(); public TelemetryOptions Telemetry { get; set; } = new(); public AuthorityOptions Authority { get; set; } = new(); public MirrorOptions Mirror { get; set; } = new(); public FeaturesOptions Features { get; set; } = new(); public AdvisoryChunkOptions AdvisoryChunks { get; set; } = new(); public EvidenceBundleOptions Evidence { get; set; } = new(); public StellaOpsCryptoOptions Crypto { get; } = new(); /// /// Air-gap mode configuration. /// Per CONCELIER-WEB-AIRGAP-56-001. /// public AirGapOptions AirGap { get; set; } = new(); [Obsolete("Legacy storage has been removed; use PostgresStorage.")] public sealed class LegacyStorageOptions { public string Driver { get; set; } = "postgres"; public string Dsn { get; set; } = string.Empty; public string? Database { get; set; } public int CommandTimeoutSeconds { get; set; } = 30; } /// /// PostgreSQL storage options for the LNM linkset cache. /// public sealed class PostgresStorageOptions { /// /// Enable PostgreSQL storage for LNM linkset cache. /// public bool Enabled { get; set; } /// /// PostgreSQL connection string. /// public string ConnectionString { get; set; } = string.Empty; /// /// Command timeout in seconds. Default is 30 seconds. /// public int CommandTimeoutSeconds { get; set; } = 30; /// /// Maximum number of connections in the pool. Default is 100. /// public int MaxPoolSize { get; set; } = 100; /// /// Minimum number of connections in the pool. Default is 1. /// public int MinPoolSize { get; set; } = 1; /// /// Connection idle lifetime in seconds. Default is 300 seconds (5 minutes). /// public int ConnectionIdleLifetimeSeconds { get; set; } = 300; /// /// Enable connection pooling. Default is true. /// public bool Pooling { get; set; } = true; /// /// Schema name for LNM tables. Default is "vuln". /// public string SchemaName { get; set; } = "vuln"; /// /// Enable automatic migration on startup. Default is false for production safety. /// public bool AutoMigrate { get; set; } /// /// Path to SQL migration files. Required if AutoMigrate is true. /// public string? MigrationsPath { get; set; } } public sealed class PluginOptions { public string? BaseDirectory { get; set; } public string? Directory { get; set; } public IList SearchPatterns { get; set; } = new List(); } public sealed class TelemetryOptions { public bool Enabled { get; set; } = true; public bool EnableTracing { get; set; } = true; public bool EnableMetrics { get; set; } = true; public bool EnableLogging { get; set; } = true; public string MinimumLogLevel { get; set; } = "Information"; public string? ServiceName { get; set; } public string? OtlpEndpoint { get; set; } public IDictionary OtlpHeaders { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); public IDictionary ResourceAttributes { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); public bool ExportConsole { get; set; } } public sealed class AuthorityOptions { public bool Enabled { get; set; } public bool AllowAnonymousFallback { get; set; } = true; public string Issuer { get; set; } = string.Empty; public string? MetadataAddress { get; set; } public bool RequireHttpsMetadata { get; set; } = true; public int BackchannelTimeoutSeconds { get; set; } = 30; public int TokenClockSkewSeconds { get; set; } = 60; public IList Audiences { get; set; } = new List(); public IList RequiredScopes { get; set; } = new List(); public IList RequiredTenants { get; set; } = new List(); public IList BypassNetworks { get; set; } = new List(); public string? ClientId { get; set; } public string? ClientSecret { get; set; } public string? ClientSecretFile { get; set; } public string? TestSigningSecret { get; set; } public IList ClientScopes { get; set; } = new List(); public ResilienceOptions Resilience { get; set; } = new(); public sealed class ResilienceOptions { public bool? EnableRetries { get; set; } public IList RetryDelays { get; set; } = new List(); public bool? AllowOfflineCacheFallback { get; set; } public TimeSpan? OfflineCacheTolerance { get; set; } } } public sealed class MirrorOptions { public bool Enabled { get; set; } public string ExportRoot { get; set; } = System.IO.Path.Combine("exports", "json"); public string? ActiveExportId { get; set; } public string LatestDirectoryName { get; set; } = "latest"; public string MirrorDirectoryName { get; set; } = "mirror"; public bool RequireAuthentication { get; set; } public int MaxIndexRequestsPerHour { get; set; } = 600; public IList Domains { get; } = new List(); [JsonIgnore] public string ExportRootAbsolute { get; internal set; } = string.Empty; } public sealed class MirrorDomainOptions { public string Id { get; set; } = string.Empty; public string? DisplayName { get; set; } public bool RequireAuthentication { get; set; } public int MaxDownloadRequestsPerHour { get; set; } = 1200; } public sealed class FeaturesOptions { public bool NoMergeEnabled { get; set; } = true; public bool LnmShadowWrites { get; set; } = true; public IList MergeJobAllowlist { get; } = new List(); } public sealed class AdvisoryChunkOptions { public int DefaultChunkLimit { get; set; } = 200; public int MaxChunkLimit { get; set; } = 400; public int DefaultObservationLimit { get; set; } = 24; public int MaxObservationLimit { get; set; } = 48; public int DefaultMinimumLength { get; set; } = 64; public int MaxMinimumLength { get; set; } = 512; public int CacheDurationSeconds { get; set; } = 30; } public sealed class EvidenceBundleOptions { public bool Enabled { get; set; } = true; public string Root { get; set; } = System.IO.Path.Combine("out", "evidence", "bundles"); public string? DefaultManifestFileName { get; set; } = "manifest.json"; public string? DefaultTransparencyFileName { get; set; } = "transparency.json"; public string PipelineVersion { get; set; } = "git:unknown"; [JsonIgnore] public string RootAbsolute { get; internal set; } = string.Empty; } }