Conversation
In multi-tenant mode, refreshing the dashboard lost all user state because alerts, analyses, and chat were stored only in memory. Added three DB tables (chat_history, alerts_log, analyses_log) and eagerly push per-user state (watchlists, config, budget, reports) on auth so the dashboard is fully populated immediately after reconnect. Made-with: Cursor
fix: persist alerts, analyses, and chat history across page refresh
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| content: r.content, | ||
| timestamp: r.created_at, | ||
| })) | ||
| } |
There was a problem hiding this comment.
Exported getChatHistoryForUser is never called anywhere
Low Severity
getChatHistoryForUser (renamed from the previous getChatHistory) is exported but never imported or called anywhere in the codebase. The broadcaster.ts imports getChatHistory directly from db.ts instead and does its own formatting in sendPerUserState. This function also hydrates the in-memory conversations cache, which suggests it was intended to replace the direct DB call in the broadcaster — but the integration was missed, leaving this as dead code.
| export function appendAlertLog(userId: number, alertId: string, payload: string): void { | ||
| getDb().prepare( | ||
| "INSERT INTO alerts_log (user_id, alert_id, payload) VALUES (?, ?, ?)" | ||
| ).run(userId, alertId, payload) |
There was a problem hiding this comment.
Exported appendAlertLog and appendAnalysisLog never called
Low Severity
appendAlertLog and appendAnalysisLog (per-user variants) are exported but never imported or called anywhere. All call sites use the ForAllUsers variants (appendAlertLogForAllUsers, appendAnalysisLogForAllUsers) instead. These are dead exports that add confusion about which function to use.
Additional Locations (1)
| } catch (err) { | ||
| log.warn(`Failed to persist analysis: ${(err as Error).message}`) | ||
| } | ||
| } |
There was a problem hiding this comment.
Alert/analysis persistence logic duplicated across four locations
Medium Severity
The same try/catch pattern for persisting alerts and analyses (check isMultiTenant(), extract ID with fallback, call appendAlertLogForAllUsers/appendAnalysisLogForAllUsers, catch and warn) is copy-pasted in four separate locations in broadcaster.ts: broadcastToAll, the onAlert callback, and the WS agent_analysis and alert route handlers. Any future change to the persistence logic (e.g., deduplication, retention) would require updating all four spots.
Additional Locations (2)
| handleRequestReports(ws, undefined) | ||
| } catch (err) { | ||
| log.warn(`Failed to send per-user state for ${auth.email}: ${(err as Error).message}`) | ||
| } |
There was a problem hiding this comment.
Broad try-catch causes total state loss on single failure
Medium Severity
The sendPerUserState function wraps all state-sending operations (alerts, analyses, chat, agent config, watchlists, schedule config, budget, reports) in a single try-catch. A JSON.parse failure on one corrupt alert or analysis payload will abort the entire function, silently preventing the user from receiving their chat history, watchlists, config, and reports on reconnect. This undermines the core goal of the PR — persisting state across page refresh — because one bad row in alerts_log can block all other state delivery.


Release: develop → main
Merges the latest develop into main to trigger a Render redeploy.
Included
chat_history,alerts_log,analyses_logCommits
6b82518fix: persist alerts, analyses, and chat history across page refresh75a5730Merge pull request fix: persist alerts, analyses, and chat history across page refresh #2Made with Cursor
Note
Medium Risk
Adds new SQLite persistence and changes WS startup/auth flows to load and broadcast per-user state, which can impact data integrity and runtime behavior on reconnect. Risk is moderate due to schema migrations and additional write paths on every alert/analysis/chat message.
Overview
Persists user state across refresh/reconnect in multi-tenant mode. Alerts and agent analyses are now written through to SQLite (
alerts_log,analyses_log) when received/broadcast, and per-user histories are loaded from DB and sent to the client instead of relying only on in-memoryrecentAlerts/recentAnalyses.Chat history is now durable. Chat messages (including error responses) are appended to a new
chat_historytable and conversation context is restored from DB when in-memory history is missing;clearChatHistoryalso clears the DB.Auth/reconnect experience is improved. After successful auth, the server eagerly pushes per-user state (alert/analysis/chat history plus config/watchlist/schedule/budget/reports) via a new
sendPerUserStatepath.Written by Cursor Bugbot for commit 75a5730. This will update automatically on new commits. Configure here.