feat: telemetry carries the backend user id and tenant when signed in
Closes #1498
What
Telemetry events carry the backend user uuid and tenant when the machine is signed in to Altimate, and the CLI names itself on backend calls.
- New
telemetry/identity.ts: resolves the signed-in user once per credential (GET /users/me, the call the workspace client already makes) and caches{ user_id, tenant }at~/.altimate/telemetry-identity.jsonunder a fingerprint of the credential, owner-only. A changed credential, a sign-out or a forced refresh invalidates it. Every failure resolves to nothing; telemetry never waits on the backend. telemetry/index.ts: stampsuser_idandtenanton every event's properties and uses the uuid asai.user.id, with the machine id as the fallback for anonymous use. The hashed account email is gone: no email, hashed or not, leaves the client.refreshIdentity()re-resolves after a sign-in in the same process;shutdown()clears it.plugin/altimate.ts: the browser sign-in callsrefreshIdentity()after it saves the credential.api/client.tsandworkspace/api-client.ts: every backend call sendsx-altimate-client: altimate-code/<version>.
Why
Web events are keyed by the backend user uuid; CLI events were keyed by the machine only, so nothing joined a CLI session to the account that created or linked the workspace it uses. One key on both sides lets the dashboards follow a user from the web into the CLI. The client header lets the backend tell which client made a create or link call.
Verification
bun test test/altimate/telemetry/identity.test.ts: 3 tests, 46 assertions. Resolution, caching and cache invalidation against a stubbed/users/me; the request headers; the cache file's mode; envelopes posted to a stubbed ingest endpoint carryuser_id,tenantandai.user.id = uuidwhen signed in, and only the machine id after sign-out; no email in any property.- Existing telemetry suites (first-run health, onboarding, safety, install telemetry, trace context): 76 pass.
tsgo --noEmitclean; oxlint and prettier clean on the changed files.
Anonymous sessions are unchanged apart from the removed email hash, which in practice was never set.
Review log (claims and residuals Codex reviews against): https://github.com/AltimateAI/altimate-code/pull/1500#issuecomment-6186948236
🤖 Generated with Claude Code
https://claude.ai/code/session_011AhtJPr3nmT1Po92ZQk4VE
Summary by cubic
Telemetry events now carry the backend user UUID and tenant when the machine is signed in to Altimate, so CLI events join web events on the same account key. The hashed account email is no longer sent.
Behavior
- Identity is resolved once per credential via
GET /users/meand cached in~/.altimate/telemetry-identity.json(owner-only, keyed by a credential fingerprint); a changed credential, sign-out, or forced refresh invalidates it. - Credentials are read like the provider: the
~/.altimate/altimate.jsonfile first, else thealtimate-backendauth-store key, normalised to drop a trailing slash. Credential changes on disk are noticed at the next flush; a buffered batch keeps the identity it was tracked under, a 401 or 403 drops the cache, and a failed lookup is retried after a 60 s backoff instead of on every flush. - In-flight resolutions are generation-guarded, so a stale response — for a previous credential or one removed mid-flight — can never overwrite a newer sign-in or a shutdown.
- Backend calls from the CLI now send
x-altimate-client: altimate-code/<version>so the server can attribute create and link calls. - Anonymous sessions are unchanged apart from the removed email hash, which in practice was never set.
- Source-guard tests now assert
Account.active()is no longer called, since identity comes from the stored credential.
Summary by CodeRabbit
-
New Features
- Telemetry events can now include the signed-in Altimate account and tenant when available, with the machine identity used when no account identity is available.
- Altimate API requests now identify the CLI and its installation version.
- Telemetry refreshes its account identity after gateway credentials are saved.
-
Bug Fixes
- Identity lookup and refresh failures no longer interrupt credential setup or telemetry operation.