using System.Net; using System.Net.Http.Json; using ItWorx.KnowledgeHub.Contracts.Auth; using ItWorx.KnowledgeHub.Contracts.Ingestion; using ItWorx.KnowledgeHub.IntegrationTests.Infrastructure; using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Options; namespace ItWorx.KnowledgeHub.IntegrationTests.Ingestion; [Collection(PostgresTestGroup.Name)] public sealed class IngestionPilotAvailabilityTests(PostgresContainerFixture postgres) : OwnerSetupTestBase(postgres) { [Fact] public async Task Disabled_intake_keeps_knowledge_routes_and_readiness_available_when_optional_mcp_is_unhealthy() { using var client = Factory.CreateClient(); var login = await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword); login.EnsureSuccessStatusCode(); var session = await client.GetFromJsonAsync("/api/v1/auth/session"); Assert.NotNull(session); Assert.False(session.Features?.IngestionProposals); var intake = await client.GetAsync("/api/v1/ingestion-proposals"); Assert.Equal(HttpStatusCode.NotFound, intake.StatusCode); var problem = await intake.Content.ReadFromJsonAsync(); Assert.Equal(IngestionProblemTypes.FeatureDisabled, problem?.Type); var knowledge = await client.GetAsync("/api/v1/pages/roots"); Assert.Equal(HttpStatusCode.OK, knowledge.StatusCode); // Model an unavailable optional external integration. The readiness endpoint // must remain tied to the Hub's own database and storage requirements. var healthChecks = Factory.Services .GetRequiredService>() .Value; healthChecks.Registrations.Add(new HealthCheckRegistration( "optional-mcp", _ => new UnavailableOptionalDependencyHealthCheck(), HealthStatus.Unhealthy, tags: null, timeout: TimeSpan.FromSeconds(1))); var readiness = await client.GetAsync("/health/ready"); Assert.Equal(HttpStatusCode.OK, readiness.StatusCode); Assert.Equal("Healthy", (await readiness.Content.ReadAsStringAsync()).Trim()); var liveness = await client.GetAsync("/health/live"); Assert.Equal(HttpStatusCode.OK, liveness.StatusCode); } private sealed class UnavailableOptionalDependencyHealthCheck : IHealthCheck { public Task CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken = default) => Task.FromResult(HealthCheckResult.Unhealthy("Optional MCP dependency is unavailable.")); } }