using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace DodoSSH.Api.Setup;
///
/// Health check wiring.
///
///
/// The split between liveness and readiness is deliberate and load-bearing for the
/// relay: /healthz/live checks the process and nothing else, so a transient
/// PostgreSQL outage cannot cause the orchestrator to restart the container and
/// guillotine every live SSH session. Dependency checks belong in
/// /healthz/ready, which only removes the instance from load balancing.
///
internal static class HealthChecks
{
/// Tag for checks that gate readiness (dependencies).
internal const string ReadyTag = "ready";
/// Tag for checks that gate startup completion.
internal const string StartupTag = "startup";
internal static IServiceCollection AddDodoHealthChecks(this IServiceCollection services)
{
services.AddHealthChecks();
// Dependency checks are registered by the milestone that introduces the
// dependency, each tagged ReadyTag:
// M1 — PostgreSQL, OIDC discovery + JWKS reachability, pending migrations
// M4 — Data Protection key ring readability
return services;
}
internal static WebApplication MapDodoHealthChecks(this WebApplication app)
{
// Liveness: process is running and the pipeline responds. No dependencies.
app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
Predicate = _ => false,
}).AllowAnonymous();
// Readiness: safe to route traffic here.
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
Predicate = registration => registration.Tags.Contains(ReadyTag),
}).AllowAnonymous();
// Startup: one-time initialisation finished (K8s startupProbe).
app.MapHealthChecks("/healthz/startup", new HealthCheckOptions
{
Predicate = registration => registration.Tags.Contains(StartupTag),
}).AllowAnonymous();
return app;
}
}