consolidation of some of the modules, localization fixes, product advisories work, qa work

This commit is contained in:
master
2026-03-05 03:54:22 +02:00
parent 7bafcc3eef
commit 8e1cb9448d
3878 changed files with 72600 additions and 46861 deletions

View File

@@ -100,6 +100,12 @@ public static class GovernanceEndpoints
.WithName("ValidateRiskProfile")
.WithDescription("Validate a candidate risk profile configuration without persisting it. Checks for required fields (name, at least one signal) and emits warnings when signal weights do not sum to 1.0. Used by policy authoring tools to provide inline validation feedback before profile creation.");
// Risk Budget endpoints
governance.MapGet("/risk-budget/dashboard", GetRiskBudgetDashboardAsync)
.RequireAuthorization(policy => policy.RequireStellaOpsScopes(StellaOpsScopes.PolicyRead))
.WithName("GetRiskBudgetDashboard")
.WithDescription("Retrieve the current risk budget dashboard including utilization, headroom, top contributors, active alerts, and KPIs for the tenant.");
// Audit endpoints
governance.MapGet("/audit/events", GetAuditEventsAsync)
.RequireAuthorization(policy => policy.RequireStellaOpsScopes(StellaOpsScopes.PolicyAudit))
@@ -539,6 +545,117 @@ public static class GovernanceEndpoints
return Task.FromResult(Results.Ok(response));
}
// ========================================================================
// Risk Budget Handlers
// ========================================================================
private static Task<IResult> GetRiskBudgetDashboardAsync(
HttpContext httpContext,
[FromServices] TimeProvider timeProvider,
[FromQuery] string? tenantId,
[FromQuery] string? projectId)
{
var tenant = tenantId ?? GetTenantId(httpContext) ?? "default";
var now = timeProvider.GetUtcNow();
var traceId = httpContext.TraceIdentifier;
var periodStart = new DateTimeOffset(now.Year, ((now.Month - 1) / 3) * 3 + 1, 1, 0, 0, 0, TimeSpan.Zero);
var periodEnd = periodStart.AddMonths(3).AddSeconds(-1);
var response = new
{
config = new
{
id = "budget-001",
tenantId = tenant,
projectId = projectId ?? (string?)null,
name = $"Q{(now.Month - 1) / 3 + 1} {now.Year} Risk Budget",
totalBudget = 1000,
warningThreshold = 70,
criticalThreshold = 90,
period = "quarterly",
periodStart = periodStart.ToString("O", CultureInfo.InvariantCulture),
periodEnd = periodEnd.ToString("O", CultureInfo.InvariantCulture),
createdAt = periodStart.AddDays(-15).ToString("O", CultureInfo.InvariantCulture),
updatedAt = now.ToString("O", CultureInfo.InvariantCulture)
},
currentRiskPoints = 720,
headroom = 280,
utilizationPercent = 72.0,
status = "warning",
timeSeries = Enumerable.Range(0, 5).Select(i =>
{
var ts = now.AddDays(-28 + i * 7);
var actual = 600 + i * 30;
return new
{
timestamp = ts.ToString("O", CultureInfo.InvariantCulture),
actual,
budget = 1000,
headroom = 1000 - actual
};
}).ToList(),
updatedAt = now.ToString("O", CultureInfo.InvariantCulture),
traceId,
topContributors = new[]
{
new { identifier = "pkg:npm/lodash@4.17.20", type = "component", displayName = "lodash", riskPoints = 120, percentOfBudget = 12.0, trend = "stable", delta24h = 0 },
new { identifier = "CVE-2024-1234", type = "vulnerability", displayName = "CVE-2024-1234", riskPoints = 95, percentOfBudget = 9.5, trend = "increasing", delta24h = 10 },
new { identifier = "vulnerability", type = "category", displayName = "Vulnerabilities", riskPoints = 450, percentOfBudget = 45.0, trend = "stable", delta24h = 5 }
},
activeAlerts = new[]
{
new
{
id = "alert-001",
threshold = new { level = 70, severity = "medium", actions = new[] { new { type = "notify", channels = new[] { "slack" } } } },
currentUtilization = 72.0,
triggeredAt = now.AddDays(-1).ToString("O", CultureInfo.InvariantCulture),
acknowledged = false,
acknowledgedBy = (string?)null,
acknowledgedAt = (string?)null
}
},
governance = new
{
id = "budget-001",
tenantId = tenant,
name = $"Q{(now.Month - 1) / 3 + 1} {now.Year} Risk Budget",
totalBudget = 1000,
warningThreshold = 70,
criticalThreshold = 90,
period = "quarterly",
periodStart = periodStart.ToString("O", CultureInfo.InvariantCulture),
periodEnd = periodEnd.ToString("O", CultureInfo.InvariantCulture),
createdAt = periodStart.AddDays(-15).ToString("O", CultureInfo.InvariantCulture),
updatedAt = now.ToString("O", CultureInfo.InvariantCulture),
thresholds = new[]
{
new { level = 70, severity = "medium", actions = new object[] { new { type = "notify", channels = new[] { "slack", "email" } } } },
new { level = 90, severity = "high", actions = new object[] { new { type = "notify", channels = new[] { "slack", "email" } }, new { type = "require_approval" } } },
new { level = 100, severity = "critical", actions = new object[] { new { type = "block_deploys" }, new { type = "escalate" } } }
},
enforceHardLimits = true,
gracePeriodHours = 24,
autoReset = true,
carryoverPercent = 0
},
kpis = new
{
headroom = 280,
headroomDelta24h = -20,
unknownsDelta24h = 3,
riskRetired7d = 45,
exceptionsExpiring = 2,
burnRate = 8.5,
projectedDaysToExceeded = 33,
traceId
}
};
return Task.FromResult(Results.Ok(response));
}
// ========================================================================
// Audit Handlers
// ========================================================================