feat(cli): add privacy-safe activity summaries - #116
Conversation
Greptile SummaryThe PR adds a locally aggregated
Confidence Score: 3/5The PR should not merge until browser buckets with unknown hostname metadata can no longer disclose another machine's domain activity in a host-specific summary. The new selector assigns every legacy unknown-host browser bucket to any requested hostname, so shared-server deployments can mix another machine's overlapping browser activity into privacy-oriented output. Files Needing Attention: aw_client/summary.py and tests/test_summary.py
|
| Filename | Overview |
|---|---|
| aw_client/summary.py | Adds bucket discovery and summary formatting, but unknown-host bucket inclusion can mix browser activity across machines. |
| aw_client/queries.py | Adds bounded server-side category, application, and domain aggregation using existing canonical event semantics. |
| aw_client/cli.py | Adds the summary command and consistently reuses the active client for category settings. |
| aw_client/classes.py | Generalizes category-settings retrieval to accept a compatible caller-provided client while preserving fallback behavior. |
| tests/test_summary.py | Covers aggregation, redaction, formatting, and CLI output, but codifies globally accepting unknown-host browser buckets. |
| README.md | Documents valid summary invocations, output sensitivity, and application/domain omission controls. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
CLI[summary command] --> Buckets[Discover browser buckets]
Buckets --> Query[Build privacySummary query]
Settings[Load category settings through active client] --> Query
Query --> Server[Local ActivityWatch aggregation]
Server --> Normalize[Normalize bounded result]
Normalize --> JSON[Provider-neutral JSON]
Normalize --> Table[Human-readable table]
Reviews (1): Last reviewed commit: "feat(cli): add privacy-safe activity sum..." | Re-trigger Greptile
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
@TimeToBuildBob check this out |
|
Greptile's concern is valid — wanted to flag the specific issue clearly. In if bucket_hostname not in (None, "", "unknown", hostname):
continueOn a shared AW server (multiple machines reporting to one instance), a legacy browser bucket from machine B with no hostname metadata would be included in machine A's privacy-safe summary. That's a meaningful privacy leak for the exact use case this PR targets. Simple fix: exclude unknown-host buckets by default and add an explicit Everything else looks solid — the redaction policy, schema versioning, AFK filtering, and test coverage are all well-done. |
find_browser_buckets() treated buckets reporting no hostname, an empty hostname, or "unknown" as matching any host. On a server collecting from several machines, a legacy browser bucket belonging to machine B was folded into machine A's summary, leaking another host's browsing domains through a command whose purpose is a privacy-safe summary. Exclude unattributed buckets by default and add --include-legacy-buckets for single-machine servers that want them counted. Record the choice in the payload's redaction block so a consumer can tell which policy produced it. The existing test asserted the leaking behaviour was correct; it now covers the default exclusion, with a second test for the opt-in path.
dfdbd09 to
20cdf83
Compare
|
Good catch, thanks — fixed.
Updated the test that asserted unknown-host buckets were accepted, and added one for the opt-in path. Also recorded the choice in the redaction block as Rebased on master to clear the conflict with #117. |
|
Fix looks correct — now rejects unattributed hostnames by default and the |
|
Review cleanup complete: the host-isolation finding is fixed on the current head ( The Build, CodeQL, Examples, and Lint workflow runs currently show |
Summary
aw-client summaryfor bounded, AFK-filtered category, application, and domain totalsWhy
ActivityWatch's agent/AI guidance recommends locally aggregated, review-before-send context instead of raw exports. Today, users need to write the query and normalization code themselves. This command turns that workflow into a reproducible CLI path without exposing raw titles, full URLs, document names, message subjects, or raw event history.
Related: ActivityWatch/activitywatch#1388
Related: ActivityWatch/aw-webui#925
Validation
ruff check aw_client tests/test_summary.pyruff format --check aw_client tests/test_summary.pymypy aw_client tests/test_summary.pyXDG_DATA_HOME=/tmp/activitywatch-test-data pytest -q tests/test_summary.py tests/test_auth.py tests/test_requestqueue.py— 17 passed