Skip to content

feat(telemetry): report safe app setting values - #866

Merged
devswha merged 4 commits into
mainfrom
feat/telemetry-settings-values
Oct 12, 2026
Merged

devswha merged 4 commits into
mainfrom
feat/telemetry-settings-values

Conversation

@devswha

@devswha devswha commented Oct 12, 2026

Copy link
Copy Markdown
Owner

Change

Expand install/update telemetry from changed appearance-setting names to actual, allowlisted app setting values. Branched from current main (55cfcfbf).

Plan implemented

  • Define one shared, strict schema and an explicit browser projection: 43 scalar setting values plus 7 customization flags/counts.
  • Carry the latest browser snapshot through the local API, persisted sender state, event preview and receiver. Store validated JSON in D1 and document per-setting distribution queries.
  • Refresh the notice and translations, then verify schema boundaries, HTTP behavior and the real browser flow.

Raw custom fonts, shortcut/key-bar contents, quick-reply text and account identifiers/order are excluded. Custom settings contribute only flags/counts. Future Settings fields require an explicit collection decision; unknown or malformed telemetry fields are rejected.

NOTICE_VERSION is now 3. Acknowledgement requires that exact version, so an old open page cannot acknowledge the expanded notice. Existing opt-outs, environment blocks, the ten-minute grace period and install/update-only delivery remain unchanged. Settings changes do not create additional events once the version has been counted. The snapshot is the last reporting browser's settings, not per-device/person tracking.

The demo intentionally retains its existing telemetry 404 and sends nothing.

Receiver deployment order

Before releasing the app: add the settings column to the existing D1 table using the command in telemetry/README.md, then deploy the Worker. Historical rows are preserved. This PR does not deploy the Worker or access production telemetry data.

Validation

  • bun run check fast — passed: workflow syntax, generated types, TypeScript, production build; 2,919 unit tests passed, 8 skipped, 0 failures across 218 files.
  • bun run check run bun test ./server/api.contract.test.ts -t 'telemetry API' — 3 passed, 28 assertions. Covers full snapshots, malformed/private-field rejection, version-bound notice acknowledgement, origin/header/auth protection and opt-out.
  • bun run check run --build bun scripts/telemetry-regression.ts — passed against an isolated herdr/server with a fake external transport. Verifies the updated notice, safe server-confirmed preview, non-default-to-non-default setting changes and Turn off preventing pending delivery. Registered in the existing UI regression suite.
  • git diff --check — passed.

Receiver tests exercise SQLite persistence/deduplication, historical table upgrade, README distribution queries, bounded payloads and rejection of unsafe snapshots. No test sends to the production telemetry endpoint.

Full integration/browser lanes and native Windows CI were not run locally. Vite retains its existing large-chunk warning; no warnings were suppressed.

@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: devswha/herdr-web-ui/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a0ab7e61-aa4e-4202-9da7-2c58dc2984d0

📥 Commits

Reviewing files that changed from the base of the PR and between 9945230 and 358bd7a.


📒 Files selected for processing (13)
  • CHANGELOG.md
  • scripts/telemetry-regression.ts
  • scripts/ui-regression.ts
  • shared/telemetry.ts
  • src/components/TelemetryControls.tsx
  • src/lib/api.test.ts
  • src/lib/i18n.ja.ts
  • src/lib/i18n.ko.ts
  • src/lib/i18n.tr.ts
  • src/lib/i18n.zh.ts
  • src/lib/settings.ts
  • telemetry/worker.test.ts
  • telemetry/worker.ts

🚧 Files skipped from review as they are similar to previous changes (5)
  • src/lib/i18n.ja.ts
  • src/lib/i18n.zh.ts
  • CHANGELOG.md
  • src/lib/i18n.ko.ts
  • src/lib/i18n.tr.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.



📝 Summary

Summary by CodeRabbit

  • Changed
    • Anonymous install and update reports now include an allowlisted snapshot of app settings, including default choices. Custom fonts, shortcuts, layouts, and replies are represented only by flags or counts—not their contents.
    • The expanded notice explains what is collected and excluded. Existing opt-outs remain unchanged, and older installs must acknowledge the notice before reporting resumes.
  • Documentation
    • Updated telemetry disclosures and guidance to describe the settings snapshot and its limits, including that it may link events and does not guarantee anonymity.

Walkthrough

Telemetry now sends validated settings snapshots instead of names of changed settings. The app, server, and Worker use the snapshot format. The notice, database schema, documentation, and regression coverage are updated.

Changes

Telemetry Settings Snapshots

Layer / File(s) Summary
Define and project settings snapshots
shared/telemetry.ts, shared/protocol.ts, src/lib/settings.ts, src/lib/settings.test.ts
The shared contract defines allowed snapshot fields and validation. The settings helper builds snapshots with customization flags and counts. Tests cover snapshot contents and invalid values.
Submit snapshots from the app
src/components/TelemetryControls.tsx, src/lib/api.ts, src/lib/api.test.ts, scripts/telemetry-regression.ts, scripts/ui-regression.ts, src/lib/i18n.*.ts, docs/guide.md, CHANGELOG.md
The UI submits the current snapshot and notice version, and refreshes status when settings change. API and browser tests, localized text, and documentation cover the updated reporting behavior.
Validate and queue telemetry snapshots
server/telemetry.ts, server/telemetry.test.ts, server/api.contract.test.ts, server/AGENTS.md
The server validates snapshot payloads and notice acknowledgements, persists snapshots, and includes them in install or update events. Tests cover validation, previews, persistence, and notice upgrades.
Validate and store snapshots in the Worker
telemetry/worker.ts, telemetry/schema.sql, telemetry/README.md, telemetry/worker.test.ts
The Worker validates snapshots and stores them as JSON in the settings column. Migration instructions, analysis queries, and tests cover fresh and existing databases.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature


Merge Risk: ⚪ Minimal · up to 358bd

No actionable issue remains from the reviewed changes. Complete the documented database migration before deploying the Worker.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 18 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the main change: reporting safe application setting values in telemetry.
Description check Passed The description includes the required Change and Validation sections. It explains the behavior, exclusions, migration order, compatibility conditions, test coverage, passed checks, and known unrun tes…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Docstring Coverage

Explanation

Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 18 files. (1 skipped: 1 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR






🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

devswha and others added 2 commits October 12, 2026 16:21
…unknown event fields

Review follow-ups on #866 (Codex astra medium, 2026-10-12), with the two
settings #811 added meanwhile:

- The browser posted its settings snapshot to the local server as soon as the
  app was unlocked, before the version-3 notice and whatever the switch or the
  environment said. Both producers (the notice line and Settings → About) now
  read the server's status first and tell the snapshot only while telemetry is
  on, not blocked and the notice seen; the first snapshot rides with the
  acknowledgement, and turning the switch on brings the snapshot the browser
  kept to itself. Off or blocked, About still shows the switch and the preview
  from the status alone.
- The receiver refuses an event body with a field no sender has ever had, so a
  misspelled or foreign field is a 400 instead of silently dropped; the
  `changed_settings` list of senders before 0.4.9 is still accepted and not
  stored.
- `pageOverlapRows` (0-100) and `chatPageKeys` (#811) join the schema and the
  projection: 45 values and 7 flags/counts. The strict receiver means the
  Worker must be deployed before the app release that adds a key, or events
  are refused and retried unreported.
- `voiceLanguage` stays in the allowlist: an explicit preference from a fixed
  list, noted in the review as the one value naming a region beyond the UI
  language.
- telemetry regression: the first snapshot is the acknowledgement's, and an
  opted-out page sends none on reload; receiver tests for the refused field and
  the legacy sender.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@devswha

devswha commented Oct 12, 2026

Copy link
Copy Markdown
Owner Author

Merge-session review (Codex astra medium, 2026-10-12); follow-ups pushed as 358bd7a on top of a merge of current main (6b108cd, no conflicts):

  • Snapshot only where an event may go. Both producers (the notice line and Settings → About) posted the settings snapshot to the local server as soon as the app was unlocked, before the version-3 notice and whatever the switch or the environment said. They now read the status first and tell the snapshot only while telemetry is on, not blocked and the notice seen; the first snapshot rides with the acknowledgement, and turning the switch on brings the snapshot the browser kept to itself. Off or blocked, About still shows the switch and the preview from the status alone. The browser regression checks the ordering and that an opted-out page sends none on reload.
  • Receiver refuses unknown event fields. A body with a field no sender has ever had is a 400 instead of silently dropped; the changed_settings list of senders before 0.4.9 is still accepted and not stored.
  • feat(shortcuts): unify pane paging with configurable overlap #811's two settings join the schema (pageOverlapRows 0-100, chatPageKeys): 45 values and 7 flags/counts. The strict receiver means the Worker must be deployed before an app release that adds a Settings key, or events are refused and stay unreported (logged "was not delivered", retried later).
  • voiceLanguage kept: an explicit preference from a fixed list; the review noted it as the one value naming a region beyond the UI language.

Verified locally: typecheck, build, unit tests, the telemetry contract tests against a live herdr, the telemetry browser regression with a fresh build. The earlier CI failures on 9945230 were the Docker rate limit in the ssh job and the prompt-dock worker-load flake; both passed on rerun.

@devswha
devswha merged commit 10fd26f into main Oct 12, 2026
17 checks passed
@devswha
devswha deleted the feat/telemetry-settings-values branch October 12, 2026 07:34
devswha added a commit to demrom/herdr-web-ui that referenced this pull request Oct 12, 2026
…pshot

devswha#866's schema asks for a collection decision on every new Settings key: attachLimit is a bounded
integer (1-50), so it is reported like the other numbers. 46 values and 7 flags/counts now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
devswha added a commit that referenced this pull request Oct 13, 2026
…try key (#948)

## Change

Two release-time mistakes that keep coming back now fail CI instead of
relying on memory: forgetting to raise the remote bundle version, and
releasing before the telemetry Worker has been deployed. Both checks
live in `scripts/release-guards.ts`, which runs in CI's **Fast checks**
(after `check fast`, once a shallow fetch has pulled in the tags) and in
the **Release** preflight (`--release X.Y.Z`).

A tree counts as a release when its `package.json` version has no
`v<version>` tag yet: a release PR, `main` between that PR's merge and
the Release run, and the Release run itself. Every other tree passes at
once, so feature PRs are not affected.

### Remote bundle version
- The inputs are what `build-remote-bundle.ts` packs: `server/` and
`shared/` (without `*.test.ts`, `*.md` and `server/fixtures/`),
`bun.lock`, `patches/`, the builder itself, and the dependency fields of
`package.json`. `dist/` is left out: the connection server serves the
page, and the bridge never does.
- Baseline: the `remote-vN` tag for the `REMOTE_BUNDLE_VERSION` in the
tree. If that tag exists and the inputs differ from it, the check fails
and says: raise N to N+1 in `shared/machines.ts`, then push
`remote-v(N+1)` after the merge and before Release. If the tag does not
exist yet (N was raised in this PR), the PR passes. The Release run
fails until `remote-vN` is published from a tree with these same inputs.
It also fails when N is lower than an existing `remote-vM`.
- Tested on past releases: v0.4.5 to v0.4.8 pass. **v0.4.4 would have
failed**: it shipped `server/index.ts`, `server/prompt.ts`,
`server/conversation.ts`, `bun.lock` and others with no new bundle
(remote-v23 was cut at v0.4.3).

### Telemetry Worker
- Parity between client and Worker already holds at compile time: the
Worker validates with `shared/telemetry.ts`, and
`telemetrySettingsSnapshot` must cover every Settings field. A new unit
test in `src/lib/settings.test.ts` adds a clear failure message on top:
it lists each key the app sends that the Worker refuses, and the
reverse. The message says to add the key to `TelemetrySettings` and
`TELEMETRY_SETTINGS_VALIDATORS` and to the worker.test.ts fixture, then
deploy the Worker before releasing. `TELEMETRY_SETTINGS_KEYS` is
exported for this test.
- What the code alone cannot show is whether the Worker was deployed.
`telemetry/deployed.json` stores the sha256 of `telemetry/worker.ts` +
`shared/telemetry.ts` as last deployed. A release whose sources differ
fails and says to deploy (telemetry/README.md), run `bun
scripts/release-guards.ts --worker-deployed` and commit the file.
**Starting value:** the v0.4.8 sources. #866 and #863 changed the schema
after that, so the next release PR will fail this check until the Worker
is deployed and the file is updated. That deploy is already planned
before the next release, so the failure is intended.

### Release metadata
- `server/release-notes.test.ts` already requires patch notes in every
language, but only for versions that have a CHANGELOG heading.
`release.yml` checked the version itself only after merge. The guard now
runs the same `releaseNotes()` check on the release PR, so a version
bump without a CHANGELOG section, without a full
`release-summaries.json` entry, or with a mismatched `herdr-plugin.toml`
fails before merge.

Docs: one paragraph in docs/development.md "Releasing" (the language
list there now includes `tr` as well), one line in telemetry/README.md
Deploy, one pointer in scripts/AGENTS.md. No CHANGELOG entry, since
users see no change.

## Validation
- `bun run check fast`: workflow syntax, generated types, typecheck,
build, unit (3031 pass, 0 fail).
- `scripts/release-guards.test.ts` builds throwaway git repos and checks
each case: a tagged tree is left alone; a release PR that changed only
the client passes; server, `bun.lock` and dependency changes under an
already-published bundle fail; a raised bundle passes the PR but fails
Release until `remote-vN` exists; a changed Worker without a recorded
deploy fails; missing patch notes fail.
- On this branch: `bun scripts/release-guards.ts` reports "Not a
release" and exits 0. `--release 0.4.8` fails with both expected
messages: 22 bundle inputs changed since remote-v27, and the Worker was
changed since its deploy.
- Simulated the CI step on a `--depth 1` clone: the tag fetch takes
about 3 s and fetches 92 tags. With `package.json` bumped to 0.4.9, all
three problems are reported.
- Mutation check: adding a key to the snapshot that the Worker does not
accept fails the new settings test with the "add it ... deploy the
Worker before releasing" message.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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