Skip to content

Weekly tech debt audit: miso-chat - 2026-07-01 #654

Description

@itsmiso-ai

Weekly tech debt audit: miso-chat - 2026-07-01

Issue URL: #654

Summary / Overall Risk Level

Overall risk level: P1 / medium, trending down. Since the 2026-06-24 audit (#622), 11 of 14 decomposed issues have been closed (issues #629#640). Significant progress:

Tests: 318 passing (up from 274), 0 failing. ESLint: 0 errors, 52 warnings. npm audit: 0 vulnerabilities. server.js: 1578 lines. public/index.html: 4011 lines.

Remaining open work from the prior audit (3 issues still open):

New findings in this cycle are concentrated at P2 (maintainability, small hardening gaps).

Top Findings

P0

  • None confirmed. No live secret exposure, no unauthenticated destructive route, no failing mainline CI.

P1

P2

  • index.html still 4011 lines. Extraction of secure-storage and session-key-hydration helped, but message rendering, history polling, auth flows, SSE handling, theme, queue, emoji shortcodes, and mobile auth callback remain in one file. 9 remaining innerHTML assignments.

  • Duplicate rate-limit key generation. The CF-IP / X-Forwarded-For / req.ip fallback chain is copy-pasted three times in server.js (lines 300, 334, 355). Should be extracted to a shared helper.

  • public/mobile/update-manager.js still uses innerHTML (line 197) for the update notification template. No user interpolation, but same vector class.

  • multer in package.json dependencies is listed but never imported or used anywhere in the codebase.

  • cors package (v2.8.6) with Express 5 (v5.2.1). Express 5 has built-in CORS support; the cors npm package is an Express 3/4 middleware. Should be verified for compatibility or replaced.

  • 5 unused variable warnings in tests (link-preview-cache, link-preview-performance, mobile-auth-regression).

  • security.js has an unused reason parameter at line 72.

  • console.warn duplication in security.js getScriptSrcDirective — same message in both branches.

P3

  • RELEASE.md still recommends git push --tags workflow for releases, but the actual release process uses manual-release.yml auto-merge.
  • scripts/release-version-check.js not run in any CI workflow.
  • docker-compose.yml still mounts . to /app shadowing the container's /app/data directory.
  • No knip or dead-code analysis tool in CI.

Evidence

Repository: misospace/miso-chat, main, HEAD 988dea0. Latest release: 0.4.19.

File sizes:

  • server.js: 1578
  • security.js: 298
  • lib/auth-session.js: 545
  • lib/gateway-ws.js: 459
  • lib/db.js: 160
  • lib/link-preview-cache.js: 259
  • lib/ssrf-validation.js: 123
  • lib/session-auth.js: 29
  • lib/update-manager.js: 163
  • public/index.html: 4011
  • public/lib/api-client.js: 304
  • public/lib/session-key-hydration.js: 122
  • public/lib/secure-storage.js: 83
  • public/lib/render-utils.js: 203
  • tests/: 6581 (total across all test files)

Test results:

  • 318 tests, 318 pass, 0 fail, duration ~30.1s

Lint:

  • 0 errors, 52 warnings

Audit:

  • 0 vulnerabilities

Unfinished business — CSRF:

  • grep -rn "X-CSRF-Token|x-csrf-token|csrfToken|/api/csrf-token" public/ public/lib/ public/mobile/ -> zero matches in browser code.
  • security.js csrfTokenCheck early-returns when session token is absent.
  • tests/security.test.js destructures csrfTokenCheck but never exercises it.
  • Issue Finish CSRF token frontend integration (#537 follow-up) #627 still status/in-progress.

Unfinished business — Android signing:

Unfinished business — graceful shutdown:

  • server.js: no process.on('SIGTERM') or process.on('SIGINT') handler.
  • gatewayWsManager.disconnect() only called from request handlers.

Duplicate rate-limit key generation in server.js:

  • Lines 300-329 (limiter)
  • Lines 334-353 (sseLimiter)
  • Lines 355-374 (authLimiter)
  • All three identical except for max and skip predicates.

innerHTML usage remaining:

  • 9 assignments in public/index.html (code highlighting, header parts, shortcode suggestions, session select, message container resets) — all hardcoded/trusted strings.
  • 1 assignment in public/mobile/update-manager.js:197 (update notification template).

Recommended Issue Breakdown

  1. P1 — Finish CSRF token frontend integration (Finish CSRF token frontend integration (#537 follow-up) #627 continuation): fetch /api/csrf-token on page load, attach X-CSRF-Token to POST/PUT/PATCH/DELETE from apiFetch, retry once on 403, add integration tests.

  2. P1 — Wire Android release signing (Wire Android release signing #628 continuation): merge signing solution from PR fix(android-release): wire release signing with key.properties and required secrets #653.

  3. P2 — Extract duplicate rate-limit key generation into shared helper: single rateLimitKeyGenerator(req) function replacing three copies.

  4. P2 — Replace innerHTML in public/mobile/update-manager.js notification: use createElement/textContent/appendChild.

  5. P2 — Add graceful shutdown (Add graceful shutdown #634 continuation): process.on('SIGTERM'/'SIGINT') handler closes HTTP server, drains SSE, calls gatewayWsManager.disconnect().

  6. P2 — Verify cors package compatibility with Express 5. Either verify or migrate to Express 5 native CORS.

  7. P2 — Remove unused multer dependency from package.json.

  8. P3 — Update RELEASE.md to match current automation release flow.

  9. P3 — Fix unused variable warnings in tests.

  10. P3 — Clean up console.warn duplication in security.js getScriptSrcDirective.

Not Worth Doing Yet

  • Do not rewrite the frontend framework. The module-extraction strategy is working.
  • Do not replace SQLite. Only reactions are stored and volume is trivial.
  • Do not build per-user RBAC before session-ownership contract settles (meta(0.5.0): plan miso-chat for OpenClaw-as-MCP and multi-provider message-plane #387).
  • Do not add knip/CI dead-code analysis until remaining P1s are closed.
  • Do not pursue Express 5 compatibility audit beyond the CORS point above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    auditAudit, review, or investigation work.enhancementNew feature or improvement.priority/p1High priority.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions