[glm-grade=B] fix: dead dashboard WS, corrupted error.log, auth-polling storm, re-auth freeze + CVE bumps
Adversarial audit 2026-08-16 (GLM-5.3 delegate, 2 rounds, 141 tool calls):
P0-1: Dashboard WebSocket (/api/v1/ws) dead on EVERY boot since DC-076.
server.js passed module exports (DependencyManager class, {AutoRestartManager}
namespace, SSLMonitor class) instead of createApp()'s live instances — first
.on() threw ERR_INVALID_ARG_TYPE, catch swallowed it. Fix: app.locals.ctx
exposed in src/app.js; server.js passes all 8 real EventEmitter instances.
P0-2: error.log corrupted since 2026-07-14. errorMiddleware called
logError(FILE, SIZE, path, err, meta) — 5 args into a 3-arg wrapper —
logging 'Error: 5242880' garbage every ~60s and DISCARDING the real error
object. Fix: correct 3-arg call + legacy-shape guard in logErrorWrapper +
~74 log.error sites swept to pass real error objects (AST-verified scope-
safe 71/71, 29/29 modules load clean).
P0-3: auth-polling storm (stranded grade=B commit never landed in prod):
401/403 behind TOTP gate hammered /api/v1/services/status + SSE reconnect
every 2-8s, with misleading direct-probe fallback marking services 'up'.
Fix landed + B-round MEDIUM follow-up: TOTP re-auth success now clears
_dcAuthLost, resumes SSE (new _sseResume clears the latch), and refreshes.
Also: eslintignore static-sites/ (33→0 errors); nodemailer 8→9.0.5 and
sharp 0.33→0.35.3 (3 high CVEs killed; jest green on new majors);
dockerode@5/uuid deferred (semver-major, Docker API surface).
Verification: 80/80 suites, 1837/1837 tests; ESLint 0 errors/743 warnings;
node --check all changed files; bundles rebuilt + SW cache bumped.
Judges: Codex quota-dead until Aug 19 (verified live) — GLM adversarial
delegate per operator directive 2026-08-07. Round 1: 98-call mechanical
verification (timed out pre-verdict). Round 2 (this grade): B, one MEDIUM
(re-auth freeze) — fixed in this commit as prescribed.
This commit is contained in:
+25
-26
@@ -68,30 +68,29 @@ process.on('uncaughtException', (error) => {
|
||||
attachExecWS(server, log, authManager);
|
||||
log.info('server', 'WebSocket exec handler attached (auth enforced)');
|
||||
|
||||
// DC-076: Attach dashboard WebSocket for real-time updates
|
||||
// DC-076: Attach dashboard WebSocket for real-time updates.
|
||||
// createApp() returns the live manager instances — use those instead
|
||||
// of re-requiring the modules (which yields singletons for some
|
||||
// managers and raw classes / namespace objects for others; calling
|
||||
// .on() on a class threw on every boot and silently killed the WS).
|
||||
try {
|
||||
const { ctx } = app.locals;
|
||||
const createDashboardWS = require('./src/websocket/dashboard-ws');
|
||||
const resourceMonitor = require('./src/managers/resource-monitor');
|
||||
const healthChecker = require('./src/monitoring/health-checker');
|
||||
const updateManager = require('./src/managers/update-manager');
|
||||
const dependencyManager = require('./src/managers/dependency-manager');
|
||||
const autoRestartManager = require('./src/managers/auto-restart-manager');
|
||||
const configDriftDetector = require('./src/managers/config-drift-detector');
|
||||
const sslMonitor = require('./src/monitoring/ssl-monitor');
|
||||
|
||||
createDashboardWS(server, {
|
||||
resourceMonitor,
|
||||
healthChecker,
|
||||
updateManager,
|
||||
dependencyManager,
|
||||
autoRestartManager,
|
||||
driftDetector: configDriftDetector,
|
||||
sslMonitor,
|
||||
resourceMonitor: ctx.resourceMonitor,
|
||||
healthChecker: ctx.healthChecker,
|
||||
updateManager: ctx.updateManager,
|
||||
dependencyManager: ctx.dependencyManager,
|
||||
autoRestartManager: ctx.autoRestartManager,
|
||||
driftDetector: ctx.driftDetector,
|
||||
sslMonitor: ctx.sslMonitor,
|
||||
dnsPropagationChecker: ctx.dnsPropagationChecker,
|
||||
log,
|
||||
});
|
||||
log.info('server', 'Dashboard WebSocket attached at /api/v1/ws');
|
||||
} catch (err) {
|
||||
log.error('server', 'Dashboard WebSocket failed to attach', { error: err.message });
|
||||
log.error('server', err, null, { feature: 'dashboard-ws' });
|
||||
}
|
||||
|
||||
// Start feature modules
|
||||
@@ -136,7 +135,7 @@ process.on('uncaughtException', (error) => {
|
||||
workflowEngine = new WorkflowEngine(workflowCtx);
|
||||
log.info('server', 'Workflow engine initialized');
|
||||
} catch (err) {
|
||||
log.error('server', 'Workflow engine failed to initialize', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Workflow engine failed to initialize' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +144,7 @@ process.on('uncaughtException', (error) => {
|
||||
// Clean up stale port locks
|
||||
portLockManager.cleanupStaleLocks()
|
||||
.then(() => log.info('server', 'Port lock cleanup completed'))
|
||||
.catch(err => log.error('server', 'Port lock cleanup failed', { error: err.message }));
|
||||
.catch(err => log.error('server', err, null, { note: 'Port lock cleanup failed' }));
|
||||
|
||||
// Resource monitoring
|
||||
try {
|
||||
@@ -156,7 +155,7 @@ process.on('uncaughtException', (error) => {
|
||||
}
|
||||
log.info('server', 'Resource monitoring started');
|
||||
} catch (err) {
|
||||
log.error('server', 'Resource monitoring failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Resource monitoring failed to start' });
|
||||
}
|
||||
|
||||
// Backup manager
|
||||
@@ -164,7 +163,7 @@ process.on('uncaughtException', (error) => {
|
||||
backupManager.start();
|
||||
log.info('server', 'Backup manager started');
|
||||
} catch (err) {
|
||||
log.error('server', 'Backup manager failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Backup manager failed to start' });
|
||||
}
|
||||
|
||||
// Security event workers (Caddy access log, fail2ban, shared_bans)
|
||||
@@ -175,7 +174,7 @@ process.on('uncaughtException', (error) => {
|
||||
startSecurityWorkers({ log });
|
||||
log.info('server', 'Security event workers started');
|
||||
} catch (err) {
|
||||
log.error('server', 'Security event workers failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Security event workers failed to start' });
|
||||
}
|
||||
|
||||
// Connect workflow engine to update manager for pre-update events
|
||||
@@ -206,7 +205,7 @@ process.on('uncaughtException', (error) => {
|
||||
healthChecker.start();
|
||||
log.info('server', 'Health checker started');
|
||||
} catch (err) {
|
||||
log.error('server', 'Health checker failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Health checker failed to start' });
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -215,7 +214,7 @@ process.on('uncaughtException', (error) => {
|
||||
updateManager.start();
|
||||
log.info('server', 'Update manager started');
|
||||
} catch (err) {
|
||||
log.error('server', 'Update manager failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Update manager failed to start' });
|
||||
}
|
||||
|
||||
// Self-updater
|
||||
@@ -234,7 +233,7 @@ process.on('uncaughtException', (error) => {
|
||||
})
|
||||
.catch(() => {});
|
||||
} catch (err) {
|
||||
log.error('server', 'Self-updater failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Self-updater failed to start' });
|
||||
}
|
||||
|
||||
// Docker maintenance (optional)
|
||||
@@ -257,7 +256,7 @@ process.on('uncaughtException', (error) => {
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
log.error('server', 'Docker maintenance failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Docker maintenance failed to start' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +270,7 @@ process.on('uncaughtException', (error) => {
|
||||
log.info('digest', `Daily digest generated for ${date}`);
|
||||
});
|
||||
} catch (err) {
|
||||
log.error('server', 'Log digest failed to start', { error: err.message });
|
||||
log.error('server', err, null, { note: 'Log digest failed to start' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user