diff --git a/docs/REMEDIATION_PLAN.md b/docs/REMEDIATION_PLAN.md index 12a60fd..6257a7b 100644 --- a/docs/REMEDIATION_PLAN.md +++ b/docs/REMEDIATION_PLAN.md @@ -45,8 +45,8 @@ Key: `S` ≤ half day · `M` ~1–3 days · `L` ~1 week+ · 🔴 launch-blocker ## Phase 4 — De-spaghetti / structural cleanup (🟡) - [x] **4.1 L — Break up `index.js` (substantially).** ✅ Extracted the verify HTML → `views/verifyPage.js` (now HTML-escaped), all 15 admin endpoints → `routes/admin.js`, and the 3 smirk endpoints → `routes/auth.js`, each as DI factories with smoke tests. **index.js: 2029 → 882 lines (-57%).** _Remaining user/public routes left inline — they're interleaved with bootstrap and have no route tests, so further slicing is diminishing-return/higher-risk; the structure + pattern are established for later._ - [~] **4.2 M — Kill duplicates (partial).** ✅ Deleted the dead `handlePlayerMove` handler (a footgun that double-stepped the monster + bypassed escape/collision detection) and its orphaned `playerMoveTimestamps` map/cleanup — the live path is `MovementManager`. _Remaining (lower-value/higher-effort): merge `rpcService`+`rpccalls`, unify `payout_address` column widths, address the `QueryValidator` false-positive — deferred._ -- [ ] **4.3 M — Config as immutable snapshots;** stop mutating `process.env` (`gameModeManager.js:189`). -- [ ] **4.4 M — Frontend de-spaghetti.** Shared `escapeHtml`/`dom.js`; kill double-declares + dead `_appendMessage`; explicit init ordering; upgrade/drop jQuery; gate broadcast logging (`broadcastManager.js:33`). +- [⏸] **4.3 M — Config snapshots — DEFERRED (risk > value).** The `process.env` config write-back is ugly but **load-bearing**: it's how DB-persisted hot-reload config reaches the env-based readers — `difficultyConfig` selects the difficulty preset from `process.env.GAME_MODE`, and `debugManager`'s simulated-blocks **safety gate** reads it. A proper `ConfigService` means rewiring those sensitive readers; with no config-reload tests and zero correctness/safety upside, the risk isn't justified right now. Documented rather than rewritten. +- [~] **4.4 M — Frontend de-spaghetti (safe wins done).** ✅ Shared `escapeHtml` already added in 0.6. Removed the duplicate `_gameMode` declaration (the later `null` silently shadowed the earlier `'free'`). Removed the dead `SocketHandlers._appendMessage` calls in `smirkAuth.js` (the method never existed; always fell through to the working `.text()` append). Gated `broadcastManager`'s high-volume per-event logs (user-count, chat-message-with-PII, game-update, game-start) behind debug mode. _Deferred: jQuery 3.4.1 upgrade and the nested-`setTimeout` init-ordering rewrite (larger, no frontend tests, higher risk)._ - [x] **4.5 S — Delete stale `test/` scratch files.** ✅ Removed 14 non-jest leftovers (5 `.js` scratch scripts + 9 `.html` debug pages) — confirmed they contained no jest constructs and were referenced nowhere. `test/` is now exclusively the 21 real jest suites. ## Phase 5 — Test & ops overhaul (🟠 — the launch gate) diff --git a/html/js/network/smirkAuth.js b/html/js/network/smirkAuth.js index 0ef780a..04be1ba 100644 --- a/html/js/network/smirkAuth.js +++ b/html/js/network/smirkAuth.js @@ -214,11 +214,8 @@ const SmirkAuth = { ? 'Smirk wallet connected! Payout address set.' : 'Smirk wallet authenticated! Please set your payout address manually.'; - if (typeof SocketHandlers !== 'undefined' && SocketHandlers._appendMessage) { - SocketHandlers._appendMessage('status', successMsg); - } else { - $('#messages').append($('
  • ').text(successMsg)); - } + // .text() sets textContent, so the message is safe from injection. + $('#messages').append($('
  • ').text(successMsg)); // Update address button status if available if (typeof SocketHandlers !== 'undefined' && SocketHandlers._updateAddressButtonStatus) { @@ -233,11 +230,7 @@ const SmirkAuth = { // Show error message const errorMsg = 'Smirk login failed: ' + err.message; - if (typeof SocketHandlers !== 'undefined' && SocketHandlers._appendMessage) { - SocketHandlers._appendMessage('error', errorMsg); - } else { - $('#messages').append($('
  • ').text(errorMsg)); - } + $('#messages').append($('
  • ').text(errorMsg)); throw err; } diff --git a/html/js/network/socketHandlers.js b/html/js/network/socketHandlers.js index 6299630..8677666 100644 --- a/html/js/network/socketHandlers.js +++ b/html/js/network/socketHandlers.js @@ -13,7 +13,8 @@ const SocketHandlers = { _hasPayoutAddress: false, _creditsBalance: 0, - _gameMode: 'free', + _gameMode: null, // set from the server's game-modes event; was previously declared + // twice in this object literal (the later `null` silently won) _directPayoutsEnabled: false, _paymentsEnabled: false, @@ -1394,8 +1395,7 @@ const SocketHandlers = { // ===================== // Early Entry Functions // ===================== - - _gameMode: null, + _earlyEntryConfig: { enabled: false }, _isQueued: false, diff --git a/src/network/broadcastManager.js b/src/network/broadcastManager.js index 94e7ec3..bf46a31 100644 --- a/src/network/broadcastManager.js +++ b/src/network/broadcastManager.js @@ -30,8 +30,10 @@ class BroadcastManager { count = this.io.engine.clientsCount || 0; } - console.log(`👥 Broadcasting user count: ${count} (last was ${this._lastUserCount})`); - + if (this.debugManager?.CONSOLE_LOGGING) { + console.log(`👥 Broadcasting user count: ${count} (last was ${this._lastUserCount})`); + } + // Always broadcast to ensure new clients get the count this._lastUserCount = count; this.io.emit('user_count', { count }); @@ -60,8 +62,10 @@ class BroadcastManager { * @param {string} socketId - Socket ID of the sender */ broadcastChatMessage(username, message, timestamp, socketId) { - console.log(`💬 Broadcasting chat message from ${socketId}: "${message}"`); - + if (this.debugManager?.CONSOLE_LOGGING) { + console.log(`💬 Broadcasting chat message from ${socketId}: "${message}"`); + } + this.io.emit('chat_broadcast', { username: username, message: message, @@ -100,11 +104,12 @@ class BroadcastManager { * @param {object} gameState - The game state to broadcast */ sendGameUpdate(playerSocketId, gameState) { - // Debug logging for lighting data in updates - console.log(`📡 sendGameUpdate to ${playerSocketId}:`); - console.log(` - Lighting data: ${!!gameState.lighting} (${gameState.lighting ? Object.keys(gameState.lighting).length : 0} rows)`); - console.log(` - Torch data: ${!!gameState.torches} (${gameState.torches ? gameState.torches.length : 0} torches)`); - + if (this.debugManager?.CONSOLE_LOGGING) { + console.log(`📡 sendGameUpdate to ${playerSocketId}:`); + console.log(` - Lighting data: ${!!gameState.lighting} (${gameState.lighting ? Object.keys(gameState.lighting).length : 0} rows)`); + console.log(` - Torch data: ${!!gameState.torches} (${gameState.torches ? gameState.torches.length : 0} torches)`); + } + // Send to the player this.io.to(playerSocketId).emit('game_update', gameState); @@ -125,7 +130,9 @@ class BroadcastManager { * @param {object} gameState - Initial game state */ sendGameStart(socketId, gameState) { - console.log(`🎮 SENDING GAME_START to ${socketId}`); + if (this.debugManager?.CONSOLE_LOGGING) { + console.log(`🎮 SENDING GAME_START to ${socketId}`); + } this.io.to(socketId).emit('game_start', gameState); }