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:
@@ -32,6 +32,18 @@ builder.Configuration
|
||||
|
||||
builder.Services.AddAdvisoryAiCore(builder.Configuration);
|
||||
|
||||
// Authorization service
|
||||
builder.Services.AddSingleton<StellaOps.AdvisoryAI.WebService.Services.IAuthorizationService, StellaOps.AdvisoryAI.WebService.Services.HeaderBasedAuthorizationService>();
|
||||
|
||||
// Rate limits service with configuration
|
||||
builder.Services.AddOptions<StellaOps.AdvisoryAI.WebService.Services.RateLimitsOptions>()
|
||||
.Bind(builder.Configuration.GetSection(StellaOps.AdvisoryAI.WebService.Services.RateLimitsOptions.SectionName))
|
||||
.ValidateOnStart();
|
||||
builder.Services.AddSingleton<StellaOps.AdvisoryAI.WebService.Services.IRateLimitsService, StellaOps.AdvisoryAI.WebService.Services.ConfigDrivenRateLimitsService>();
|
||||
|
||||
// TimeProvider for deterministic timestamps
|
||||
builder.Services.AddSingleton(TimeProvider.System);
|
||||
|
||||
// VEX-AI-016: Consent and justification services
|
||||
builder.Services.AddSingleton<IAiConsentStore, InMemoryAiConsentStore>();
|
||||
builder.Services.AddSingleton<IAiJustificationGenerator, DefaultAiJustificationGenerator>();
|
||||
@@ -645,9 +657,12 @@ static async Task<IResult> HandlePolicyValidate(
|
||||
}
|
||||
|
||||
// POLICY-19: POST /v1/advisory-ai/policy/studio/compile
|
||||
// NOTE: This is a stub implementation. In production, this would compile rules into a PolicyBundle.
|
||||
// The stub returns experimental markers to indicate incomplete implementation.
|
||||
static Task<IResult> HandlePolicyCompile(
|
||||
HttpContext httpContext,
|
||||
PolicyCompileApiRequest request,
|
||||
TimeProvider timeProvider,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
using var activity = AdvisoryAiActivitySource.Instance.StartActivity("advisory_ai.policy_compile", ActivityKind.Server);
|
||||
@@ -659,9 +674,14 @@ static Task<IResult> HandlePolicyCompile(
|
||||
return Task.FromResult(Results.StatusCode(StatusCodes.Status403Forbidden));
|
||||
}
|
||||
|
||||
// In a real implementation, this would compile rules into a PolicyBundle
|
||||
var bundleId = $"bundle:{Guid.NewGuid():N}";
|
||||
var now = DateTime.UtcNow;
|
||||
// STUB: This endpoint is experimental and not wired to real policy compilation.
|
||||
// Return a deterministic bundle ID derived from input to avoid nondeterministic output.
|
||||
var inputHash = ComputeDeterministicBundleId(request.BundleName, request.RuleIds);
|
||||
var bundleId = $"bundle:stub:{inputHash}";
|
||||
var now = timeProvider.GetUtcNow();
|
||||
|
||||
// Compute content hash deterministically from the rule IDs
|
||||
var contentHash = ComputeDeterministicContentHash(request.RuleIds);
|
||||
|
||||
var response = new PolicyBundleApiResponse
|
||||
{
|
||||
@@ -670,13 +690,29 @@ static Task<IResult> HandlePolicyCompile(
|
||||
Version = "1.0.0",
|
||||
RuleCount = request.RuleIds.Count,
|
||||
CompiledAt = now.ToString("O"),
|
||||
ContentHash = $"sha256:{Guid.NewGuid():N}",
|
||||
ContentHash = $"sha256:{contentHash}",
|
||||
SignatureId = null // Would be signed in production
|
||||
};
|
||||
|
||||
return Task.FromResult(Results.Ok(response));
|
||||
}
|
||||
|
||||
// Deterministic hash computation for stub bundle ID
|
||||
static string ComputeDeterministicBundleId(string bundleName, IReadOnlyList<string> ruleIds)
|
||||
{
|
||||
var input = $"{bundleName}:{string.Join(",", ruleIds.OrderBy(x => x, StringComparer.Ordinal))}";
|
||||
var bytes = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(input));
|
||||
return Convert.ToHexString(bytes)[..32].ToLowerInvariant();
|
||||
}
|
||||
|
||||
// Deterministic content hash for stub bundles
|
||||
static string ComputeDeterministicContentHash(IReadOnlyList<string> ruleIds)
|
||||
{
|
||||
var input = string.Join(",", ruleIds.OrderBy(x => x, StringComparer.Ordinal));
|
||||
var bytes = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(input));
|
||||
return Convert.ToHexString(bytes).ToLowerInvariant();
|
||||
}
|
||||
|
||||
// VEX-AI-016: Consent handler functions
|
||||
static string GetTenantId(HttpContext context)
|
||||
{
|
||||
@@ -869,41 +905,24 @@ static async Task<IResult> HandleRemediate(
|
||||
}
|
||||
}
|
||||
|
||||
// VEX-AI-016: Rate limits handler
|
||||
// VEX-AI-016: Rate limits handler using config-driven service
|
||||
static Task<IResult> HandleGetRateLimits(
|
||||
HttpContext httpContext,
|
||||
StellaOps.AdvisoryAI.WebService.Services.IRateLimitsService rateLimitsService,
|
||||
TimeProvider timeProvider,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// Return current rate limit info for each feature
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var resetTime = now.AddMinutes(1);
|
||||
var limits = rateLimitsService.GetRateLimits(timeProvider);
|
||||
|
||||
var limits = new List<AiRateLimitInfoResponse>
|
||||
var response = limits.Select(l => new AiRateLimitInfoResponse
|
||||
{
|
||||
new AiRateLimitInfoResponse
|
||||
{
|
||||
Feature = "explain",
|
||||
Limit = 10,
|
||||
Remaining = 10,
|
||||
ResetsAt = resetTime.ToString("O")
|
||||
},
|
||||
new AiRateLimitInfoResponse
|
||||
{
|
||||
Feature = "remediate",
|
||||
Limit = 5,
|
||||
Remaining = 5,
|
||||
ResetsAt = resetTime.ToString("O")
|
||||
},
|
||||
new AiRateLimitInfoResponse
|
||||
{
|
||||
Feature = "justify",
|
||||
Limit = 3,
|
||||
Remaining = 3,
|
||||
ResetsAt = resetTime.ToString("O")
|
||||
}
|
||||
};
|
||||
Feature = l.Feature,
|
||||
Limit = l.Limit,
|
||||
Remaining = l.Remaining,
|
||||
ResetsAt = l.ResetsAt.ToString("O")
|
||||
}).ToList();
|
||||
|
||||
return Task.FromResult(Results.Ok(limits));
|
||||
return Task.FromResult(Results.Ok(response));
|
||||
}
|
||||
|
||||
internal sealed record PipelinePlanRequest(
|
||||
|
||||
Reference in New Issue
Block a user