using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using StellaOps.AirGap.Time.Models; using StellaOps.AirGap.Time.Services; namespace StellaOps.AirGap.Time.Hooks; public static class StartupValidationExtensions { /// /// Runs sealed-mode time anchor validation during app startup; aborts if missing or stale. /// public static IHost ValidateTimeAnchorOnStart(this IHost host, string tenantId, StalenessBudget budget) { using var scope = host.Services.CreateScope(); var validator = scope.ServiceProvider.GetRequiredService(); var logger = scope.ServiceProvider.GetRequiredService().CreateLogger("AirGap.Time.Startup"); var result = validator.ValidateAsync(tenantId, budget, CancellationToken.None).GetAwaiter().GetResult(); if (!result.IsValid) { logger.LogCritical("AirGap time validation failed: {Reason} (tenant {TenantId})", result.Reason, tenantId); throw new InvalidOperationException($"sealed-startup-blocked:{result.Reason}"); } logger.LogInformation("AirGap time validation passed: anchor={Anchor} age={Age}s tenant={Tenant}", result.Status?.Anchor.TokenDigest, result.Status?.Staleness.AgeSeconds, tenantId); return host; } }