You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
P2 — Add graceful shutdown: install process.on('SIGTERM'|'SIGINT') handler that closes the HTTP server, drains the SSE client set, calls gatewayWsManager.disconnect(), waits up to a budget, then exits. Test the drain with a fake server.
Matched top finding
public/index.html is still 4,085 lines mixing UI, auth, queue, SSE, rendering, reactions, and notifications. Some extraction to public/lib/ (api-client, capacitor-detect, render-utils, reaction-events-browser) happened, but session-key hydration, mobile auth callback, queueing, theme, message rendering, history poll, and the rest still live in one HTML file. This is the same P2 Extract public/index.html runtime modules #541 had, partially closed.
server.js is 1,513 lines. Auth/sessions, Gateway WS, sessions routes, link previews, mobile OTA manifest proxying, SSE, reactions, and reactions all coexist. #540 partially closed; remaining hotspots are session/agent routes (738-1346) and reactions (1321-1365).
No tests cover /api/agents, /api/assistant-identity, /api/csrf-token, /api/openclaw-status, /api/openclaw-stop, or the /api/config exposure contract (only /api/sessions redirects and CSRF-origin cases in tests/authz-integration.test.js). The previously closed Add authorization/integration test matrix #539 added the test file but the matrix is sparse for new endpoints.
No graceful shutdown handler. No process.on('SIGTERM'/'SIGINT') in server.js or lib/*.js — the gateway WebSocket manager does not get a disconnect() on SIGTERM, leaving an open WS until process exit. Affects rollouts in Kubernetes and the Docker HEALTHCHECK drain.
Dead devDependency: typescript ^6.0.0 in package.json:40 with no .ts files anywhere in the repo (only .js and one .gradle).
Two update managers with overlapping concepts.lib/update-manager.js (server metadata helper, 164 lines) and public/mobile/update-manager.js (browser OTA lifecycle, 280 lines) both compute semver comparisons, both look at GitHub releases, but they live separately. Consolidate mobile update manager logic #542 partially closed — the client-side module now documents lib/update-manager.js as "for reference" but the server module still pulls @capacitor/core at import time, which is only safe because Capacitor?.isNativePlatform?.() short-circuits in Node. Importing the server module on Node without @capacitor/core installed would still crash.
README/OTA-docs drift. README changelog stops at v0.4.13. docs/OTA-UPDATES.md still references CAPGO_API_KEY and Capgo Cloud despite public/mobile/update-manager.js:7-9 saying "No Capgo account/API key required" and the validator rejecting cloud-shaped artifacts. Current package.json is 0.4.19, current release is 0.4.19.
Link preview performance still soft-bounded. Cache + coalescer exist (lib/link-preview-cache.js, applied at server.js:967-983), but _fetchLinkPreview can still do DNS resolution + up to 5 redirect hops + up to LINK_PREVIEW_MAX_HTML_CHARS (default 250,000) per uncached request. Tests cover cache behavior but not concurrent SSRF-DNS timeout pressure.
CSRF/origin integration tests don't cover the rotated-token path or the X-CSRF-Token missing-with-token-in-session path.tests/authz-integration.test.js exercises csrfOriginCheck (trusted/untrusted) and the unauthenticated redirects for /api/sessions//api/agents. It does not exercise csrfTokenCheck at all (the middleware name is even destructured out in tests/security.test.js:4).
Parent umbrella issue: #622
Source audit: Weekly tech debt audit: miso-chat - 2026-06-24
Source audit date: 2026-06-24
Original recommendation
P2 — Add graceful shutdown: install
process.on('SIGTERM'|'SIGINT')handler that closes the HTTP server, drains the SSE client set, callsgatewayWsManager.disconnect(), waits up to a budget, then exits. Test the drain with a fake server.Matched top finding
public/index.htmlis still 4,085 lines mixing UI, auth, queue, SSE, rendering, reactions, and notifications. Some extraction topublic/lib/(api-client, capacitor-detect, render-utils, reaction-events-browser) happened, but session-key hydration, mobile auth callback, queueing, theme, message rendering, history poll, and the rest still live in one HTML file. This is the same P2 Extract public/index.html runtime modules #541 had, partially closed.server.jsis 1,513 lines. Auth/sessions, Gateway WS, sessions routes, link previews, mobile OTA manifest proxying, SSE, reactions, and reactions all coexist.#540partially closed; remaining hotspots are session/agent routes (738-1346) and reactions (1321-1365).No tests cover
/api/agents,/api/assistant-identity,/api/csrf-token,/api/openclaw-status,/api/openclaw-stop, or the/api/configexposure contract (only/api/sessionsredirects and CSRF-origin cases intests/authz-integration.test.js). The previously closed Add authorization/integration test matrix #539 added the test file but the matrix is sparse for new endpoints.No graceful shutdown handler. No
process.on('SIGTERM'/'SIGINT')inserver.jsorlib/*.js— the gateway WebSocket manager does not get adisconnect()on SIGTERM, leaving an open WS until process exit. Affects rollouts in Kubernetes and the Docker HEALTHCHECK drain.Dead devDependency:
typescript^6.0.0 inpackage.json:40with no.tsfiles anywhere in the repo (only.jsand one.gradle).Two update managers with overlapping concepts.
lib/update-manager.js(server metadata helper, 164 lines) andpublic/mobile/update-manager.js(browser OTA lifecycle, 280 lines) both compute semver comparisons, both look at GitHub releases, but they live separately. Consolidate mobile update manager logic #542 partially closed — the client-side module now documentslib/update-manager.jsas "for reference" but the server module still pulls@capacitor/coreat import time, which is only safe becauseCapacitor?.isNativePlatform?.()short-circuits in Node. Importing the server module on Node without@capacitor/coreinstalled would still crash.README/OTA-docs drift. README changelog stops at
v0.4.13.docs/OTA-UPDATES.mdstill referencesCAPGO_API_KEYand Capgo Cloud despitepublic/mobile/update-manager.js:7-9saying "No Capgo account/API key required" and the validator rejecting cloud-shaped artifacts. Currentpackage.jsonis0.4.19, current release is0.4.19.Link preview performance still soft-bounded. Cache + coalescer exist (
lib/link-preview-cache.js, applied atserver.js:967-983), but_fetchLinkPreviewcan still do DNS resolution + up to 5 redirect hops + up toLINK_PREVIEW_MAX_HTML_CHARS(default 250,000) per uncached request. Tests cover cache behavior but not concurrent SSRF-DNS timeout pressure.CSRF/origin integration tests don't cover the rotated-token path or the
X-CSRF-Tokenmissing-with-token-in-session path.tests/authz-integration.test.jsexercisescsrfOriginCheck(trusted/untrusted) and the unauthenticated redirects for/api/sessions//api/agents. It does not exercisecsrfTokenCheckat all (the middleware name is even destructured out intests/security.test.js:4).