stabilizaiton work - projects rework for maintenanceability and ui livening

This commit is contained in:
master
2026-02-03 23:40:04 +02:00
parent 074ce117ba
commit 557feefdc3
3305 changed files with 186813 additions and 107843 deletions

View File

@@ -0,0 +1,15 @@
<?xml version='1.0' encoding='utf-8'?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,190 @@
// Copyright (c) StellaOps. All rights reserved.
// Licensed under BUSL-1.1. See LICENSE in the project root.
using Microsoft.Extensions.Configuration;
namespace StellaOps.Settings;
/// <summary>
/// POCO that holds resolved CORS settings for Stella Ops web services.
/// Supports a priority cascade: env vars → config keys → legacy env vars → legacy config keys → defaults.
/// </summary>
public sealed class StellaOpsCorsSettings
{
public bool Enabled { get; set; }
public string[] Origins { get; set; } = [];
// ── Primary env vars ───────────────────────────────────────────────
public const string EnvEnabled = "STELLAOPS_WEBSERVICES_CORS";
public const string EnvOrigin = "STELLAOPS_WEBSERVICES_CORS_ORIGIN";
// ── Primary config keys (appsettings.json / YAML) ──────────────────
public const string ConfigEnabled = "StellaOps:WebServices:Cors:Enabled";
public const string ConfigOrigin = "StellaOps:WebServices:Cors:Origin";
// ── Legacy (fallback) ──────────────────────────────────────────────
public const string LegacyEnvEnabled = "STELLAOPS_CORS_ENABLED";
public const string LegacyEnvOrigin = "STELLAOPS_CORS_ALLOWED_ORIGIN";
public const string LegacyConfigEnabled = "StellaOps:Cors:Enabled";
public const string LegacyConfigOrigin = "StellaOps:Cors:AllowedOrigin";
/// <summary>
/// Default origins used in Development when no explicit origin is configured.
/// </summary>
public static readonly string[] DefaultDevOrigins =
[
"https://stella-ops.local",
"https://stella-ops.local:10000",
"https://localhost:10000"
];
/// <summary>
/// Resolves CORS settings using a priority cascade:
/// env vars → config keys → legacy env vars → legacy config keys → built-in defaults.
/// </summary>
public static StellaOpsCorsSettings Resolve(IConfiguration configuration, bool isDevelopment)
{
return Resolve(configuration, isDevelopment, defaultEnabled: null, defaultOrigins: null, onNotConfigured: null);
}
/// <summary>
/// Resolves CORS settings with explicit default values used when no configuration source
/// provides a value (instead of the built-in defaults).
/// </summary>
/// <param name="configuration">Application configuration.</param>
/// <param name="isDevelopment">Whether the host is running in the Development environment.</param>
/// <param name="defaultEnabled">Default value for <see cref="Enabled"/> when no source provides a value.</param>
/// <param name="defaultOrigins">Default value for <see cref="Origins"/> when no source provides a value.</param>
public static StellaOpsCorsSettings Resolve(
IConfiguration configuration,
bool isDevelopment,
bool defaultEnabled,
string[] defaultOrigins)
{
ArgumentNullException.ThrowIfNull(defaultOrigins);
return Resolve(configuration, isDevelopment, (bool?)defaultEnabled, defaultOrigins, onNotConfigured: null);
}
/// <summary>
/// Resolves CORS settings with a callback that is invoked when the full cascade
/// finds no explicit configuration. The callback receives a settings object
/// populated with built-in defaults and may inspect or replace it.
/// </summary>
/// <param name="configuration">Application configuration.</param>
/// <param name="isDevelopment">Whether the host is running in the Development environment.</param>
/// <param name="onNotConfigured">
/// Called when neither env vars nor config keys provide a value.
/// Receives the settings with built-in defaults applied; return value replaces them.
/// </param>
public static StellaOpsCorsSettings Resolve(
IConfiguration configuration,
bool isDevelopment,
Func<StellaOpsCorsSettings, StellaOpsCorsSettings> onNotConfigured)
{
ArgumentNullException.ThrowIfNull(onNotConfigured);
return Resolve(configuration, isDevelopment, defaultEnabled: null, defaultOrigins: null, onNotConfigured);
}
private static StellaOpsCorsSettings Resolve(
IConfiguration configuration,
bool isDevelopment,
bool? defaultEnabled,
string[]? defaultOrigins,
Func<StellaOpsCorsSettings, StellaOpsCorsSettings>? onNotConfigured)
{
ArgumentNullException.ThrowIfNull(configuration);
var (enabled, enabledFromCascade) = ResolveBool(
configuration, isDevelopment,
EnvEnabled, ConfigEnabled,
LegacyEnvEnabled, LegacyConfigEnabled,
defaultEnabled);
var (origins, originsFromCascade) = ResolveOrigins(
configuration, isDevelopment,
EnvOrigin, ConfigOrigin,
LegacyEnvOrigin, LegacyConfigOrigin,
defaultOrigins);
var settings = new StellaOpsCorsSettings { Enabled = enabled, Origins = origins };
// If neither field was resolved from the cascade and a callback is provided, invoke it.
if (!enabledFromCascade && !originsFromCascade && onNotConfigured is not null)
{
settings = onNotConfigured(settings);
}
return settings;
}
/// <returns>A tuple of (resolved value, whether a cascade source provided the value).</returns>
private static (bool Value, bool FromCascade) ResolveBool(
IConfiguration configuration,
bool isDevelopment,
string envKey, string configKey,
string legacyEnvKey, string legacyConfigKey,
bool? explicitDefault)
{
// 1. Primary env var
var value = Environment.GetEnvironmentVariable(envKey);
if (!string.IsNullOrWhiteSpace(value))
return (IsTruthy(value), true);
// 2. Primary config key
var configValue = configuration[configKey];
if (!string.IsNullOrWhiteSpace(configValue))
return (IsTruthy(configValue), true);
// 3. Legacy env var
value = Environment.GetEnvironmentVariable(legacyEnvKey);
if (!string.IsNullOrWhiteSpace(value))
return (IsTruthy(value), true);
// 4. Legacy config key
configValue = configuration[legacyConfigKey];
if (!string.IsNullOrWhiteSpace(configValue))
return (IsTruthy(configValue), true);
// 5. Explicit default or built-in default
return (explicitDefault ?? isDevelopment, false);
}
/// <returns>A tuple of (resolved origins, whether a cascade source provided the value).</returns>
private static (string[] Value, bool FromCascade) ResolveOrigins(
IConfiguration configuration,
bool isDevelopment,
string envKey, string configKey,
string legacyEnvKey, string legacyConfigKey,
string[]? explicitDefault)
{
// 1. Primary env var
var value = Environment.GetEnvironmentVariable(envKey);
if (!string.IsNullOrWhiteSpace(value))
return (SplitOrigins(value), true);
// 2. Primary config key
var configValue = configuration[configKey];
if (!string.IsNullOrWhiteSpace(configValue))
return (SplitOrigins(configValue), true);
// 3. Legacy env var
value = Environment.GetEnvironmentVariable(legacyEnvKey);
if (!string.IsNullOrWhiteSpace(value))
return (SplitOrigins(value), true);
// 4. Legacy config key
configValue = configuration[legacyConfigKey];
if (!string.IsNullOrWhiteSpace(configValue))
return (SplitOrigins(configValue), true);
// 5. Explicit default or built-in default
return (explicitDefault ?? (isDevelopment ? DefaultDevOrigins : []), false);
}
private static bool IsTruthy(string value) =>
string.Equals(value, "true", StringComparison.OrdinalIgnoreCase)
|| string.Equals(value, "1", StringComparison.OrdinalIgnoreCase);
private static string[] SplitOrigins(string raw) =>
raw.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
}