fix: deep bug hunt II — concurrency, security & optimization (25 files)

Critical: watchdog mutex panic safety, SetGeoAppOverride nil guard,
SSD-only app DB restore fallback.

High: double deploy race (atomic Deploying flag), delete/remove during
deploy guard, ScanStacks overwrite protection, FileBrowser mount mutex,
PushEvent history, PushOnce error handling, DB dump sync+close before
rename, restic retry fresh context, encrypt failure logging, cross-backup
path traversal validation, deepCopyStack completeness.

Security: constant-time API key comparison, login rate limiting (5/min),
git credential masking in logs, storage path prefix traversal fix.

Concurrency: MigrateEncryption lock ordering, SubdomainInUse I/O outside
lock, scheduler late-registered jobs, SQLite WAL verification, metrics
shutdown context, telemetry scan error logging, asset sync lock scope.

Optimization: streaming file copy for DB dumps, restic stats dedup,
atomic infra config copy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 14:21:09 +01:00
parent 72ab145b41
commit db83db383c
25 changed files with 930 additions and 626 deletions
+6 -6
View File
@@ -54,25 +54,25 @@ func (c *MetricsCollector) loop(ctx context.Context) {
defer ticker.Stop()
// Sample immediately on start
c.sample()
c.sampleWith(ctx)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
c.sample()
c.sampleWith(ctx)
}
}
}
func (c *MetricsCollector) sample() {
func (c *MetricsCollector) sampleWith(ctx context.Context) {
sys := c.sampleSystem()
if err := c.store.InsertSystemMetrics(sys); err != nil {
c.logger.Printf("[WARN] Failed to store system metrics: %v", err)
}
containers := c.sampleContainers()
containers := c.sampleContainers(ctx)
if err := c.store.InsertContainerMetrics(containers); err != nil {
c.logger.Printf("[WARN] Failed to store container metrics: %v", err)
}
@@ -96,8 +96,8 @@ func (c *MetricsCollector) sampleSystem() SystemSample {
}
}
func (c *MetricsCollector) sampleContainers() []ContainerSample {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
func (c *MetricsCollector) sampleContainers(parentCtx context.Context) []ContainerSample {
ctx, cancel := context.WithTimeout(parentCtx, 30*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "docker", "stats", "--no-stream",