fix(usage): keep Codex workspace seats that share an email

Merged
TS
2d ago
+132-18

What & why

Fixes #9058.

The Codex cards on the Usage tab were deduped by email alone. One email can hold a personal ChatGPT account and a workspace seat, each signed in from its own CODEX_HOME with its own tokens.account_id. When both homes answered, the home that sorts later lost its card; the default home comes first. In the reported setup the lost card was the workspace seat. The seat appeared only while its read failed, because a failed card has no email and is keyed by its auth.json path instead.

A hidden home could not be made the default or removed either. Both mutations check the selection against the same deduped list and answered BAD_REQUEST.

The dedupe now keys on email plus the ChatGPT account id, which codex.ts already reads to send as chatgpt-account-id. One account signed in from several homes still shows once, and the default home still wins. A home whose auth.json states no account id is never merged into another; a duplicate card is better than a hidden account. That last rule came out of review. The tRPC output shape does not change. Only the module-private fetchCodexAccountForHome now also returns the account id, and the dedupe moved into an exported pure helper so it can be tested.

How I tested it

  • bun test src/trpc/router/usage in packages/host-service: 152 pass on bun 1.3.11 (the repo pins 1.4.3). The new codex.test.ts covers five cases:
    • a personal account and a workspace seat on one email;
    • one account signed in from two homes;
    • two people in one workspace;
    • homes with no email;
    • homes on one email that state no account id.
  • The first test fails when the old email-only key is put back.
  • ./scripts/lint.sh is clean (11,791 files).
  • bun run typecheck in packages/host-service on my machine reports 21 errors, all in packages/trpc and packages/auth (better-auth plugin types). I get the same 21 on unmodified main, and upstream CI passed typecheck on that commit, so I take them to be my local install (wrong bun version). None are in the changed files. I am relying on this PR's CI for the typecheck result.
  • No screenshots: I did not run the dev app. The bug was seen on the 2.0.0 desktop app with eight personal accounts and eight workspace seats on the same eight emails. Only the eight personal cards showed.

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run lint and bun run typecheck pass. Lint passes; typecheck pending CI, see above.
  • "Allow edits from maintainers" is checked on fork PRs
  • I have signed the CLA (the bot asks on your first PR)

šŸ¤– Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Codex usage results now distinguish ChatGPT accounts that share an email address when their account IDs differ.
    • Duplicate entries for the same email and ChatGPT account are consolidated across homes. Accounts without an email or ChatGPT account ID continue to use their account key for deduplication.