feat: Implement Scheduler Worker Options and Planner Loop
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added `SchedulerWorkerOptions` class to encapsulate configuration for the scheduler worker.
- Introduced `PlannerBackgroundService` to manage the planner loop, fetching and processing planning runs.
- Created `PlannerExecutionService` to handle the execution logic for planning runs, including impact targeting and run persistence.
- Developed `PlannerExecutionResult` and `PlannerExecutionStatus` to standardize execution outcomes.
- Implemented validation logic within `SchedulerWorkerOptions` to ensure proper configuration.
- Added documentation for the planner loop and impact targeting features.
- Established health check endpoints and authentication mechanisms for the Signals service.
- Created unit tests for the Signals API to ensure proper functionality and response handling.
- Configured options for authority integration and fallback authentication methods.
This commit is contained in:
2025-10-27 09:46:31 +02:00
parent 96d52884e8
commit 730354a1af
135 changed files with 10721 additions and 946 deletions

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
namespace StellaOps.Signals.Options;
/// <summary>
/// Authority configuration for the Signals service.
/// </summary>
public sealed class SignalsAuthorityOptions
{
/// <summary>
/// Enables Authority-backed authentication.
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Allows header-based development fallback when Authority is disabled.
/// </summary>
public bool AllowAnonymousFallback { get; set; } = true;
/// <summary>
/// Authority issuer URL.
/// </summary>
public string Issuer { get; set; } = string.Empty;
/// <summary>
/// Indicates whether HTTPS metadata is required.
/// </summary>
public bool RequireHttpsMetadata { get; set; } = true;
/// <summary>
/// Optional metadata address override.
/// </summary>
public string? MetadataAddress { get; set; }
/// <summary>
/// Back-channel timeout (seconds).
/// </summary>
public int BackchannelTimeoutSeconds { get; set; } = 30;
/// <summary>
/// Token clock skew allowance (seconds).
/// </summary>
public int TokenClockSkewSeconds { get; set; } = 60;
/// <summary>
/// Accepted token audiences.
/// </summary>
public IList<string> Audiences { get; } = new List<string>();
/// <summary>
/// Required scopes.
/// </summary>
public IList<string> RequiredScopes { get; } = new List<string>();
/// <summary>
/// Required tenants.
/// </summary>
public IList<string> RequiredTenants { get; } = new List<string>();
/// <summary>
/// Networks allowed to bypass scope enforcement.
/// </summary>
public IList<string> BypassNetworks { get; } = new List<string>();
/// <summary>
/// Validates the configured options.
/// </summary>
public void Validate()
{
if (!Enabled)
{
return;
}
if (string.IsNullOrWhiteSpace(Issuer))
{
throw new InvalidOperationException("Signals Authority issuer must be configured when Authority integration is enabled.");
}
if (!Uri.TryCreate(Issuer.Trim(), UriKind.Absolute, out var issuerUri))
{
throw new InvalidOperationException("Signals Authority issuer must be an absolute URI.");
}
if (RequireHttpsMetadata && !issuerUri.IsLoopback && !string.Equals(issuerUri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("Signals Authority issuer must use HTTPS unless running on loopback.");
}
if (BackchannelTimeoutSeconds <= 0)
{
throw new InvalidOperationException("Signals Authority back-channel timeout must be greater than zero seconds.");
}
if (TokenClockSkewSeconds < 0 || TokenClockSkewSeconds > 300)
{
throw new InvalidOperationException("Signals Authority token clock skew must be between 0 and 300 seconds.");
}
}
}