mbproxy: remediate the 2026-05-16 code-review findings
Fixes every finding from the codereviews/2026-05-16 multi-agent review (2 Critical, 20 Major, 38 Minor) and adds that review to the repo. Highlights: dashboard XSS escape; response cache invalidated on the write request (not just the response); ReloadValidator now runs at startup so port collisions / duplicate names / malformed Resilience profiles fail fast; AdminPort 0 genuinely disables the admin endpoint; PlcListener accept-loop faults propagate to the supervisor's faulted path; reconciler Restart builds before removing; Resilience pipelines are restart-only from a frozen snapshot; multiplexer connect-race leak, watchdog party-list snapshot, backend-response and FC16 framing validation; frontend reconnect retry and util.js load guard; plus the log-event/doc drift sweep and test-port hygiene. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,16 @@
|
||||
}
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const { escapeHtml } = window.mbproxyUtil;
|
||||
|
||||
// util.js must load before this script. If it failed to load, fail loud and
|
||||
// visible rather than letting the destructure throw and abort the page silently.
|
||||
if (!window.mbproxyUtil) {
|
||||
document.body.innerHTML =
|
||||
'<p style="padding:2rem;font-family:sans-serif;color:#b00">' +
|
||||
'Admin UI failed to load (util.js missing). Check the browser console.</p>';
|
||||
throw new Error('window.mbproxyUtil is not defined');
|
||||
}
|
||||
const { escapeHtml, escapeAttr } = window.mbproxyUtil;
|
||||
|
||||
document.title = `mbproxy — ${plcName}`;
|
||||
$('crumb-name').textContent = plcName;
|
||||
@@ -220,8 +229,8 @@
|
||||
</tr>`;
|
||||
}
|
||||
const dirCls = t.direction === 'write' ? 'dir-write' : 'dir-read';
|
||||
const stale = (t.ageSeconds || 0) > 30 ? ' stale' : '';
|
||||
return `<tr class="${stale.trim()}">
|
||||
const staleAttr = (t.ageSeconds || 0) > 30 ? ' class="stale"' : '';
|
||||
return `<tr${staleAttr}>
|
||||
${tagCell(t)}
|
||||
<td>${Number(t.width)}-bit</td>
|
||||
<td><span class="dir-tag ${dirCls}">${escapeHtml(t.direction)}</span></td>
|
||||
@@ -280,10 +289,10 @@
|
||||
|
||||
connection.on('plc', onDetail);
|
||||
connection.onreconnecting(() => setConn('connecting', 'reconnecting'));
|
||||
connection.onreconnected(() => {
|
||||
setConn('connected');
|
||||
connection.invoke('SubscribePlc', plcName, tabId).catch(() => {});
|
||||
});
|
||||
// On a warm reconnect the transport is back but the group subscription is not —
|
||||
// re-subscribe through connect(), which retries with backoff if the invoke fails
|
||||
// and re-arms the snapshot watchdog (instead of silently showing a dead feed).
|
||||
connection.onreconnected(() => connect());
|
||||
connection.onclose(() => setConn('disconnected', 'disconnected'));
|
||||
|
||||
// Cold start. withAutomaticReconnect only recovers an already-established
|
||||
|
||||
Reference in New Issue
Block a user