feat: session filter restore, error nav, large-file mode, backend filtering, logging, CSP hardening#201
Open
adamgell wants to merge 2 commits into
Open
feat: session filter restore, error nav, large-file mode, backend filtering, logging, CSP hardening#201adamgell wants to merge 2 commits into
adamgell wants to merge 2 commits into
Conversation
…tering, logging, CSP hardening Seven application-level improvements from static code review: fix(session): restore FilterClause[] into useFilterStore on session open - session.ts validates clauses as typed FilterClause[] - session-restore.ts calls setClauses() after files load; AppShell re-applies naturally - Regression tests: src/lib/session.test.ts, src/lib/session-restore.test.ts feat(logging): add tauri-plugin-log + open logs folder (resolves #193) - Initialized tauri-plugin-log in lib.rs; logs written to platform log dir - app_config.rs: open_app_logs_folder IPC command - AboutDialog: 'Open Logs Folder' button and test coverage feat(nav): next/previous error navigation (F8 / Shift+F8) - Toolbar Prev/Next Error buttons; disabled in large-file mode - log-store: navigates filtered visible-row order, wraps at boundaries - use-keyboard: F8/Shift+F8 shortcuts feat(perf): large-file mode (>50 MB threshold) - Backend detects large files in file_ops.rs; emits LargeFileModeInfo metadata - Frontend disables sort, auto-fit, full-text find; shows inline banner + status badge - tab-snapshot-cache preserves large-file mode across tab switches feat(perf): backend session-keyed filtering - AppState holds parsed-entry registry (HashMap<String, Vec<LogEntry>>) - apply_filter accepts optional sessionKey; falls back to raw entries if stale - filter-store: mergeFilteredIds for incremental live-tail appends - AppShell dispatches session-keyed filter; merges new tail rows incrementally fix(security): replace null CSP with restrictive content security policy - tauri.conf.json: default-src 'self'; img-src asset: data:; style-src 'unsafe-inline' - dev bundle adds script-src 'unsafe-eval' for Vite HMR ci: add Playwright smoke tests to CI frontend job - e2e/smoke.spec.ts tightened with deterministic assertions - cmtrace-ci.yml runs npm run test:e2e after Vitest Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR delivers a set of end-to-end improvements across the CMTrace Open Tauri backend and React frontend, focused on session persistence (filters), usability for troubleshooting (error navigation), performance safeguards for large logs, backend-assisted filtering, and operational hardening (logging, CSP, CI smoke tests).
Changes:
- Fixes session restore so saved filter clauses are validated/sanitized and re-applied after files load, with new regression tests.
- Adds large-file mode metadata from the backend and disables expensive UI features (find/sort/autofit/filtering) to protect responsiveness; introduces Next/Prev Error navigation.
- Introduces backend session-keyed filtering plumbing plus application logging (“Open Logs Folder”), CSP hardening, and Playwright smoke tests in CI.
Reviewed changes
Copilot reviewed 32 out of 32 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/cmtrace-ci.yml |
Adds Playwright install + e2e smoke test run in CI. |
e2e/smoke.spec.ts |
Makes smoke tests more deterministic (shared open helper, tighter assertions). |
src-tauri/Cargo.toml |
Adds tauri-plugin-log dependency. |
src-tauri/src/lib.rs |
Initializes log plugin, emits startup/log-dir diagnostics, registers new IPC commands. |
src-tauri/src/state/app_state.rs |
Adds parsed-entry session registry in app state (register/get/release). |
src-tauri/src/commands/app_config.rs |
Adds open_app_logs_folder command to open platform log directory in file manager. |
src-tauri/src/commands/file_ops.rs |
Adds large-file mode evaluation/metadata and wraps parse responses with backend session metadata. |
src-tauri/src/commands/filter.rs |
Updates apply_filter to accept optional session key and resolve entries via AppState. |
src-tauri/src/parser/dns_audit.rs |
Ensures parse results include large_file_mode: None and tweaks logging/formatting. |
src-tauri/tauri.conf.json |
Replaces null CSP with restrictive production + dev CSP policies. |
crates/cmtraceopen-parser/src/models/log_entry.rs |
Adds LargeFileModeMetadata and optional large_file_mode fields to parse results. |
crates/cmtraceopen-parser/src/parser/mod.rs |
Sets default large_file_mode: None in parser output. |
src/stores/log-store.ts |
Adds large-file mode state, visible error navigation state, and disables find when large-file mode is active. |
src/stores/log-store.test.ts |
Adds tests for large-file mode state and visible error navigation behavior. |
src/stores/filter-store.ts |
Adds backend filter invocation helper, session-key fallback behavior, and mergeFilteredIds. |
src/stores/filter-store.test.ts |
Adds tests for backend filtering behavior (session key, fallback, forced raw entries) and merge helper. |
src/lib/commands.ts |
Normalizes wrapped backend parse responses; adds parsed-entry session + open logs folder commands. |
src/lib/log-source.ts |
Propagates backend session keys into sources, caches large-file mode, and registers aggregate sessions. |
src/lib/session.ts |
Sanitizes/restores typed filter clauses from saved sessions; refactors filter validation. |
src/lib/session.test.ts |
New tests validating filter clause sanitization/back-compat in sessions. |
src/lib/session-restore.ts |
Restores filter clauses via filter-store after file load (alongside find/highlight state). |
src/lib/session-restore.test.ts |
New tests verifying filter clause restore timing and sanitization behavior. |
src/lib/tab-snapshot-cache.ts |
Extends cached tab snapshots with large-file mode metadata. |
src/components/dialogs/AboutDialog.tsx |
Adds “Open Logs Folder” action with user-friendly error display. |
src/components/dialogs/AboutDialog.test.tsx |
Adds tests for the new logs folder action and error handling. |
src/components/layout/AppShell.tsx |
Moves filtering to backend helper, supports incremental tail filtering, disables filtering in large-file mode. |
src/components/layout/FindBar.tsx |
Disables find UI/actions in large-file mode and adds explanatory tooltips/message. |
src/components/layout/StatusBar.tsx |
Shows large-file mode badge and status text when active. |
src/components/layout/Toolbar.tsx |
Adds Prev/Next Error actions and refines filter button tooltip/disable messaging. |
src/components/log-view/LogListView.tsx |
Disables sorting/autofit in large-file mode; reports visible IDs to enable error navigation. |
src/hooks/use-keyboard.ts |
Adds F8 / Shift+F8 keyboard shortcuts for error navigation gated by command state. |
src/types/log.ts |
Adds TS types for backend session metadata and large-file mode metadata on parse results/sources. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+115
to
+120
| function getErrorNavigationDisabledReason( | ||
| activeView: WorkspaceId, | ||
| isLoading: boolean, | ||
| entriesCount: number, | ||
| visibleErrorEntryCount: number | ||
| ): string | null { |
| lastAppliedSignatureRef.current = null; | ||
| appliedFilterSnapshotRef.current = null; | ||
| setFilteredIds(null); | ||
| setIsFiltering(false); |
Comment on lines
+117
to
+121
|
|
||
| fn register_parsed_entries_backend_session( | ||
| state: &AppState, | ||
| entries: &[LogEntry], | ||
| ) -> Result<Option<ParsedEntriesSessionMetadata>, crate::error::AppError> { |
Comment on lines
+92
to
+96
|
|
||
| Ok(sessions | ||
| .get(session_key) | ||
| .map(|session| session.entries.clone())) | ||
| } |
Comment on lines
+249
to
+253
| if (direction === "next") { | ||
| for (const errorId of state.visibleErrorEntryIds) { | ||
| if (state.visibleEntryIds.indexOf(errorId) > selectedVisibleIndex) { | ||
| return errorId; | ||
| } |
Comment on lines
+390
to
+392
| let backend_session = | ||
| register_parsed_entries_backend_session(state.inner(), &result.entries)?; | ||
|
|
Comment on lines
+456
to
+463
| const aggregateView = buildAggregateView(allResults); | ||
| const backendSession = await registerAggregateEntriesSession( | ||
| aggregateView.allEntries | ||
| ); | ||
| const sourceWithSession = withSourceSessionKeys(source, { | ||
| sessionKey: null, | ||
| aggregateSessionKey: backendSession?.sessionKey ?? null, | ||
| }); |
Comment on lines
+315
to
+318
| const sourceWithSession = withSourceSessionKeys(source, { | ||
| sessionKey: result.backendSession?.sessionKey ?? null, | ||
| }); | ||
| state.setActiveSource(sourceWithSession); |
Comment on lines
+53
to
+57
| function buildClauseSignature(clauses: FilterClause[]): string { | ||
| return clauses | ||
| .map((clause) => `${clause.field}:${clause.op}:${clause.value}`) | ||
| .join("|"); | ||
| } |
Comment on lines
+128
to
+136
| const appendedEntries = entries.filter((entry) => entry.id > appliedSnapshot.maxEntryId); | ||
|
|
||
| if (appendedEntries.length === 0) { | ||
| return null; | ||
| } | ||
|
|
||
| return appliedSnapshot.entryCount + appendedEntries.length === entries.length | ||
| ? appendedEntries | ||
| : null; |
| tags: None, | ||
| } | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.