using System.Net; using System.Net.Http.Json; using ItWorx.KnowledgeHub.Infrastructure.Persistence; using ItWorx.KnowledgeHub.IntegrationTests.Infrastructure; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace ItWorx.KnowledgeHub.IntegrationTests.Operations; /// docs/19-observability.md: "/api/v1/system/info" is permissioned /// information, distinct from the anonymous /health/live and /health/ready /// endpoints. [Collection(PostgresTestGroup.Name)] public sealed class SystemInfoTests(PostgresContainerFixture postgres) : OwnerSetupTestBase(postgres) { [Fact] public async Task An_authenticated_administrator_sees_the_current_schema_version() { using var client = Factory.CreateClient(); await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword); var response = await client.GetAsync("/api/v1/system/info"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var payload = await response.Content.ReadFromJsonAsync(); Assert.NotNull(payload); Assert.Equal("ItWorx Knowledge Hub", payload.Product); using var scope = Factory.Services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var currentMigration = (await db.Database.GetAppliedMigrationsAsync()).Last(); Assert.Equal(currentMigration, payload.SchemaVersion); } [Fact] public async Task An_anonymous_caller_is_rejected() { using var client = Factory.CreateClient(); var response = await client.GetAsync("/api/v1/system/info"); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } /// docs/adr/ADR-029-v2-r5-final-hardening.md (brief Phase 9): the /// canonical release identity always includes a live-computed database migration /// range for whichever database the instance is actually connected to — this is /// never baked into the build-time manifest, so it must be non-null once /// migrations have run (which they always have, by the time an integration test's /// database is usable at all). Build-time-only fields (openApiHash, etc.) are /// honestly null in this test environment, since no release-manifest.json exists /// on a local test run — never fabricated. [Fact] public async Task The_release_identity_always_reports_a_live_database_migration_range() { using var client = Factory.CreateClient(); await SetupHelper.LoginAsync(client, OwnerEmail, OwnerPassword); var response = await client.GetAsync("/api/v1/system/info"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var payload = await response.Content.ReadFromJsonAsync(); Assert.NotNull(payload); Assert.NotNull(payload.Release); Assert.False(string.IsNullOrWhiteSpace(payload.Release.DatabaseMigrationRange)); // No release-manifest.json is baked in for a local test run — this must // degrade to null, never a fabricated value. Assert.Null(payload.Release.OpenApiHash); } private sealed record SystemInfoPayload(string Product, string SchemaVersion); private sealed record SystemInfoWithReleasePayload(string Product, ReleaseIdentityPayload Release); private sealed record ReleaseIdentityPayload(string? DatabaseMigrationRange, string? OpenApiHash); }