Frontend gaps fill work. Testing fixes work. Auditing in progress.

This commit is contained in:
StellaOps Bot
2025-12-30 01:22:58 +02:00
parent 1dc4bcbf10
commit 7a5210e2aa
928 changed files with 183942 additions and 3941 deletions

View File

@@ -0,0 +1,38 @@
using System;
using System.Linq;
using System.Net.Http.Json;
using StellaOps.Platform.WebService.Contracts;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Platform.WebService.Tests;
public sealed class HealthEndpointsTests : IClassFixture<PlatformWebApplicationFactory>
{
private readonly PlatformWebApplicationFactory factory;
public HealthEndpointsTests(PlatformWebApplicationFactory factory)
{
this.factory = factory;
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Summary_UsesCacheAndStableDataAsOf()
{
var tenantId = $"tenant-health-{Guid.NewGuid():N}";
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Add("X-StellaOps-Tenant", tenantId);
var first = await client.GetFromJsonAsync<PlatformItemResponse<PlatformHealthSummary>>("/api/v1/platform/health/summary");
Assert.NotNull(first);
Assert.False(first!.Cached);
var second = await client.GetFromJsonAsync<PlatformItemResponse<PlatformHealthSummary>>("/api/v1/platform/health/summary");
Assert.NotNull(second);
Assert.True(second!.Cached);
Assert.Equal(first.DataAsOf, second.DataAsOf);
Assert.True(first.Item.Services.Select(service => service.Service)
.SequenceEqual(second.Item.Services.Select(service => service.Service)));
}
}

View File

@@ -0,0 +1,32 @@
using System.Linq;
using System.Net.Http.Json;
using StellaOps.Platform.WebService.Contracts;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Platform.WebService.Tests;
public sealed class MetadataEndpointsTests : IClassFixture<PlatformWebApplicationFactory>
{
private readonly PlatformWebApplicationFactory factory;
public MetadataEndpointsTests(PlatformWebApplicationFactory factory)
{
this.factory = factory;
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Metadata_ReturnsCapabilitiesInStableOrder()
{
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Add("X-StellaOps-Tenant", "tenant-metadata");
var response = await client.GetFromJsonAsync<PlatformItemResponse<PlatformMetadata>>(
"/api/v1/platform/metadata");
Assert.NotNull(response);
var ids = response!.Item.Capabilities.Select(cap => cap.Id).ToArray();
Assert.Equal(new[] { "health", "onboarding", "preferences", "quotas", "search" }, ids);
}
}

View File

@@ -0,0 +1,40 @@
using System.Linq;
using System.Net.Http.Json;
using StellaOps.Platform.WebService.Contracts;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Platform.WebService.Tests;
public sealed class OnboardingEndpointsTests : IClassFixture<PlatformWebApplicationFactory>
{
private readonly PlatformWebApplicationFactory factory;
public OnboardingEndpointsTests(PlatformWebApplicationFactory factory)
{
this.factory = factory;
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Onboarding_CompleteStepUpdatesStatus()
{
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Add("X-StellaOps-Tenant", "tenant-onboarding");
client.DefaultRequestHeaders.Add("X-StellaOps-Actor", "actor-onboarding");
var response = await client.PostAsync("/api/v1/platform/onboarding/complete/connect-scanner", null);
response.EnsureSuccessStatusCode();
var state = await response.Content.ReadFromJsonAsync<PlatformOnboardingState>();
Assert.NotNull(state);
var step = state!.Steps.FirstOrDefault(item => item.Step == "connect-scanner");
Assert.NotNull(step);
Assert.Equal("completed", step!.Status);
Assert.Equal("actor-onboarding", step.UpdatedBy);
Assert.Equal(
state.Steps.OrderBy(item => item.Step, System.StringComparer.Ordinal).Select(item => item.Step),
state.Steps.Select(item => item.Step));
}
}

View File

@@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Logging;
namespace StellaOps.Platform.WebService.Tests;
public sealed class PlatformWebApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseSetting("Platform:Authority:Issuer", "https://authority.local");
builder.UseSetting("Platform:Authority:RequireHttpsMetadata", "false");
builder.UseSetting("Platform:Authority:BypassNetworks:0", "127.0.0.1/32");
builder.UseSetting("Platform:Authority:BypassNetworks:1", "::1/128");
builder.ConfigureLogging(logging =>
{
logging.ClearProviders();
});
}
}

View File

@@ -0,0 +1,47 @@
using System.Linq;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
using StellaOps.Platform.WebService.Contracts;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Platform.WebService.Tests;
public sealed class PreferencesEndpointsTests : IClassFixture<PlatformWebApplicationFactory>
{
private readonly PlatformWebApplicationFactory factory;
public PreferencesEndpointsTests(PlatformWebApplicationFactory factory)
{
this.factory = factory;
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Preferences_RoundTripUpdatesLayout()
{
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Add("X-StellaOps-Tenant", "tenant-preferences");
client.DefaultRequestHeaders.Add("X-StellaOps-Actor", "actor-preferences");
var request = new PlatformDashboardPreferencesRequest(new JsonObject
{
["layout"] = "incident",
["widgets"] = new JsonArray("health", "quota"),
["filters"] = new JsonObject { ["scope"] = "tenant" }
});
var updateResponse = await client.PutAsJsonAsync("/api/v1/platform/preferences/dashboard", request);
updateResponse.EnsureSuccessStatusCode();
var updated = await client.GetFromJsonAsync<PlatformDashboardPreferences>("/api/v1/platform/preferences/dashboard");
Assert.NotNull(updated);
Assert.Equal("tenant-preferences", updated!.TenantId);
Assert.Equal("actor-preferences", updated.ActorId);
Assert.Equal("incident", updated.Preferences["layout"]?.GetValue<string>());
var widgets = updated.Preferences["widgets"] as JsonArray;
Assert.NotNull(widgets);
Assert.Equal(new[] { "health", "quota" }, widgets!.Select(widget => widget!.GetValue<string>()).ToArray());
}
}

View File

@@ -0,0 +1,35 @@
using System.Linq;
using System.Net.Http.Json;
using StellaOps.Platform.WebService.Contracts;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Platform.WebService.Tests;
public sealed class QuotaEndpointsTests : IClassFixture<PlatformWebApplicationFactory>
{
private readonly PlatformWebApplicationFactory factory;
public QuotaEndpointsTests(PlatformWebApplicationFactory factory)
{
this.factory = factory;
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Quotas_ReturnDeterministicOrder()
{
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Add("X-StellaOps-Tenant", "tenant-quotas");
var response = await client.GetFromJsonAsync<PlatformListResponse<PlatformQuotaUsage>>(
"/api/v1/platform/quotas/summary");
Assert.NotNull(response);
var items = response!.Items.ToArray();
Assert.Equal(
new[] { "gateway.requests", "orchestrator.jobs", "storage.evidence" },
items.Select(item => item.QuotaId).ToArray());
Assert.Equal(77000m, items[0].Remaining);
}
}

View File

@@ -0,0 +1,41 @@
using System.Linq;
using System.Net.Http.Json;
using StellaOps.Platform.WebService.Contracts;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Platform.WebService.Tests;
public sealed class SearchEndpointsTests : IClassFixture<PlatformWebApplicationFactory>
{
private readonly PlatformWebApplicationFactory factory;
public SearchEndpointsTests(PlatformWebApplicationFactory factory)
{
this.factory = factory;
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Search_ReturnsDeterministicOrder()
{
using var client = factory.CreateClient();
client.DefaultRequestHeaders.Add("X-StellaOps-Tenant", "tenant-search");
var response = await client.GetFromJsonAsync<PlatformListResponse<PlatformSearchItem>>(
"/api/v1/platform/search?limit=5");
Assert.NotNull(response);
var items = response!.Items.Select(item => item.EntityId).ToArray();
Assert.Equal(
new[]
{
"scan-2025-0001",
"finding-cve-2025-1001",
"policy-ops-baseline",
"pack-offline-kit",
"tenant-acme"
},
items);
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>preview</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\StellaOps.Platform.WebService\StellaOps.Platform.WebService.csproj" />
<ProjectReference Include="..\..\..\__Libraries\StellaOps.TestKit\StellaOps.TestKit.csproj" />
</ItemGroup>
</Project>