feat: send one final telemetry_opted_out event when telemetry is disabled

RA
3d ago
+366-1

Closes #1499

Stacked on #1500 (user id and tenant on events); review this one after it, or read only the last commit.

What

When telemetry is disabled, a machine that has sent telemetry before sends exactly one final telemetry_opted_out event, and then nothing until telemetry is turned back on.

  • New telemetry/opt-out.ts: the marker file ~/.altimate/telemetry-opted-out next to the machine id, and a read of the machine id that never mints one.
  • telemetry/index.ts: recordOptOut(source) runs from both disabled branches of init (env for the environment variables, config for telemetry.disabled). It stops at once when the marker exists or no machine id exists, applies the same sink rules as a normal init (test runners never reach the production sink), uses the identity cached by an earlier signed-in run without any request, posts one envelope with a 3 s cap, and writes the marker only once the ingest endpoint accepted it, so an offline launch tries again next time. The event carries machine_id, cli_version, opt_out_source, and user_id and tenant when they were cached. A normal init clears the marker.
  • The event type is declared in the union for documentation; it is never sent through track().

Why

Telemetry is on by default and can be turned off. An opted-out machine goes silent, which on the dashboards is indistinguishable from a client that stopped emitting, so missing events get investigated as bugs. With the opt-out as the last event, the dashboards can state the opt-out count and attribute the silence that follows. Opt-outs set before the first launch produce no event; the dashboard states that remainder as unknowable.

Verification

  • bun test test/altimate/telemetry/opt-out.test.ts: 4 tests. The final event and its properties against a stubbed ingest endpoint, with the identity taken from the cache and no request to resolve it; nothing sent afterwards and nothing on a later init; no event and no marker without a machine id; the marker only after a 2xx (a 500 leaves it for the next launch); a normal init removes the marker.
  • Identity suite (3) and the existing telemetry suites pass; tsgo --noEmit clean; oxlint and prettier clean on the new files.

Review log (claims and residuals Codex reviews against): https://github.com/AltimateAI/altimate-code/pull/1501#issuecomment-6186949559

šŸ¤– Generated with Claude Code

https://claude.ai/code/session_011AhtJPr3nmT1Po92ZQk4VE


Summary by cubic

Sends one final telemetry_opted_out event when telemetry is disabled, so dashboards can distinguish opted-out machines from clients that stopped emitting. Closes #1499.

  • The event carries the machine id, CLI version, opt-out source, and cached user id and tenant; it is sent at most once, guarded by a telemetry-opted-out marker file next to the machine id.
  • The marker is written only after the ingest endpoint accepted the event, so an offline launch retries next time; a normal init clears it, so a later opt-out is recorded again.
  • A send still in flight when telemetry is re-enabled is dropped, so it never recreates the marker for the new lifecycle.
  • The machine id is read without minting one, so machines that never sent telemetry send nothing; the opt-out path never runs under the force flag or a test runner unless a test opts in.