feat(audit): Apply TreatWarningsAsErrors=true to 160+ production csproj files

Sprint: SPRINT_20251229_049_BE_csproj_audit_maint_tests
Tasks: AUDIT-0001 through AUDIT-0147 APPLY tasks (approved decisions 1-9)

Changes:
- Set TreatWarningsAsErrors=true for all production .NET projects
- Fixed nullable warnings in Scanner.EntryTrace, Scanner.Evidence,
  Scheduler.Worker, Concelier connectors, and other modules
- Injected TimeProvider/IGuidProvider for deterministic time/ID generation
- Added path traversal validation in AirGap.Bundle
- Fixed NULL handling in various cursor classes
- Third-party GostCryptography retains TreatWarningsAsErrors=false (preserves original)
- Test projects excluded per user decision (rejected decision 10)

Note: All 17 ACSC connector tests pass after snapshot fixture sync
This commit is contained in:
StellaOps Bot
2026-01-04 11:21:16 +02:00
parent bc4dd4f377
commit e411fde1a9
438 changed files with 2648 additions and 668 deletions

View File

@@ -8,6 +8,19 @@ namespace StellaOps.AirGap.Bundle.Services;
public sealed class BundleBuilder : IBundleBuilder
{
private readonly TimeProvider _timeProvider;
private readonly IGuidProvider _guidProvider;
public BundleBuilder() : this(TimeProvider.System, SystemGuidProvider.Instance)
{
}
public BundleBuilder(TimeProvider timeProvider, IGuidProvider guidProvider)
{
_timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
_guidProvider = guidProvider ?? throw new ArgumentNullException(nameof(guidProvider));
}
public async Task<BundleManifest> BuildAsync(
BundleBuildRequest request,
string outputPath,
@@ -21,7 +34,10 @@ public sealed class BundleBuilder : IBundleBuilder
foreach (var feedConfig in request.Feeds)
{
var component = await CopyComponentAsync(feedConfig, outputPath, ct).ConfigureAwait(false);
// Validate relative path before combining
var targetPath = PathValidation.SafeCombine(outputPath, feedConfig.RelativePath);
var component = await CopyComponentAsync(feedConfig, outputPath, targetPath, ct).ConfigureAwait(false);
feeds.Add(new FeedComponent(
feedConfig.FeedId,
feedConfig.Name,
@@ -35,7 +51,10 @@ public sealed class BundleBuilder : IBundleBuilder
foreach (var policyConfig in request.Policies)
{
var component = await CopyComponentAsync(policyConfig, outputPath, ct).ConfigureAwait(false);
// Validate relative path before combining
var targetPath = PathValidation.SafeCombine(outputPath, policyConfig.RelativePath);
var component = await CopyComponentAsync(policyConfig, outputPath, targetPath, ct).ConfigureAwait(false);
policies.Add(new PolicyComponent(
policyConfig.PolicyId,
policyConfig.Name,
@@ -48,7 +67,10 @@ public sealed class BundleBuilder : IBundleBuilder
foreach (var cryptoConfig in request.CryptoMaterials)
{
var component = await CopyComponentAsync(cryptoConfig, outputPath, ct).ConfigureAwait(false);
// Validate relative path before combining
var targetPath = PathValidation.SafeCombine(outputPath, cryptoConfig.RelativePath);
var component = await CopyComponentAsync(cryptoConfig, outputPath, targetPath, ct).ConfigureAwait(false);
cryptoMaterials.Add(new CryptoComponent(
cryptoConfig.ComponentId,
cryptoConfig.Name,
@@ -65,11 +87,11 @@ public sealed class BundleBuilder : IBundleBuilder
var manifest = new BundleManifest
{
BundleId = Guid.NewGuid().ToString(),
BundleId = _guidProvider.NewGuid().ToString(),
SchemaVersion = "1.0.0",
Name = request.Name,
Version = request.Version,
CreatedAt = DateTimeOffset.UtcNow,
CreatedAt = _timeProvider.GetUtcNow(),
ExpiresAt = request.ExpiresAt,
Feeds = feeds.ToImmutableArray(),
Policies = policies.ToImmutableArray(),
@@ -83,9 +105,9 @@ public sealed class BundleBuilder : IBundleBuilder
private static async Task<CopiedComponent> CopyComponentAsync(
BundleComponentSource source,
string outputPath,
string targetPath,
CancellationToken ct)
{
var targetPath = Path.Combine(outputPath, source.RelativePath);
Directory.CreateDirectory(Path.GetDirectoryName(targetPath) ?? outputPath);
await using (var input = File.OpenRead(source.SourcePath))