31 lines
1.4 KiB
C#
31 lines
1.4 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// Runs sealed-mode time anchor validation during app startup; aborts if missing or stale.
|
|
/// </summary>
|
|
public static IHost ValidateTimeAnchorOnStart(this IHost host, string tenantId, StalenessBudget budget)
|
|
{
|
|
using var scope = host.Services.CreateScope();
|
|
var validator = scope.ServiceProvider.GetRequiredService<SealedStartupValidator>();
|
|
var logger = scope.ServiceProvider.GetRequiredService<ILoggerFactory>().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;
|
|
}
|
|
}
|