fix(datastore): apply privacy filters on save and startup - #662
fix(datastore): apply privacy filters on save and startup#662TimeToBuildBob wants to merge 6 commits into
Conversation
The webui saved settings.privacy_filters, but DatastoreWorker started with an empty engine and never reloaded on SetKeyValue. Insert and heartbeat paths filtered correctly against rules that were never loaded, so drop/redact rules appeared to do nothing (ActivityWatch#659). Reload the in-memory engine when that key is written or deleted, load it at worker startup, and keep RefreshPrivacyFilter as an explicit path.
Greptile SummaryThe PR synchronizes the datastore worker’s in-memory privacy-filter engine with persisted settings during startup, setting changes, deletion, and transaction recovery.
Confidence Score: 3/5The PR is not yet safe to merge because commit-recovery read errors can leave the active privacy engine reflecting a rolled-back deletion and allow sensitive events to be stored. The reply claiming the recovery issue was fixed overlooks the rolled-back-delete counterexample: settings mutations update the engine from the uncommitted transaction, while a failed post-rollback reload now preserves that transaction-derived state rather than restoring the durable rules. Files Needing Attention: aw-datastore/src/worker.rs Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
S[Privacy setting write or delete] --> T[SQLite transaction]
T --> R[Reload in-memory engine from transaction]
R --> C{Commit succeeds?}
C -->|Yes| E[Engine and durable setting agree]
C -->|No| D[Reload from durable connection]
D --> N[Process later inserts and heartbeats]
Reviews (3): Last reviewed commit: "fix(datastore): only clear privacy rules..." | Re-trigger Greptile |
The reopen assertion already passed on windows-latest; remove_file then hit ERROR_SHARING_VIOLATION because the worker thread still held the SQLite handle. Unique-ify the temp db and treat cleanup as best-effort.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #662 +/- ##
==========================================
+ Coverage 70.81% 78.85% +8.04%
==========================================
Files 51 66 +15
Lines 2916 5525 +2609
==========================================
+ Hits 2065 4357 +2292
- Misses 851 1168 +317 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
SystemTime::now().as_nanos() may return the same value when called in quick succession on macOS due to clock precision, causing multiple databases to collide on the same file path. This leads to concurrent initialization races when Datastore objects try to migrate the same database simultaneously. Replace the timestamp with an atomic counter to guarantee unique paths even when databases are created rapidly within the same test.
A SetKeyValue/DeleteKeyValue on settings.privacy_filters reloads the in-memory engine from the still-open transaction. If the batched commit later fails, SQLite rolls back but the engine keeps the rules from the rolled-back write, so subsequent inserts filter against state that no longer exists on disk — including running unfiltered after a rolled-back delete. Reload from the durable connection on the commit-failure path so the engine matches what actually persisted.
…mestamp) The counter alone is unique within a process but not across runs: the tests never remove their temp dbs, so a PID reuse restarts the counter at 0 and can reopen a leftover file. Keeping the timestamp covers that. Makes the file byte-identical to ActivityWatch#655, which fixes the same macOS flake on master, so the two land in either order without a conflict.
macOS CI failure was the known
|
|
@greptileai review |
The reload treated every get_key_value error as "key deleted" and emptied the engine. A transient InternalError from the query would therefore disable filtering entirely and let the events these rules exist to exclude get stored. Clear only on NoSuchKey; warn and keep the current engine otherwise.
|
@greptileai review |
Summary
Privacy filter rules saved from the webui never actually applied.
DatastoreWorkerstarts with an emptyPrivacyFilterEngine, insert/heartbeat paths do filter against that engine, andRefreshPrivacyFilterreloadssettings.privacy_filters— but nothing called refresh after save, and startup never loaded the persisted key. The UI could save drop/redact rules all day; matching events were stored unchanged.Fixes #659.
What changed
settings.privacy_filtersis written or deleted (SetKeyValue/DeleteKeyValue).RefreshPrivacyFilteras an explicit path (HTTP settings endpoints still call it as belt-and-suspenders).set_key_valueactually drops a matching insert (no explicit refresh), and the same rule still applies after reopen.Test plan
cargo test -p aw-datastore --test datastore