using System; namespace StellaOps.Configuration; /// /// API lifecycle controls for the Authority service. /// public sealed class AuthorityApiLifecycleOptions { /// /// Settings for the legacy OAuth endpoint shim (/oauth/* → canonical). /// public AuthorityLegacyAuthEndpointOptions LegacyAuth { get; } = new(); internal void Validate() { LegacyAuth.Validate(); } } /// /// Configuration for legacy OAuth endpoint shims and deprecation signalling. /// public sealed class AuthorityLegacyAuthEndpointOptions { private static readonly DateTimeOffset DefaultDeprecationDate = new(2025, 11, 1, 0, 0, 0, TimeSpan.Zero); private static readonly DateTimeOffset DefaultSunsetDate = new(2026, 5, 1, 0, 0, 0, TimeSpan.Zero); /// /// Enables the legacy endpoint shim that routes /oauth/* to the canonical endpoints. /// public bool Enabled { get; set; } = true; /// /// Date when clients should consider the legacy endpoints deprecated. /// public DateTimeOffset DeprecationDate { get; set; } = DefaultDeprecationDate; /// /// Date when legacy endpoints will be removed. /// public DateTimeOffset SunsetDate { get; set; } = DefaultSunsetDate; /// /// Optional documentation URL included in the Sunset link header. /// public string? DocumentationUrl { get; set; } = "https://docs.stella-ops.org/authority/legacy-auth"; internal void Validate() { if (!Enabled) { return; } var normalizedDeprecation = DeprecationDate.ToUniversalTime(); var normalizedSunset = SunsetDate.ToUniversalTime(); if (normalizedSunset <= normalizedDeprecation) { throw new InvalidOperationException("Legacy auth sunset date must be after the deprecation date."); } DeprecationDate = normalizedDeprecation; SunsetDate = normalizedSunset; if (!string.IsNullOrWhiteSpace(DocumentationUrl)) { if (!Uri.TryCreate(DocumentationUrl, UriKind.Absolute, out var uri) || (uri.Scheme != Uri.UriSchemeHttps && uri.Scheme != Uri.UriSchemeHttp)) { throw new InvalidOperationException("Legacy auth documentation URL must be an absolute HTTP or HTTPS URL."); } } } }