feat(app): opt-in debug logging mode and safer, richer diagnostic bundles - #314
Merged
Conversation
Contributor
Coverage
Gate: passed - no coverage regression (epsilon 0.1 pp). |
pmaxhogan
added a commit
that referenced
this pull request
Aug 17, 2026
PR #314's "ui build + lint + unit" CI job failed in 38s at the prettier --check step (after pnpm install + lint, before test:unit and build): activity-debug-chip.test.ts and settings-pages.test.ts were hand-typed and not run through Prettier before the previous commit. No logic change, whitespace/wrapping only - re-verified lint, format:check, test:unit (793 passed), and build all pass locally in the workflow's exact step order. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019xKUm9vH4ifb5LHR5szy1v
…dles Closes #309, closes #204. instead of cloning GlobalSettings and patching one field, so a future secret-bearing field fails to compile here rather than leaking silently. Fixes three concrete leaks: pre/post_backup_hook command lines (a classic home for embedded secrets) are now redacted wholesale, custom_root_ca_path is hashed like every other path in the bundle, and proxy_url in PAC mode (a local file path, not a URL) is now hashed instead of passing the userinfo-strip-only path through untouched. The ProxyError Display leak the issue also flagged was already fixed by #208 - verified, not touched. always-visible amber warning, backed by a real runtime-reloadable tracing filter (logging.rs) that raises Driven's own crates to trace level while on. The toggle persists an epoch-ms expiry and auto-turns-off 24h after being enabled, enforced by a boot-time reconcile plus a periodic watchdog (debug_mode.rs) so the window is honoured even across a restart. The rolling log cap widens from 25 MB to 250 MB while debug mode is on. The diagnostic bundle gains a DEBUG_MODE.txt notice and an unredacted debug/engine_state.txt when debug mode is on - the one deliberate exception to the #204 redaction rules, gated on the user's explicit opt-in. Every bundle now also ships manifest.txt (entry name + size). Activity's export button shows an amber "Debug data included" chip while debug mode is on. Also closes the long-documented gap where global.log_level only exported RUST_LOG for the next launch - it now reloads the live filter too. Testing: 18 Rust redaction tests (leak-shaped fixtures for hooks, CA path, PAC-mode path, PAC-mode URL, and one full end-to-end fixture asserting the serialized bundle JSON), 5 debug_mode watchdog/expiry tests, 5 settings-persistence round-trip tests. cargo test -p driven-app --lib: 458 passed. cargo clippy --workspace --all-targets -- -D warnings: clean. cargo fmt --all -- --check: clean. pnpm vitest run: 793 passed across 60 files (new: activity-debug-chip.test.ts, plus PrivacyPage toggle tests in settings-pages.test.ts). vue-tsc --noEmit: clean. Linux visual baselines regenerated via `just visual-update` (privacy.png light+dark) and pass. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019xKUm9vH4ifb5LHR5szy1v
PR #314's "ui build + lint + unit" CI job failed in 38s at the prettier --check step (after pnpm install + lint, before test:unit and build): activity-debug-chip.test.ts and settings-pages.test.ts were hand-typed and not run through Prettier before the previous commit. No logic change, whitespace/wrapping only - re-verified lint, format:check, test:unit (793 passed), and build all pass locally in the workflow's exact step order. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019xKUm9vH4ifb5LHR5szy1v
…quit drain Rebases wave-1-debug-diag onto origin/main now that #310-#316 merged (#312's quit-path restructuring in particular). Structural follow-up: - The debug-logging-mode watchdog (debug_mode.rs) previously used the detached memlog.rs pattern (no shutdown tracking). #312 replaced the old shutdown_orchestrators() with a proper ShutdownHandles/ drain_shutdown_handles structure that every other periodic background task (updater, telemetry, iostat, and now #311's bottleneck sampler) registers into for a no-orphan quit drain. Re-homed the watchdog into that same structure: a new DebugModeRuntime (task + shutdown watch, no shared hub - the watchdog only reads/writes settings directly) on AppState, set_debug_mode_task/shutdown_debug_mode_task mirroring set_bottleneck_task/shutdown_bottleneck_task exactly, a debug_mode field on ShutdownHandles, and spawn_watchdog now runs the same select!-on-shutdown-or-tick loop bottleneck_hub/iostat_hub use instead of a bare loop. - Added app_state::tests::debug_mode_runtime_task_and_shutdown_round_trip, mirroring bottleneck's round-trip test. - privacy.png (light+dark) and 9 shell.spec.ts baselines (light+dark) regenerated via `just visual-update` (Docker) - the shell baselines drifted independently of this PR's own diff (same delta across every scenario in both themes), consistent with normal headless-Chromium rendering drift between visual-update runs; all 106 visual specs pass against the regenerated set. No other conflicts: README.md, dtos.rs, settings.rs's redaction code, en-US.json, Activity.vue, and fixtures.ts all auto-merged cleanly with #311's bottleneck-tile additions coexisting alongside this PR's debug logging toggle and diagnostic-bundle changes. Verified after rebase: cargo test -p driven-app --lib (494 passed), cargo clippy --workspace --all-targets -- -D warnings (clean), cargo fmt --all --check (clean), pnpm lint (0 errors), pnpm format:check (clean), pnpm test:unit (861 passed, 64 files), pnpm build / vue-tsc (clean). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019xKUm9vH4ifb5LHR5szy1v
pmaxhogan
force-pushed
the
wave-1-debug-diag
branch
from
August 18, 2026 17:16
1da421a to
aa7b8d7
Compare
pmaxhogan
enabled auto-merge (squash)
August 18, 2026 17:16
…ction
Both `seeded_repo()` test helpers (settings.rs, pre-existing; debug_mode.rs,
new in this PR) hand-rolled a temp directory via
`std::env::temp_dir().join(format!("...{nonce}-{:p}...", ...))` before
passing it to `SqliteStateRepo::open`. That is exactly the pattern
`rust/path-injection` flags in this repo (driven-ci-flakes memory, PR 151
precedent; also documented at src-tauri/Cargo.toml's `tempfile` dependency
comment) - CodeQL's dataflow can see straight through the inline `format!`
call, and the pointer-formatted nonce reads as attacker-observable data.
Switched both to `tempfile::tempdir().keep()` (an opaque external call
CodeQL's analysis does not see into, so the taint chain never forms),
keeping the `(SqliteStateRepo, PathBuf)` return shape unchanged so every
existing `cleanup(dir)` call site round-trips with no other edits. This is
the repo's established FIX (not a dismissal) for this exact pattern.
Also explains the refingerprinted `crates/driven-core/src/state/sqlite.rs`
alert this PR's CI run surfaced as "new": that file's `SqliteStateRepo::open`
sink is unchanged, but adding new callers (via the two seeded_repo() sites)
to the analyzed call graph re-triggers CodeQL's whole-program dataflow scan
and re-mints the alert number. Fixing the source pattern at both call sites
resolves it without a dismissal.
Verified: cargo test -p driven-app --lib (494 passed), cargo clippy
--workspace --all-targets -- -D warnings (clean), cargo fmt --all --check
(clean).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019xKUm9vH4ifb5LHR5szy1v
pmaxhogan
added a commit
that referenced
this pull request
Aug 18, 2026
🤖 I have created a release *beep* *boop* --- ## [2.12.0](v2.11.1...v2.12.0) (2026-08-18) ### Features * **app:** opt-in debug logging mode and safer, richer diagnostic bundles ([#314](#314)) ([33c281c](33c281c)) * **core:** allow nested backup sources when the parent excludes the child ([#294](#294)) ([0b62df9](0b62df9)) * **core:** live exclusion pickup and a visible pending-work queue ([#313](#313)) ([e6427c7](e6427c7)) * live bottleneck indicator on the Activity dashboard ([#311](#311)) ([2d9d763](2d9d763)) * **ui:** folder picker sort/filter/create/rename and exclusions size rollups ([#315](#315)) ([7e87341](7e87341)) ### Bug Fixes * **app:** never freeze on tray quit during a backup; quitting tray state; honest recovery status ([#312](#312)) ([f951cde](f951cde)) * clear the attention banner after a passing run and make source removal backend-aware ([#310](#310)) ([6d8e1ab](6d8e1ab)) * **s3:** honest per-source versioning across backends and multipart-upload leak sweep ([#316](#316)) ([d462592](d462592)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
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.
Summary
Closes #309, closes #204. Part of the v2.12.0 wave (PR5).
#204 (diagnostic bundle PII/secret leaks) -
redact_settings()used to cloneGlobalSettingsverbatim and patch onlyproxy_url. It now builds a field-for-fieldRedactedGlobalSettingsstruct, so a future secret-bearing field added toGlobalSettingsfails to compile here until someone decides how to redact it, instead of leaking silently. Fixes the three concrete leaks the issue named:pre_backup_hook/post_backup_hook(command lines - a classic home for embedded secrets) are now redacted wholesale (<hook-redacted: N chars>), not shipped raw.custom_root_ca_pathis now hashed through the same<path:hash>scheme the rest of the bundle already uses.proxy_urlin PAC mode (a local file path, not a URL) is now hashed instead of only having userinfo-stripping applied (which never matched a bare path).ProxyError'sDisplayembedding raw userinfo) was already fixed by fix(net): redact userinfo from PAC source in logs #208 - verified viagit blame, not touched again.#309 (debug logging mode) - a new Settings > Privacy & Data toggle ("Debug logging") with an always-visible amber warning panel (shown before the toggle is ever switched on, per the approved mockup), backed by:
logging.rs,tracing_subscriber::reload) - flipping the toggle now actually changes the live process's verbosity, no restart needed. This also closes a long-documented gap whereglobal.log_levelonly ever exportedRUST_LOGfor the next launch; it now reloads the live filter too (deferred while debug mode is active, so it doesn't undo the debug-mode filter).debug_mode.rs) that auto-turns the toggle off 24h after enabling - honoured across a restart, not just while the app keeps running. The watchdog is registered onAppStateand joined by fix(app): never freeze on tray quit during a backup; quitting tray state; honest recovery status #312's no-orphan quit drain (ShutdownHandles/drain_shutdown_handles), the same pattern feat: live bottleneck indicator on the Activity dashboard #311's bottleneck sampler uses.DEBUG_MODE.txtand an unredacteddebug/engine_state.txtwhile debug mode is on - the one deliberate exception to the Diagnostic bundle still ships PII and possible secrets in settings_redacted.json #204 redaction rules, gated on the user's explicit opt-in (every other bundle file stays redacted regardless).manifest.txt(entry name + size), a small bundle-usefulness improvement.Also in this PR
mainafter fix: clear the attention banner after a passing run and make source removal backend-aware #310-fix(s3): honest per-source versioning across backends and multipart-upload leak sweep #316 merged. Re-homed the debug-mode watchdog from a detachedmemlog.rs-style task into fix(app): never freeze on tray quit during a backup; quitting tray state; honest recovery status #312'sShutdownHandles/drain_shutdown_handlesno-orphan quit drain (newDebugModeRuntimeonAppState,set_debug_mode_task/shutdown_debug_mode_taskmirroringset_bottleneck_task/shutdown_bottleneck_task).rust/path-injectionfix (not a dismissal): two test helpers (settings.rs's pre-existingseeded_repo()and this PR's newdebug_mode.rsone) hand-rolled a temp dir viastd::env::temp_dir().join(format!(...))before feeding it toSqliteStateRepo::open- exactly the pattern this repo's CodeQL rule flags (see thetempfiledependency comment insrc-tauri/Cargo.toml, and PR 151 precedent). Switched both totempfile::tempdir().keep(), an opaque external call CodeQL's dataflow can't see into, so the taint chain never forms.cargo update -p h2(0.4.15 -> 0.4.16), lockfile-only, noCargo.tomlchanges. This advisory is unrelated to this PR's own diff (git diffagainst the pre-PR base shows zeroCargo.lockchanges before this commit) and would failcargo denyrepo-wide onmaintoo; landing it here unblocks this PR'scargo denycheck and delivers the fix tomainin the same step.Test plan
cargo test -p driven-app --lib- 494 passed (18 Diagnostic bundle still ships PII and possible secrets in settings_redacted.json #204 redaction tests with leak-shaped fixtures, incl. one asserting the full serialized bundle JSON end-to-end; 5 debug-mode watchdog/expiry tests; 6 settings-persistence round-trip tests; 1AppStatedebug-mode task/shutdown round-trip test)cargo clippy --workspace --all-targets -- -D warnings- cleancargo fmt --all -- --check- cleancargo build --workspace --tests- cleancargo deny check- clean (advisories ok, bans ok, licenses ok, sources ok)pnpm lint/pnpm format:check/pnpm test:unit(861 passed, 64 files) /pnpm build(vue-tsc + vite) - all clean, run in the CI job's exact orderjust visual-update(Docker) -privacy.png(light+dark) plus 9shell.spec.tsbaselines (light+dark) that had drifted independently of this PR; all 106 visual specs pass🤖 Generated with Claude Code
https://claude.ai/code/session_019xKUm9vH4ifb5LHR5szy1v