← Back to PRs

#17205: fix: enforce full operator scopes for Control UI and Webchat auto-pairing

by Limitless2023 open 2026-02-15 14:25 View on GitHub →
channel: telegram gateway scripts commands agents stale size: M
Fixes #17187 ## Problem After gateway restart (e.g., WSL2 restart), auto-paired Dashboard/Webchat devices only have 3 scopes: `operator.admin`, `operator.approvals`, `operator.pairing`. Missing `operator.read` and `operator.write` causes Dashboard to be completely non-functional with "missing scope: operator.read" errors on every operation. ## Root Cause The scopes enforcement logic only set full scopes when `scopes.length === 0`: ```typescript if ((isControlUi || isWebchat) && scopes.length === 0) { scopes = [/* full list */]; } ``` **Problem scenario:** 1. Client connects with incomplete scopes (e.g., `["operator.admin", "operator.approvals", "operator.pairing"]` from an old config or device token) 2. Condition `scopes.length === 0` is **false** (length is 3) 3. Scopes are **not corrected** to include `operator.read` and `operator.write` 4. These incomplete scopes are saved during auto-pairing 5. On subsequent connections (e.g., after WSL2 restart), the paired device loads these incomplete scopes 6. Dashboard fails with "missing scope: operator.read" ## Solution Always enforce full operator scopes for Control UI and Webchat, **regardless of what the client provides**: ```typescript if (isControlUi || isWebchat) { scopes = [ "operator.read", "operator.write", "operator.admin", "operator.approvals", "operator.pairing", ]; } ``` This ensures auto-paired devices always get all necessary scopes, fixing Dashboard functionality after restarts. ## Impact - ✅ Dashboard works correctly after gateway restart (WSL2, systemd, etc.) - ✅ Auto-paired devices get full operator permissions - ✅ No manual re-pairing needed - ✅ Fixes regression where incomplete scopes break Dashboard - 🔒 Security unchanged: Control UI and Webchat already required operator role <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a critical bug where auto-paired Dashboard/Webchat devices lose `operator.read` and `operator.write` scopes after gateway restart, causing complete Dashboard failure. The core fix in `message-handler.ts` correctly enforces full operator scopes for Control UI/Webchat regardless of client-provided scopes, ensuring auto-paired devices always get complete permissions. **Major changes:** - **message-handler.ts**: Always enforces full operator scopes for Control UI/Webchat (lines 306-317), fixing the incomplete scope bug - **bot-message-context.ts**: Improves DM audio handling by transcribing voice messages to text - **store.ts**: Adds filtering for invalid session file paths (but has a data loss bug - see comment) - **turns.ts**: Extends message merging to handle consecutive system/assistant messages - **session.ts**: Preserves `responseUsage` across session resets - Minor improvements: workspaceDir support, diagnostic event broadcasting, cron heartbeat fixes **Critical bugs found:** 1. `bot-message-context.ts:401` - Temporal Dead Zone violation will crash on DM audio 2. `store.ts:189` - Overly aggressive filtering removes valid sessions before transcript initialization <h3>Confidence Score: 3/5</h3> - Safe to merge with fixes - core scope enforcement is correct, but two critical runtime bugs need immediate attention - The primary scope enforcement fix (message-handler.ts) is sound and solves the stated problem correctly. However, two critical bugs exist: (1) TDZ violation in bot-message-context.ts will cause runtime crashes on DM audio messages, and (2) session store filtering will cause data loss for new sessions. Score of 3 reflects that the main fix works but accompanying changes introduce regressions that must be fixed before merge. - Critical fixes needed in `src/telegram/bot-message-context.ts` (line 401, TDZ crash) and `src/config/sessions/store.ts` (line 189, data loss). Review `src/gateway/server/ws-connection/message-handler.ts` scope enforcement logic carefully. <sub>Last reviewed commit: 239defd</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs