Skip to content

feat: follow-up prompt to record telemetry denial#93

Merged
8bitAlex merged 2 commits into
mainfrom
feat/telemetry-opt-out-followup-prompt
May 14, 2026
Merged

feat: follow-up prompt to record telemetry denial#93
8bitAlex merged 2 commits into
mainfrom
feat/telemetry-opt-out-followup-prompt

Conversation

@8bitAlex
Copy link
Copy Markdown
Owner

Summary

When a user declines the first-run telemetry prompt, raid now asks one follow-up: may we send a single anonymous event recording your denial? Default is no (capital N), just like the main prompt.

raid would like to send anonymous usage telemetry to help prioritize features.
…
  [y] yes, send telemetry      [N] no, leave it off       [?] what's collected
> n

Telemetry is off. May raid send a single anonymous event recording your decision?
This is the only event raid would ever send; it helps the project measure how
many users opt out vs. opt in. Same anonymity guarantees as above.

  [y] yes, send once       [N] no, send nothing at all
> 

If accepted, raid fires exactly one raid_telemetry_opt_out event (with reason: "prompt-declined") under explicit per-event consent and then leaves telemetry permanently off. If declined or skipped, raid makes zero network calls for the remainder of the install.

Why this matters. Opt-out rate is the most useful single data point for prioritization that's otherwise impossible to recover from website analytics alone — without it, we can't tell whether a quiet user opted out actively or just never finished setup.

Implementation

  • New CaptureOptOutConsented(reason string) in telemetry.go bypasses the IsActive() gate (which is false the moment after a decline because the state hasn't been written yet) but still respects the two hard kill-switches: a build with no APIKey and DO_NOT_TRACK. The function comment scopes its use strictly to the prompt-decline path — the trust model rests on per-event consent being explicit.
  • Follow-up wired into prompt.go on the explicit-decline branch of MaybePromptForConsent. All skip paths (non-TTY, headless, DO_NOT_TRACK, already-decided, raid telemetry ... invocations) continue to ask nothing further.
  • The EOF case (stray Enter, closed stdin after the main prompt) defaults to no — verified by a dedicated test.

Test plan

  • go test ./... -race — all packages green
  • TestMaybePromptForConsent_declineThenConsentToOptOutEvent — happy path: decline + yes → exactly one event delivered + state persisted off
  • TestMaybePromptForConsent_declineRefuseOptOutEventSendsNothing — decline + no → zero events
  • TestMaybePromptForConsent_declineEmptyFollowUpSendsNothing — decline + EOF → zero events
  • TestMaybePromptForConsent_acceptSkipsFollowUp — accept main → no follow-up prompt rendered
  • TestCaptureOptOutConsented_bypassesInactive — fires when IsActive() == false, payload includes event name + reason
  • TestCaptureOptOutConsented_respectsAPIKeyEmpty — no-op when APIKey == ""
  • TestCaptureOptOutConsented_respectsDoNotTrack — no-op when DO_NOT_TRACK=1
  • askOptOutEventConsent and optOutFollowUpText at 100% line coverage
  • cd site && npm run build — no broken anchors

Docs

🤖 Generated with Claude Code

When a user declines the first-run telemetry prompt, raid now asks
one follow-up: may we send a single anonymous event recording
your denial? Default is no (capital N) just like the main prompt.
If accepted, raid fires exactly one raid_telemetry_opt_out event
(reason: "prompt-declined") under explicit per-event consent and
then leaves telemetry permanently off. If declined or skipped, raid
makes zero network calls for the remainder of the install.

The opt-out-rate signal is the most useful single data point for
prioritization that's otherwise impossible to recover from website
analytics alone — without it, we can't tell whether a quiet user
opted out actively or just never finished setup.

Implementation:
- New CaptureOptOutConsented(reason) bypasses the IsActive() gate
  (which is false the moment after a decline) but still respects
  APIKey == "" and DO_NOT_TRACK. Scoped strictly to this code path
  in a comment — the trust model rests on per-event consent being
  explicit.
- Follow-up runs only on the explicit-decline branch of
  MaybePromptForConsent. All skip paths (non-TTY, headless,
  DO_NOT_TRACK, already-decided, telemetry subcommand) continue
  to ask nothing further.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 21:39
@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

❌ Patch coverage is 93.10345% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.81%. Comparing base (6e1e6e0) to head (11f52a3).

Files with missing lines Patch % Lines
src/internal/telemetry/telemetry.go 77.77% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #93      +/-   ##
==========================================
+ Coverage   90.80%   90.81%   +0.01%     
==========================================
  Files          47       47              
  Lines        4034     4063      +29     
==========================================
+ Hits         3663     3690      +27     
- Misses        244      245       +1     
- Partials      127      128       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a first-run follow-up prompt that (only with explicit per-event consent) allows sending a single anonymous raid_telemetry_opt_out event after a user declines telemetry, so the project can measure opt-out rate while keeping telemetry permanently disabled.

Changes:

  • Introduces CaptureOptOutConsented(reason) to send the opt-out event even when IsActive() is false, while still honoring APIKey == "" and DO_NOT_TRACK.
  • Wires a follow-up consent prompt into MaybePromptForConsent’s decline path and adds targeted tests for the new behavior (including EOF/Enter defaulting to “no”).
  • Updates telemetry documentation and release notes to describe the new follow-up and the new reason: "prompt-declined" value.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/internal/telemetry/telemetry.go Adds a new synchronous, per-event-consent opt-out capture path that bypasses IsActive().
src/internal/telemetry/prompt.go Adds a follow-up prompt on decline and conditionally fires the one-off opt-out event.
src/internal/telemetry/telemetry_test.go Adds tests covering follow-up consent outcomes and the new capture entry point’s gates.
site/docs/telemetry.mdx Documents the follow-up prompt and expands the opt-out event’s reason semantics.
site/docs/whats-new.mdx Adds release note entry describing the follow-up prompt and one-off event behavior.

Comment on lines +101 to +105
// CaptureOptOutConsented fires the opt-out event under explicit
// per-event consent — used by the first-run prompt when a user
// declines telemetry generally but agrees to send a single
// anonymous "denial recorded" event. Bypasses the standard
// IsActive() gate (which would short-circuit because consent has
Comment thread site/docs/telemetry.mdx
Comment on lines +52 to +55
### Follow-up: may we record the denial?

If you decline the first prompt, raid asks one follow-up question:

Comment on lines +724 to +726
// "y" accepts. If the follow-up wrongly fired, the second line
// would be the input — but the test reader has only one line,
// so the missing line proves the follow-up was skipped.
Updates the telemetry package godoc and the public telemetry docs page
to spell out the narrow per-event-consent exception introduced by the
follow-up prompt (CaptureOptOutConsented may create the anonymous ID
and send one event after a declined first-run prompt). Also clarifies
the test comment for TestMaybePromptForConsent_acceptSkipsFollowUp so
it describes the actual output-based assertion rather than the input
length.

Co-Authored-By: Copilot <copilot@github.com>
@8bitAlex
Copy link
Copy Markdown
Owner Author

Auto-review by meeseeks

Updates pushed: 1 commit

  • 11f52a3 — fix: address Copilot review — document consented opt-out exception

Copilot comments addressed: 3 of 3

  • telemetry.go:24 — package godoc updated to spell out the two narrow exceptions (consent-decision marker + CaptureOptOutConsented) to the "no anonymous ID until opt-in" rule.
  • telemetry.mdx:12 — disclosure paragraph now calls out the follow-up exception alongside the "off by default" claim, linking to the follow-up section.
  • telemetry_test.go:726 — comment rewritten to describe the actual output-based assertion instead of relying on input-length reasoning.

Skipped: 0

Codecov patch: 93.10% (project 90.81%, +0.01%) — at-or-above project, both checks green.
Other CI: green (build matrix, docs, CodeQL, version-check all passing).

@8bitAlex 8bitAlex merged commit bc12743 into main May 14, 2026
13 checks passed
@8bitAlex 8bitAlex deleted the feat/telemetry-opt-out-followup-prompt branch May 14, 2026 21:54
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.

3 participants