This commit is contained in:
StellaOps Bot
2025-11-29 02:19:50 +02:00
parent 2548abc56f
commit b34f13dc03
86 changed files with 9625 additions and 640 deletions

View File

@@ -0,0 +1,28 @@
using System.Reflection;
using StellaOps.Infrastructure.Postgres.Testing;
using StellaOps.Policy.Storage.Postgres;
using Xunit;
namespace StellaOps.Policy.Storage.Postgres.Tests;
/// <summary>
/// PostgreSQL integration test fixture for the Policy module.
/// Runs migrations from embedded resources and provides test isolation.
/// </summary>
public sealed class PolicyPostgresFixture : PostgresIntegrationFixture, ICollectionFixture<PolicyPostgresFixture>
{
protected override Assembly? GetMigrationAssembly()
=> typeof(PolicyDataSource).Assembly;
protected override string GetModuleName() => "Policy";
}
/// <summary>
/// Collection definition for Policy PostgreSQL integration tests.
/// Tests in this collection share a single PostgreSQL container instance.
/// </summary>
[CollectionDefinition(Name)]
public sealed class PolicyPostgresCollection : ICollectionFixture<PolicyPostgresFixture>
{
public const string Name = "PolicyPostgres";
}

View File

@@ -0,0 +1,109 @@
using System.Collections.Immutable;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using StellaOps.Policy.Scoring;
using StellaOps.Policy.Scoring.Receipts;
using StellaOps.Policy.Storage.Postgres.Repositories;
using StellaOps.Policy.Storage.Postgres.Tests;
using StellaOps.Policy.Storage.Postgres;
using Xunit;
namespace StellaOps.Policy.Storage.Postgres.Tests;
[Collection(PolicyPostgresCollection.Name)]
public sealed class PostgresReceiptRepositoryTests : IAsyncLifetime
{
private readonly PolicyPostgresFixture _fixture;
private readonly PostgresReceiptRepository _repository;
private readonly string _tenantId = Guid.NewGuid().ToString();
public PostgresReceiptRepositoryTests(PolicyPostgresFixture fixture)
{
_fixture = fixture;
var options = fixture.Fixture.CreateOptions();
options.SchemaName = fixture.SchemaName;
var dataSource = new PolicyDataSource(Options.Create(options), NullLogger<PolicyDataSource>.Instance);
_repository = new PostgresReceiptRepository(dataSource, NullLogger<PostgresReceiptRepository>.Instance);
}
public Task InitializeAsync() => _fixture.TruncateAllTablesAsync();
public Task DisposeAsync() => Task.CompletedTask;
[Fact]
public async Task SaveAndGet_RoundTripsReceipt()
{
var receipt = CreateReceipt(_tenantId);
var saved = await _repository.SaveAsync(_tenantId, receipt);
var fetched = await _repository.GetAsync(_tenantId, saved.ReceiptId);
fetched.Should().NotBeNull();
fetched!.ReceiptId.Should().Be(saved.ReceiptId);
fetched.InputHash.Should().Be(saved.InputHash);
fetched.PolicyRef.PolicyId.Should().Be("default");
fetched.AttestationRefs.Should().BeEquivalentTo(saved.AttestationRefs);
}
private static CvssScoreReceipt CreateReceipt(string tenantId)
{
var baseMetrics = new CvssBaseMetrics
{
AttackVector = AttackVector.Network,
AttackComplexity = AttackComplexity.Low,
AttackRequirements = AttackRequirements.None,
PrivilegesRequired = PrivilegesRequired.None,
UserInteraction = UserInteraction.None,
VulnerableSystemConfidentiality = ImpactMetricValue.High,
VulnerableSystemIntegrity = ImpactMetricValue.High,
VulnerableSystemAvailability = ImpactMetricValue.High,
SubsequentSystemConfidentiality = ImpactMetricValue.High,
SubsequentSystemIntegrity = ImpactMetricValue.High,
SubsequentSystemAvailability = ImpactMetricValue.High
};
var scores = new CvssScores
{
BaseScore = 10.0,
ThreatScore = null,
EnvironmentalScore = null,
FullScore = null,
EffectiveScore = 10.0,
EffectiveScoreType = EffectiveScoreType.Base
};
return new CvssScoreReceipt
{
ReceiptId = Guid.NewGuid().ToString(),
SchemaVersion = "1.0.0",
Format = "stella.ops/cvssReceipt@v1",
VulnerabilityId = "CVE-2025-0001",
TenantId = tenantId,
CreatedAt = DateTimeOffset.UtcNow,
CreatedBy = "tester",
CvssVersion = "4.0",
BaseMetrics = baseMetrics,
ThreatMetrics = null,
EnvironmentalMetrics = null,
SupplementalMetrics = null,
Scores = scores,
VectorString = "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H",
Severity = CvssSeverity.Critical,
PolicyRef = new CvssPolicyReference
{
PolicyId = "default",
Version = "1.0.0",
Hash = "abc123",
ActivatedAt = null
},
Evidence = ImmutableList<CvssEvidenceItem>.Empty,
AttestationRefs = ImmutableList<string>.Empty,
InputHash = "hash123",
History = ImmutableList<ReceiptHistoryEntry>.Empty,
AmendsReceiptId = null,
IsActive = true,
SupersededReason = null
};
}
}

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" ?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\__Libraries\StellaOps.Policy.Storage.Postgres\StellaOps.Policy.Storage.Postgres.csproj" />
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.Postgres.Testing\StellaOps.Infrastructure.Postgres.Testing.csproj" />
<ProjectReference Include="..\..\StellaOps.Policy.Scoring\StellaOps.Policy.Scoring.csproj" />
</ItemGroup>
</Project>