Skip to content

Muse Code: show a user-selected dev.meta.ai team quota when the login omits quotas - #4011

Merged
steipete merged 7 commits into
steipete:mainfrom
enieuwy:feat/muse-web-team-quota
Sep 26, 2026
Merged

steipete merged 7 commits into
steipete:mainfrom
enieuwy:feat/muse-web-team-quota

Conversation

@enieuwy

@enieuwy enieuwy commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #4002. Replaces #4003, following the conditions in its close comment.

When the Muse Code 5-hour window is idle, POST /muse-code/key omits subs_usage, so CodexBar (and the Muse CLI /usage) show no quota even when the weekly limit has real usage. This adds an opt-in browser-team quota inside the bundled muse.ts plugin. It never infers which team holds the subscription.

How each close condition is met

Condition (#4003 close) This PR
Explicit, user-selected team; no first-match New Browser team ID setting (stored in the existing workspaceID config field, as OpenCode Go and Devin do). Empty by default. A quota is read only when the ID exactly matches a team the session can see.
A setting listing the teams the session can see With no team, or an unknown team, the card shows a Browser teams section listing each visible team's name and ID, and requests no quota. See "Scope decision" below.
Labelled as a browser-team quota, not the CLI plan Separate Browser team quota (dev.meta.ai) section with a Team row, a menu note "Quota from the selected dev.meta.ai browser team", source oauth+web, dataConfidence: estimated (never exact).
Same domain scoping Unchanged: cookie source is Off by default; Automatic reads Chrome/Firefox only; the device token goes only to api.meta.ai; dev.meta.ai gets only the cookie.
Present/omitted/expired-window fixtures on both engines; wrong-team and list-order cases Added to MusePluginTests, run on both plugin engines.

Extra guards:

  • The team quota's tier must equal the login's subs_tier_name; a different plan shows no browser reading (covers "Everyday quota under a Power login").
  • The session email (/api/auth/me) must match the CLI login email.
  • A weekly reset in the past shows no browser reading; an idle/expired 5-hour window shows 0% with no reset time.
  • Present subs_usage always wins; the browser is never contacted.

The new suite fails against the #4003 plugin (wrong team, list order, different plan, expired windows) and passes here.

Scope decision

The team list lives in the menu card, and the setting is a text field, not a picker. A real Settings picker needs either a new plugin API that returns the team list or a public Core function that reads the browser cookie from the Settings pane (as Kilo's Refresh does). I kept that out to avoid widening the plugin host; happy to add it as a follow-up if you prefer the picker.

Proof

.github/pr-proof/muse-web-team-quota.log — real account, production CLI path, no CodexBar Keychain read, 5-hour window idle:

Run Result
Brew 0.66.0 oauth, Quota: Not included in this login response
Branch, default (Off) same as Brew; no browser read
Branch, no team Browser teams list; no quota request
Branch, team not visible "not visible to this session"; no quota request
Branch, real team oauth+web, estimated, 5h 0%, weekly 22.58% (matches direct endpoint: 13,550,839,000 / 60,000,000,000)

Different-plan and multi-team order cases can't be shown with a one-team account; fixtures cover them.

Existing coverage

Searched issues/PRs for muse, meta.ai, subscription-quota, llama_dev_sess:

Validation

  • swift test --filter 'MusePluginTests|MuseMenuCardModelTests|MuseCredentialsTests|MuseKeychainAccessTests|ProviderArchitectureGatekeeperTests|ProviderPluginRuntimeTests|ProviderSettingsDescriptorTests|ConfigValidationTests|MenuCardModel|OpenCodeGoMenuCardModelTests|CookieProviderCutover|BrowserCookieAccessGate' — 354 tests pass
  • make check — 0 violations
  • Two adversarial reviews of the authority chain and tests; all findings fixed.

@clawsweeper

clawsweeper Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review blocked

Automated review did not run, so no review verdict was produced.

Reason: The input-safety check rejected material in this revision. No detected value, path, or scanner output is reproduced here.

ClawSweeper will not retry this unchanged revision.

Next step: If this is a genuine credential, remove and rotate it. If it is an intentional test fixture, a maintainer must review and qualify it.

View the workflow run.

@enieuwy
enieuwy force-pushed the feat/muse-web-team-quota branch from d1d4af8 to e8d977d Compare September 26, 2026 01:08
@enieuwy
enieuwy force-pushed the feat/muse-web-team-quota branch from e8d977d to 2cd6b2e Compare September 26, 2026 01:08
@enieuwy

enieuwy commented Sep 26, 2026

Copy link
Copy Markdown
Contributor Author

The input-safety block looks like a pre-existing fixture, not new material.

TruffleHog (3.97.9, run locally) finds nothing in this PR's diff or body. Scanning the full changed files gives one hit: the URI detector on Tests/CodexBarTests/ConfigValidationTests.swift:184:

"https://user:pass@sub2api.example.com",

That line is already on main (the sub2api rejects unsafe base URLs fake-URL test). This PR only changes line 382 of that file, adding muse to the workspaceID provider list in the validation message.

Could a maintainer qualify that fixture so the review can run? I left the line unchanged to keep unrelated tests out of this PR.

Separately, revision 2 replaced a real team ID in the Muse fixtures with a fictitious one.

steipete and others added 5 commits September 25, 2026 19:11
Preserve the contributor commits while bringing the Muse quota work onto the
current development baseline. Maintainer corrections follow separately.

Refs steipete#4011.
Co-authored-by: enieuwy <121954036+enieuwy@users.noreply.github.com>
List visible teams in settings without choosing one implicitly. Preserve a
selected team that becomes unavailable, and disclose browser-team quota usage.
Try later browser sessions after account mismatches or expired credentials,
with a five-request budget. Keep malformed resets and durations unknown.

Add synthetic regressions on both plugin engines and menu rendering proof.
Move the release note to the current Unreleased section and credit enieuwy.

Fixes steipete#4002.
Refs steipete#4011.
@steipete
steipete merged commit a818bf1 into steipete:main Sep 26, 2026
9 checks passed
@steipete

Copy link
Copy Markdown
Owner

Merged as yours, @enieuwy, with your commits intact; the maintainer commits on your branch replaced the pasted team ID with a picker of the teams the session can see, added bounded session iteration after wrong-account responses, and brought in fixtures, docs, and the changelog line. It ships in 0.67.1. Thanks for the rework!

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.

Muse Code quota disappears while the 5-hour window is idle

2 participants