### Fixed - **Cards not shown after browser refresh** — when the browser reconnected to the SSE stream after a completed scan, the scan_phase events in the replay buffer temporarily set S._m365ScanRunning = true (all running flags start at false after a page reload). The watchdog's loadHistorySession call fired in this window and bailed on the stale flag; once scan_done cleared the flag, _initialStatusChecked was already true so loadHistorySession was never retried. Fixed by having the sse_replay_done handler retry loadHistorySession(null) when no scan is running and S._historyRefScanId is still null after replay.
This commit is contained in:
1 parent
79e589b525
commit
f845a2f686
3 files changed
+11
-1
No files matched your search
@@ -155,6 +155,7 @@ Allows reviewing results from any past scan session without running a new scan.
|
||||
- **Cache invalidation** — `_sessions` and `_latestRefScanId` are module-level in `history.js`. `invalidateHistoryCache()` clears both. All three `*_done` SSE handlers in `scan.js` call `window.invalidateHistoryCache?.()` so the picker reflects the newest scan after completion.
|
||||
- **Re-scan diff** — `loadHistorySession` fetches the immediately preceding session's items after rendering the current session. Items present in the previous session but absent from the current one (compared by `id`) are tagged `_resolved: true` and appended after a `.resolved-divider` separator. `appendCard` in `results.js` adds `.card-resolved` (opacity 0.6), a green `✓ Resolved` badge, and hides the delete button for resolved items. `_setHistoryBanner` accepts an optional `resolvedCount` parameter and appends it to the banner label. Resolved items are NOT added to `S.flaggedData` — they are grid-only and cannot be bulk-selected or exported.
|
||||
- **Auto-load on page load** — `results.js` calls `window.loadHistorySession?.(null)` once when the SSE watchdog confirms `!status.running`. `null` resolves to the latest completed session via `_fetchSessions()[0].ref_scan_id`. The `_initialStatusChecked` guard ensures this fires at most once per page load.
|
||||
- **`sse_replay_done` retry** — `scan_phase` events replayed from a *completed* scan temporarily set `S._m365ScanRunning = true` (because all flags start at `false` after a page refresh). This causes the watchdog's `loadHistorySession` call to bail before `scan_done` clears the flag. The `sse_replay_done` handler in `scan.js` retries `loadHistorySession(null)` if no scan is running and `S._historyRefScanId` is still `null` after replay. Do not remove this retry — it is the only way to guarantee DB items are loaded when the watchdog fires in the middle of a replay.
|
||||
- **Mode transitions** — `startScan()` calls `window.exitHistoryMode?.()` before clearing the grid, so any history banner is dismissed and `S._historyRefScanId` is reset before SSE events start arriving.
|
||||
|
||||
## CPR cross-referencing — gdpr_db.py + routes/database.py + static/js/results.js
|
||||
@@ -199,6 +200,7 @@ Allows reviewing results from any past scan session without running a new scan.
|
||||
- **Two separate abort events** — `state._scan_abort` (M365 + file) and `state._google_scan_abort` (Google). `POST /api/scan/stop` sets **both**. `_check_abort()` inside `_run_google_scan` must use the module-level `_scan_abort` alias (`= state._google_scan_abort`), not `gdpr_scanner._scan_abort` (which is the M365 event). Do not conflate them — a Google-only scan must react to Stop, and `gdpr_scanner._scan_abort` is not the right event for that path.
|
||||
- **`_check_abort()` emits `google_scan_done`, not `scan_cancelled`** — when the Google thread detects the abort signal it broadcasts `google_scan_done` (with `cancelled: True`). Do NOT change this back to `scan_cancelled`. The `scan_cancelled` handler in the frontend unconditionally closes the SSE connection; if a new M365/file scan started while the old Google thread was still winding down, that would drop all remaining events from the new scan. `google_scan_done` is safe because its handler checks `!S._m365ScanRunning && !S._fileScanRunning` before closing the SSE.
|
||||
- **Google Drive uses a lazy generator, not `list()`** — `iter_drive_files()` is iterated directly (no `list()` wrapping) in both the non-delta path and the delta-fallback path. Wrapping in `list()` would block the thread — and the abort check — for the entire file enumeration. The delta start token is recorded *before* the iteration loop so it captures state at the right moment regardless of when the loop is interrupted.
|
||||
- **`scan_phase` replay sets running flags — handled by `sse_replay_done`** — the `scan_phase` handler sets `S._m365ScanRunning/S._googleScanRunning/S._fileScanRunning = true` whenever no flag is currently set and a matching source keyword is found in the phase text. On page refresh this fires during SSE replay of a completed scan (all flags start `false`), temporarily making the scan appear to still be running. This is intentional for live reconnection but harmless for the completed-scan case because `scan_done` clears the flag and `sse_replay_done` retries `loadHistorySession`. Do not remove the flag-setting logic from `scan_phase` — it is needed to detect reconnection to a genuinely running scan.
|
||||
|
||||
## Email sending — routes/email.py + m365_connector.py
|
||||
|
||||
|
||||
Reference in new issue
Block a user