namespace ItWorx.KnowledgeHub.Api.Tests; public sealed class SecurityHeaderTests : IClassFixture { private readonly HttpClient _client; public SecurityHeaderTests(KnowledgeHubApiFactory factory) { _client = factory.CreateClient(); } [Fact] public async Task Responses_carry_the_documented_baseline_security_headers() { using var response = await _client.GetAsync("/health/live"); Assert.Equal("nosniff", GetHeader(response, "X-Content-Type-Options")); Assert.Equal("DENY", GetHeader(response, "X-Frame-Options")); Assert.Equal("same-origin", GetHeader(response, "Referrer-Policy")); Assert.Contains("frame-ancestors 'none'", GetHeader(response, "Content-Security-Policy")); Assert.Contains("object-src 'none'", GetHeader(response, "Content-Security-Policy")); Assert.DoesNotContain("script-src 'self' 'unsafe-inline'", GetHeader(response, "Content-Security-Policy")); Assert.NotNull(GetHeader(response, "Permissions-Policy")); } [Fact] public async Task Every_response_carries_a_correlation_id_header() { using var response = await _client.GetAsync("/health/live"); var correlationId = GetHeader(response, "X-Correlation-ID"); Assert.False(string.IsNullOrWhiteSpace(correlationId)); Assert.True(Guid.TryParse(correlationId, out _)); } [Fact] public async Task A_supplied_correlation_id_is_echoed_back_unchanged() { using var request = new HttpRequestMessage(HttpMethod.Get, "/health/live"); request.Headers.Add("X-Correlation-ID", "caller-supplied-id-123"); using var response = await _client.SendAsync(request); Assert.Equal("caller-supplied-id-123", GetHeader(response, "X-Correlation-ID")); } private static string? GetHeader(HttpResponseMessage response, string name) => response.Headers.TryGetValues(name, out var values) ? string.Join(", ", values) : null; }