Skip to content

Send one cli.command telemetry event per run - #46

Merged
zmofei merged 4 commits into
mainfrom
telemetry-events
Oct 9, 2026
Merged

zmofei merged 4 commits into
mainfrom
telemetry-events

Conversation

@zmofei

@zmofei zmofei commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Stacked on #91.

Each run sends one cli.command event to Mapbox Events from a detached child, so the command never waits. The schema and Legal's review are in mapbox/event-schema#300.

  • What's sent: the command, its options and outcome. Parameter values only for flags, enums, numbers and code-shaped language/country/types; coordinates send their name, other strings their length. README's Privacy section lists every field.
  • Token: the user's token, then their login, then the CLI's own pk. token as a last fallback (cli_token.rs). A 401 tries the next one.
  • Endpoint: production Events in every build. MAPBOX_INTERNAL_TELEMETRY_URL overrides it only in non-release builds.
  • Skipped: MAPBOX_CLI_NO_TELEMETRY=1, completion, sudo, and uninstall on Windows.

Verified: tests against a loopback server; staging events reached the warehouse. Not verified: Windows locally, and the release pipeline's bundled token (mapbox-cli-private).

Before release: mapbox/event-schema#300 merges and MAPBOX_CLI_BUNDLED_TOKEN is set in mapbox-cli-private.

@zmofei
zmofei changed the base branch from main to run-log September 28, 2026 09:04
@zmofei
zmofei changed the base branch from run-history to run-record September 28, 2026 11:34
@zmofei
zmofei added this pull request to stack #60 September 28, 2026 12:18
@zmofei zmofei self-assigned this Sep 29, 2026
@zmofei
zmofei removed this pull request from stack #60 October 9, 2026 09:57
@zmofei
zmofei changed the base branch from run-record to main October 9, 2026 09:57
@zmofei
zmofei added this pull request to stack #88 October 9, 2026 09:57
@zmofei
zmofei removed this pull request from stack #88 October 9, 2026 11:34
@zmofei
zmofei changed the base branch from main to cli-token October 9, 2026 11:34
@zmofei
zmofei added this pull request to stack #90 October 9, 2026 11:34
@zmofei
zmofei removed this pull request from stack #90 October 9, 2026 11:50
@zmofei
zmofei added this pull request to stack #92 October 9, 2026 11:50
@zmofei zmofei changed the title WIP: Record one cli.command telemetry event per run WIP: Record and send one cli.command telemetry event per run Oct 9, 2026
@zmofei
zmofei removed this pull request from stack #92 October 9, 2026 14:33
@zmofei
zmofei changed the base branch from cli-token to fix/help-groups-navigation October 9, 2026 14:33
@zmofei
zmofei added this pull request to stack #93 October 9, 2026 14:33
@zmofei
zmofei force-pushed the telemetry-events branch 2 times, most recently from 18a5f2c to ebf2948 Compare October 9, 2026 15:36
@zmofei
zmofei marked this pull request as ready for review October 9, 2026 15:39
@zmofei
zmofei requested a review from a team as a code owner October 9, 2026 15:39
@zmofei zmofei changed the title WIP: Record and send one cli.command telemetry event per run Record and send one cli.command telemetry event per run Oct 9, 2026
@zmofei
zmofei removed this pull request from stack #93 October 9, 2026 15:50
@zmofei
zmofei changed the base branch from fix/help-groups-navigation to main October 9, 2026 15:53
@zmofei
zmofei added this pull request to stack #94 October 9, 2026 15:53
zmofei added 3 commits October 9, 2026 19:02
Each run builds one cli.command event from the run record, under the
privacy rules reviewed in mapbox/event-schema#300: a value only for
flags, fixed choices, numbers and language, country or feature-type
codes; coordinates and tile addresses by name only; free strings as
lengths; --data by the keys its spec declares; a userId replaced daily;
no request ids.

A detached child sends it to production Mapbox Events, so the command
never waits. cli_token::send tries tokens in the order its caller
declares: the user's --token or MAPBOX_ACCESS_TOKEN, then the login
(refreshed only when about to expire), then the CLI's own token
(MAPBOX_CLI_TOKEN, then a pk. token compiled in from
MAPBOX_CLI_BUNDLED_TOKEN; build.rs refuses anything else). With no
token the event is dropped. MAPBOX_CLI_NO_TELEMETRY=1 turns it off, and
runs under sudo record nothing.

MAPBOX_INTERNAL_TELEMETRY_URL redirects the send in builds that are not
a production release, and MAPBOX_INTERNAL_TELEMETRY_LOG logs each
delivery. On Windows, detached children no longer hold the caller's
stdout pipe open.
The Privacy section still said only the service is collected and never
credentials. It now lists the command and the shape of its options, the
token kind and account, and that Mapbox Events keeps the token an event
is sent with. The API commands section lists the event's fields.
- Send a language or country value only when it is exactly a code, so a short word can't pass as one.
- Read `--data @<path>` again only when it is a regular file, so a FIFO can't hang the exit.
- Count `MapboxAccessToken` as the user's token, and honor `--use-login` on runs that never parse.
- Skip the event for `uninstall` on Windows, where the sender would keep `mapbox.exe` locked.
- Make `auth logout` wait for a refresh in flight so it can't write the login back.
- Keep `cargo test` from posting to production Events, and test the sudo skip, `--q`'s privacy and new numeric location parameters.
- List every field the event carries in README's Privacy section.
@zmofei zmofei changed the title Record and send one cli.command telemetry event per run Send one cli.command telemetry event per run Oct 9, 2026
@zmofei
zmofei requested a review from mattpodwysocki October 9, 2026 16:05

@mattpodwysocki mattpodwysocki left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Went deep on this one given what it's doing, first time this CLI sends anything recurring rather than a one-time install ping. Read telemetry_event.rs directly rather than trusting the description: coordinates really do send name only (classify() returns early for anything in COORDINATES, backed by every_numeric_location_parameter_is_a_coordinate which walks every bundled spec and fails the build if a future lon/lat-shaped parameter isn't added to that list), free strings really do reduce to length only, and language/country/types only send the actual value when it's strictly code-shaped. the_event_sends_only_fields_the_schema_declares diffing against a hand-maintained field list is exactly the kind of test that catches a field silently added later without a schema/legal update, and no_request_id_is_sent closes the one leak I'd have worried about most.

Confirmed it's genuinely fire-and-forget: the exit code is computed before run_record::finish() runs, and the actual POST happens in a detached child (reusing update_check's own detach() primitive), with a direct test that sends against a loopback server that never responds and confirms the command doesn't wait. Liked that MAPBOX_INTERNAL_TELEMETRY_URL's production gate is a compile-time const fn checked independently in both the parent and the detached child, so a compromised parent can't hand the child an override a release build would honor. Token fallback order matches the description exactly, and it travels over the child's stdin rather than argv or env, with the user's token explicitly removed from the child's environment before spawning.

Build, fmt, clippy, full suite (unit + the loopback integration tests) all pass. This is some of the most carefully verified privacy-surface code I've seen in this repo, nice work. Approving.

@zmofei
zmofei merged commit d1a8224 into main Oct 9, 2026
8 checks 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.

2 participants