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:
@@ -29,9 +29,9 @@ internal sealed record RuNkckiCursor(
|
||||
{
|
||||
var document = new DocumentObject
|
||||
{
|
||||
["pendingDocuments"] = new DocumentArray(PendingDocuments.Select(id => id.ToString())),
|
||||
["pendingMappings"] = new DocumentArray(PendingMappings.Select(id => id.ToString())),
|
||||
["knownBulletins"] = new DocumentArray(KnownBulletins),
|
||||
["pendingDocuments"] = new DocumentArray(PendingDocuments.OrderBy(id => id).Select(id => id.ToString())),
|
||||
["pendingMappings"] = new DocumentArray(PendingMappings.OrderBy(id => id).Select(id => id.ToString())),
|
||||
["knownBulletins"] = new DocumentArray(KnownBulletins.OrderBy(id => id, StringComparer.Ordinal)),
|
||||
};
|
||||
|
||||
if (LastListingFetchAt.HasValue)
|
||||
|
||||
@@ -339,7 +339,7 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
}
|
||||
|
||||
var doc = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
|
||||
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-nkcki.v1", doc, _timeProvider.GetUtcNow());
|
||||
var dtoRecord = new DtoRecord(ComputeDeterministicId(document.Id.ToString(), "ru-nkcki/1.0"), document.Id, SourceName, "ru-nkcki.v1", doc, _timeProvider.GetUtcNow());
|
||||
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
|
||||
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -609,7 +609,7 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
return false;
|
||||
}
|
||||
|
||||
var recordId = existing?.Id ?? Guid.NewGuid();
|
||||
var recordId = existing?.Id ?? ComputeDeterministicId(documentUri, "ru-nkcki-doc/1.0");
|
||||
_ = await _rawDocumentStorage.UploadAsync(SourceName, documentUri, payload, "application/json", null, cancellationToken, recordId).ConfigureAwait(false);
|
||||
|
||||
var metadata = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
@@ -725,12 +725,12 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
return new ListingPageResult(attachments, uniquePagination);
|
||||
}
|
||||
|
||||
private static string DeriveBulletinId(Uri uri)
|
||||
private string DeriveBulletinId(Uri uri)
|
||||
{
|
||||
var fileName = Path.GetFileName(uri.AbsolutePath);
|
||||
if (string.IsNullOrWhiteSpace(fileName))
|
||||
{
|
||||
return Guid.NewGuid().ToString("N");
|
||||
return ComputeDeterministicSlug(uri.AbsoluteUri, "bulletin-id");
|
||||
}
|
||||
|
||||
if (fileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -746,7 +746,7 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
return fileName.Replace('_', '-');
|
||||
}
|
||||
|
||||
private static string BuildDocumentUri(RuNkckiVulnerabilityDto dto)
|
||||
private string BuildDocumentUri(RuNkckiVulnerabilityDto dto)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(dto.FstecId))
|
||||
{
|
||||
@@ -761,7 +761,10 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
return $"https://nvd.nist.gov/vuln/detail/{dto.MitreId}";
|
||||
}
|
||||
|
||||
return $"https://cert.gov.ru/materialy/uyazvimosti/{Guid.NewGuid():N}";
|
||||
// Fallback: deterministic slug based on dto content
|
||||
var dtoJson = JsonSerializer.Serialize(dto, SerializerOptions);
|
||||
var slug2 = ComputeDeterministicSlug(dtoJson, "nkcki-doc");
|
||||
return $"https://cert.gov.ru/materialy/uyazvimosti/{slug2}";
|
||||
}
|
||||
|
||||
private string ResolveCacheDirectory(string? configuredPath)
|
||||
@@ -791,7 +794,7 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
private string GetBulletinCachePath(string bulletinId)
|
||||
{
|
||||
var fileStem = string.IsNullOrWhiteSpace(bulletinId)
|
||||
? Guid.NewGuid().ToString("N")
|
||||
? ComputeDeterministicSlug("unknown-bulletin", _timeProvider.GetUtcNow().ToString("O"))
|
||||
: Uri.EscapeDataString(bulletinId);
|
||||
return Path.Combine(_cacheDirectory, $"{fileStem}.json.zip");
|
||||
}
|
||||
@@ -947,4 +950,17 @@ public sealed class RuNkckiConnector : IFeedConnector
|
||||
|
||||
return new ListingFetchSummary(attachments, visited);
|
||||
}
|
||||
|
||||
private Guid ComputeDeterministicId(string source, string identifier)
|
||||
{
|
||||
var input = Encoding.UTF8.GetBytes($"{source}:{identifier}");
|
||||
var hash = _hash.ComputeHash(input, HashAlgorithms.Sha256);
|
||||
return new Guid(hash.AsSpan()[..16]);
|
||||
}
|
||||
|
||||
private string ComputeDeterministicSlug(string source, string identifier)
|
||||
{
|
||||
var input = Encoding.UTF8.GetBytes($"{source}:{identifier}");
|
||||
return _hash.ComputeHashHex(input, HashAlgorithms.Sha256)[..32];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user