fix(server): scope Claude hub usage to its organization#26634

closed1
main
GitHub fork: fix/claude-hub-workspace-identity
opened13d agobyHHelpsHelps2
View on GitHubTwo-way sync enabledPR last imported 1d ago

Problem

Usage → Limits can merge a Claude Team subscription reported by CLIProxyAPI into a personal Max subscription with the same email. With the direct business provider disabled or removed, the business entry disappears and the Max entry can display the business quota instead.

The native Claude provider reports its organization as auth.workspaceId. The hub adapter currently reports a workspace only for Codex. The shared account resolver therefore assigns an unscoped Claude hub report to the only enabled native workspace for that email, even when it is a different subscription.

Change

Read /api/oauth/profile through the existing hub api-call endpoint using the same selected credential as the usage request. Publish organization.uuid as the Claude hub account's existing workspaceId field. The existing shared merger can then keep personal and business quotas separate and deduplicate a native/hub pair for the same organization.

A failed profile request or missing/blank organization ID produces the existing unavailable-account state instead of publishing quota under an ambiguous identity. Codex reporting and request routing are unchanged. No new contract fields, settings, or client-specific changes are needed; all clients consume the corrected hub snapshot.

This adds one profile request per Claude account during a hub quota read. It does not download credential files or expose profile bodies in errors.

Scope and approval

This is a small, focused fix for an obvious identity mismatch in the existing Claude hub reporting capability, under the exception in CONTRIBUTING.md. It fills an existing workspace identity field; it does not add account switching, a new integration, or a new product behavior. One existing adapter test is extended for same-email subscriptions, with a failure table for unavailable organization identity.

Verification

  • Before the implementation, the four focused regression cases failed: same-email Claude accounts had no workspaceId, and failed/malformed profile responses still allowed ambiguous usage to be published.
  • vp test run apps/server/src/usage/cliproxyApi.test.ts packages/shared/src/usageLimits.test.ts — 55 tests passed. These cover hub organization reporting and the existing shared logic for keeping workspaces separate and merging duplicates.
  • vp run check:changed — format, lint, both knip passes, generated GraphQL checks, typechecks for the three affected packages, and all 17 hub-adapter tests passed.
  • Read-only runtime checks on macOS arm64, T3 Code 0.1.4-nightly.20261028.3824, and CLIProxyAPI 8.0.45: /auth-files omitted the Claude organization ID; /api/oauth/profile returned HTTP 200 and its organization UUID matched the business credential. The installed account resolver reproduced the personal/business merge with the native business provider disabled, and separate identities when the hub report carried the business organization ID.
  • The running desktop installation was not patched. No UI code or account credentials are changed by this PR.

Written with GPT-6.1 Sol in the Codex harness, running through T3 Code.

Checks

24 successful · 14 skipped
All checks passed
194f730

Added 1 commit

  • fix(server): scope Claude hub usage to its organization194f730
Synced from GitHub

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code Review⚠️ Failed 2026-10-28T20:30:51.822147Z
We couldn’t complete this review. Comment @codex review to try again.
194f730PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Synced from GitHub

Approvability

Verdict: Approved at 194f730

Macroscope's review found this PR approvable — Claude hub usage now includes the account's organization identifier so usage can be scoped appropriately. The additional read-only profile request uses existing timeout and unavailable-usage handling, without changing permissions or charges.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between 9e09926d97824179d97311d1a810c6b5bb60d2d1 and 194f730b5d42fc1f4447046893659c5ec53cc6ef.

External image Files selected for processing: 2
  • apps/server/src/usage/cliproxyApi.test.ts
  • apps/server/src/usage/cliproxyApi.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

Claude usage reads now fetch and validate the OAuth profile before requesting usage. The profile’s organization UUID becomes the usage result’s workspace ID. Tests cover accounts with distinct organizations and profile lookup or validation failures.

Changes: Claude usage identity

Layer / File(s)Summary
Profile contract
apps/server/src/usage/cliproxyApi.ts
A Claude profile schema and decoder require an organization UUID that is a trimmed, non-empty string.
Profile lookup and workspace identity
apps/server/src/usage/cliproxyApi.ts, apps/server/src/usage/cliproxyApi.test.ts
Claude account reads fetch and decode the profile before requesting usage. The result uses the profile organization UUID as its workspace ID. Tests cover distinct organizations and profile failures; the account fixture allows an omitted id_token.

Priority: External image Normal

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Sequence Diagram(s)

mermaid
1sequenceDiagram
2 participant ClaudeAccountRead
3 participant OAuthProfileEndpoint
4 participant ProfileDecoder
5 participant ClaudeUsageEndpoint
6 ClaudeAccountRead->>OAuthProfileEndpoint: Fetch OAuth profile
7 OAuthProfileEndpoint-->>ClaudeAccountRead: Profile JSON
8 ClaudeAccountRead->>ProfileDecoder: Decode profile JSON
9 ProfileDecoder-->>ClaudeAccountRead: Organization UUID
10 ClaudeAccountRead->>ClaudeUsageEndpoint: Request usage

Possibly related issues

  • pingdotgg/t3code#23054 — The issue concerns pooled-limit identity merging for Codex accounts. This change supplies Claude organization UUIDs as workspace identity, but does not address Codex identity resolution.

Possibly related PRs

Suggested labels: size:M

Suggested reviewers: juliusmarminge, maria-rcks

Merge Risk: External image Minimal · up to 194f7

Claude hub usage is scoped by organization. No merge-blocking issue was identified.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely identifies the main change: scoping Claude hub usage to its organization.
Description checkPassedThe description covers the problem, implementation, scope justification, focused verification, observed results, limitations, and agent details. It is complete and directly aligned with the requested …
Linked Issues checkPassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes checkPassedCheck skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description covers the problem, implementation, scope justification, focused verification, observed results, limitations, and agent details. It is complete and directly aligned with the requested fix.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

Synced from GitHub

Independent confirmation of this fix, from a CLIProxyAPI hub with 5 Claude credentials (2 e-mails that each belong to a Max org and a Team org, plus one single-org e-mail), reported in #33343:

  • /api/oauth/profile through the hub api-call returned HTTP 200 for all 5 credentials, with a distinct organization.uuid per org, so the same e-mail yields two workspace ids.
  • With the same change applied on current main, Usage → Limits → Claude → Weekly showed 5 bars, one per credential, matching the hub's per-credential numbers. Without it there were 3 bars.

Mock hub with the issue's numbers and example e-mails (no real accounts shown):

Before (3 weekly bars)After (5 weekly bars)
BeforeAfter

Agree with treating a failed profile read as unavailable: an unscoped hub report otherwise attaches to the only native workspace for that e-mail. The branch currently conflicts with main (the adapter's config parameter is now hub), so it needs a rebase. I closed my duplicate #33354 in favor of this one.

Thanks, HelpsHelps2, for the earlier fix and detailed verification. Closing as a duplicate of #33602 by Angusross111, whose current head is based on main; this branch now conflicts with main and has not been updated since October 28.