Security & resource hardening: eliminate CPU/disk attack surface
Addresses production CPU spike incident. Key changes: - Guard OTel exporter behind OTEL_EXPORTER_OTLP_ENDPOINT env var; filter tracing to /api paths only — unconditional export was primary suspect - Remove /healthz endpoint entirely (unauthenticated, hit DB on every call) - Replace KnownUserMiddleware with POST /api/users/me called once on login from TokenSync — eliminates unconditional DB write on every request - Add DB indexes: (BudgetId, IsDeleted) on Incomes/Outgos, OwnerUserId on Budgets, SharedWithUserId and (IsPending, SharedWithEmail) on BudgetShares - Move UseRateLimiter() before UseStaticFiles() so all requests are throttled - Replace full-array reorder with move-by-position (id + newIndex) — bounded input, fewer DB writes, better API design - Lock ForwardedHeaders to 172.20.0.0/16 subnet; fixes KnownNetworks deprecation warning (0 warnings in build now) - Add AsNoTracking() to all read-only queries in Summary/Incomes/OutgosController - FrequencyCalculator returns 0 for unknown enum values instead of throwing - Thread.Sleep → await Task.Delay in OIDC startup loop - AllowedHosts locked to budget.stwaddle.com Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,11 +29,11 @@ public class SummaryController(AppDbContext db, BudgetAuthorizationService authz
|
||||
if (TryGetUserId(out var userId) is { } err) return err;
|
||||
if (!await authz.CanReadAsync(budgetId, userId)) return Forbid();
|
||||
|
||||
var budget = await db.Budgets.FindAsync(budgetId);
|
||||
var budget = await db.Budgets.AsNoTracking().FirstOrDefaultAsync(b => b.Id == budgetId);
|
||||
if (budget is null) return NotFound();
|
||||
|
||||
var incomes = await db.Incomes.Where(i => i.BudgetId == budgetId).ToListAsync();
|
||||
var outgos = await db.Outgos.Where(o => o.BudgetId == budgetId).ToListAsync();
|
||||
var incomes = await db.Incomes.AsNoTracking().Where(i => i.BudgetId == budgetId).ToListAsync();
|
||||
var outgos = await db.Outgos.AsNoTracking().Where(o => o.BudgetId == budgetId).ToListAsync();
|
||||
|
||||
var monthlyIncome = incomes.Sum(i => FrequencyCalculator.ToMonthly(i.Amount, i.Frequency));
|
||||
var annualIncome = monthlyIncome * 12m;
|
||||
|
||||
Reference in New Issue
Block a user