Skip to content

Split days by local time zone, fix collector deadlock and secret exposure - #21

Merged
Backtthefuture merged 6 commits into
mainfrom
optimize/collector-timezone-privacy
Sep 25, 2026
Merged

Backtthefuture merged 6 commits into
mainfrom
optimize/collector-timezone-privacy

Conversation

@Backtthefuture

@Backtthefuture Backtthefuture commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Fixes a collector deadlock, a secret exposed in process arguments, and a data race in quota fetching. Days are now split in the system time zone instead of a fixed Asia/Shanghai, and routine collections cost much less.

Behavior change: users outside UTC+8 will see their daily totals re-split by local midnight after upgrading. Collector caches record their time zone and rebuild once when it changes.

  • Fixes: the Codex SQLite fallback read its pipe only after sqlite3 exited, so large results deadlocked. GLM/Kimi/Grok keys were passed to security -w on the command line; they now go through stdin. Quota results were read without the lock while late providers could still write.
  • Performance: appended Claude Code transcripts are read from the last complete line (133 ms → 12 ms on a 21 MB active session). SQLite is queried in process through the C API instead of spawning sqlite3 (CC Switch 66 ms → 0.1 ms).
  • Structure: UsageCollector.swift is split into Services/Collector/. Cost estimates are an ordered price rule table with the same prices.
  • Privacy docs: PRIVACY.md lists every network request. The privacy page no longer says there is no network use by default: update checks are on by default, and the rank board is only read, never uploaded to.
  • Repo: the legacy Python prototype moved to legacy/. Release history moved from README to CHANGELOG.md.

Validation: collecting real local data (62 days, 1.54B tokens) with the original and new code in the same time zone gives identical snapshots. Each fix has a reproduction that failed before the change and passes after it (deadlock, argv leak, ThreadSanitizer). New fixture checks cover time zones, incremental Claude reads, and the settings Codable implementation, and each was confirmed to fail on an injected bug. All fixture checks and the app build pass locally, and CI passed all 117 XCTests, including the new time zone case in UsageSnapshotRefreshPolicyTests.

🤖 Generated with Claude Code

Backtthefuture and others added 6 commits September 24, 2026 08:50
- Store GLM/Kimi/Grok keys through `security -i` on stdin, so the secret
  never appears in process arguments visible to `ps`. Existing keychain
  items stay readable without a new access prompt.
- Read the quota results under the same lock the provider threads use;
  providers that miss the 12 second deadline can still be writing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Split usage into days with the system time zone (TokenStepClock) instead
  of a hard-coded Asia/Shanghai. Collector caches record their zone and are
  rebuilt when it changes; the app recollects on system zone changes.
- Read appended Claude Code transcripts incrementally from the last
  complete line, with a prefix fingerprint to detect rewrites (133ms -> 12ms
  per collection on a 21MB active session).
- Query SQLite in process with the C API instead of spawning sqlite3
  (CC Switch collection 66ms -> 0.1ms). This also fixes a deadlock where the
  Codex SQLite fallback filled the pipe buffer before being read.
- Split UsageCollector.swift into Services/Collector/ by responsibility and
  turn cost estimates into an ordered price rule table (same prices).
- Emit Claude records in file order so cost sums are deterministic.
- Remove stale .dat.nosync leftovers from interrupted atomic writes.
- Add fixture checks for time zones, incremental Claude reads and the
  hand-written settings Codable, plus script/test_all.sh as one entry point.
  Tests pin TOKENSTEP_TIMEZONE=Asia/Shanghai.

Accounting on real local data is identical to the previous version when
run in the same time zone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PRIVACY.md now lists each request TokenStep makes, when, and what it sends.
- The privacy page no longer claims no network use by default: update
  checks are on by default, and the rank board is read-only (TokenStep
  never uploads to it).
- Label the Codex SQLite fallback as approximate in data source status.
- Fix AGENT_SUPPORT (archived_sessions is not read) and point the PRD at
  the current collector layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Swift app replaced it and nothing builds or tests it. Icon assets stay
in TokenUsageMenuApp/assets because the Swift app bundles them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README keeps a short latest-version note and links to CHANGELOG.md, which
holds the per-version sections unchanged. The release guide now lists the
documents to update for each release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add release notes, the CHANGELOG entry, README download links, and the
default build version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Backtthefuture
Backtthefuture merged commit 3a14f5c into main Sep 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant