Repository navigation
Conversation
mattpodwysocki
left a comment
There was a problem hiding this comment.
This looks good to me @zmofei. I traced every telemetry path and couldn't find any way for the user's token to reach a send: --token, MAPBOX_ACCESS_TOKEN, the config file and the stored login are never read on that path, the child's env has them stripped, and opt-out is checked before any network work. The deleted fallback chain didn't take anything still needed with it. Build, tests, clippy and fmt are clean.
Just nits, none blocking:
- README around line 494: "never yours" isn't quite true if someone puts their own
pk.token inMAPBOX_CLI_TOKEN, which the README documents and a release build honors. A few words saying it's a developer override for a different CLI token would cover it. That paragraph could use a reflow too (long line 495, "The token is" left on its own at 505). SEND_TIMEOUTinsrc/telemetry_sink.rsis described as the child's time budget, but it only bounds the POST. With the fetch, the Tokens API check and a refetch, the child can run about 25s. Harmless since it's detached, the comment just misleads.- The never-the-user's-token tests use
sk.andtk.values. Adding apk.user token toa_logged_in_run_sends_with_the_clis_tokenwould catch a regression that brought back a plausible-user-token fallback, which thepk.filter would otherwise let through.
| ); | ||
| match attempt { | ||
| CliAttempt::Done(result) => return result, | ||
| CliAttempt::Unusable { error, why, .. } if !caller.user_fallback() => { |
There was a problem hiding this comment.
This arm can't be reached today, since report is the only command caller and it has user_fallback: true. On a dry run it would also execute with no token at all. Could we drop it until a caller needs it, or add a test that covers it?
There was a problem hiding this comment.
Dropped it in 470bca1. No command uses a policy without user_fallback, so instead a test (every_cli_token_command_has_the_command_policy) now fails if one is added.
bbe0165 to
71f5234
Compare
Mapbox Events keeps the token an event was sent with, and the request logs record it as access_token, so sending with a user's token stored a login's tk. token or a secret sk. one there. Telemetry now sends only with MAPBOX_CLI_TOKEN or the fetched CLI token, and drops the event when neither can be used. The user-token plumbing to the send child is removed. An event is sent at most once. A refused CLI token is still checked, and a dead one replaced at once, so the next run's event uses the new token. While telemetry rests from a token an API refused, the endpoint is asked for another on the existing fetch schedule: the rested token served again counts as a miss, and a different token ends the rest. report is unchanged: it keeps its resend and its fallback to the user's token.
Keep a rest's misses on its cooldown so they no longer shorten a dead token's wait, and keep the rest when the same token is taken back. Require MAPBOX_CLI_TOKEN to be a pk. token for telemetry, and say why an event was dropped in the delivery log. Remove the unused retry policy parameter, and bring the docs and changelog in line with the behavior.
Test that a refused MAPBOX_CLI_TOKEN is never checked or replaced, that it is sent through a rest or fetch pause, that no user token reaches the fetched-token send, and how a rest that outlasts the fetch pause behaves. Pull report's refusal handling into cli_attempt so it can be unit-tested.
Only the token on disk is shared now. Each background caller (today only telemetry) keeps its own count of failures in a row: a fetch with no usable token, or a refusal after which the endpoint, asked at once, serves no different token. The third failure quiets the caller for an hour, in which it sends and fetches nothing. An accepted request or a different token starts the count over. This replaces the global fetch pause and the per-caller rest, with its misses and rotation-during-rest rules. Waits an earlier build wrote to cli-token.json are not read. `mapbox report` and MAPBOX_CLI_TOKEN are never held by telemetry's count, and report never writes it.
…y once A new token on disk now ends every caller's failure count and quiet period, whichever caller saved it. Each count records the token it was made with, so a count merged back by a run that still had the old token holds nobody back. Telemetry and commands now differ only by a Policy (paced, resends, user_fallback) named next to each caller, instead of separate entry points and ledger variants.
…e no-CLI-token outcome
71f5234 to
e1786c3
Compare
…a pk. user token - Remove the command path for a caller without user_fallback. No command uses one, so a test now holds every CLI-token command to the COMMAND policy instead. - README: say MAPBOX_CLI_TOKEN is a developer override for another CLI token, and reflow the paragraph. - SEND_TIMEOUT bounds only the POST, not the child. - Use a pk. user token in a_logged_in_run_sends_with_the_clis_token, so a fallback gated on is_plausible would be caught.
|
@mattpodwysocki Thanks! All four addressed in 470bca1:
fmt, clippy and the full suite pass locally. Could you take another look? |
Telemetry events are now sent only with the CLI's own public token:
MAPBOX_CLI_TOKENwhen set, otherwise the token fetched fromhttps://cli.mapbox.com/config/token.json. A user's token (--token,MAPBOX_ACCESS_TOKEN, a login) is never used for telemetry.no_tokenline says why (quiet,override_not_public).paced,resends,user_fallback): telemetry is paced, never resends and never falls back to the user's token;reportis not paced, resends once with a fresh token, and may fall back. Adding a caller is one entry.MAPBOX_CLI_TOKENmust be apk.token. It is sent as is, never checked or replaced, even while telemetry is quiet.mapbox reportis unchanged: it still prefers the CLI's token, falls back to the user's, and resends with a fresh token after a refusal.README, CHANGELOG and
docs/architecture.mdare updated.Testing: fmt, clippy and the full suite (916 tests) pass locally on macOS, and CI passes on all three runners at bbe0165. New tests cover a user's token never appearing in a telemetry request on the override and fetched-token paths; nothing sent when the CLI token is unusable; no resend after a 401/403; a different token after a refusal used by the next run; three failures quieting telemetry for an hour and nothing sent or fetched meanwhile; another caller's state and an earlier build's waits not holding telemetry; a non-
pk.override dropped; and an old-format state file. Each new test was seen failing under a mutation of its behavior. Against production, with this branch's build: 10 commands sent 10 events, all accepted (204), while the user's own login was invalid; a run with no login and an empty config directory fetched the CLI token from the real endpoint and its event was accepted too. Not verified: the Tokens API on a real refusal, since none occurred.report's resend and fallback after a refusal have no end-to-end test, since nothing points a command's API request at loopback; the outcome mapping is unit-tested.Known follow-ups, not in this PR: right after a rotation, a revoked token can cost two Tokens API calls in the background sender;
Policy's three flags allow combinations no caller uses;refusedreads the state file several times per refusal.Downstream: events from users who have their own token now carry the CLI's token, so the token-derived
owneron those rows becomes the CLI token's account. The user's account is still in the event'sauth.account. Operational: none, no deploy.