Skip to content

Maple Agent: account, billing, and settings parity with the web app #890

Description

@AnthonyRonning

Tracking issue for bringing the Maple Agent app (apps/maple-agent, formerly benthecarman/maple-gpui) to feature parity with the web app's account, billing, and settings features.

Done (merged as benthecarman/maple-gpui #55#60, now in apps/maple-agent)

  • Settings → Account: email with verified badge and resend, sign-in method, member since, sign out (sends POST /logout; the backend does not revoke the refresh token yet).
  • Change password for email and anonymous accounts, with the rotated token pair persisted.
  • Delete account: type DELETE, emailed code plus client secret, runtime stopped before the irreversible call.
  • Billing: full subscription status, Stripe portal, Stripe checkout for individual plans, credit balance, plans on sale.
  • API keys: list, create (shown once), delete; gated on Pro/Max/Team.
  • CLI: maple-gpui login [--email] so acp works without the desktop.

Remaining

1. Deep links and OAuth loopback redirect

OAuth still asks the user to paste the redirect URL back; billing return URLs point at trymaple.ai, as in the Tauri build; reset and pass-redeem email links land in a browser. Decide custom scheme (maple://) versus loopback listener (or both); register per platform (CFBundleURLTypes, .desktop x-scheme-handler, Windows registry); single-instance handoff for a URL arriving while the app runs; route to OAuth completion, billing refresh, reset, redeem; validate state end to end. Test on all three OSes from a bundle and a dev binary. Most of the items below lean on this.

2. Plan gating and quota exhaustion

The web gates images, documents, voice, and models by tier and handles "out of messages" with an upgrade dialog. The agent only has an image gate by plan-label string match. Move gating onto PlanTier, find out what the backend returns when the quota is exhausted mid-task (429 from inference, can_chat: false, or both), and design the recovery: pause the task, offer Upgrade / Buy credits, resume. Needs an exhausted fixture, probably staging.

3. Auth coherence across desktop, acp, and CLI login

auth.json is written by three processes. A password change rotates the token pair, so a running acp for the same account starts failing without explanation. login can switch the account under a running desktop, whose rotation sink may write its own account back. Decide the ownership model (last writer wins, or react to a replaced file, e.g. watch it with notify), and give acp a clear "sign-in changed" message. Validate: desktop + acp during a password change; CLI login as another account while the desktop runs.

4. Delete account: cleanup parity and end-to-end confirm

The web wipes agent data, the proxy key, and workspace preferences before the irreversible call. The agent stops the runtime and drops credentials but leaves the account-scoped local directories (agent/accounts/<scope>/, the ACP config). Decide whether deletion wipes them and whether to stop a running proxy/acp. The confirm step has not been exercised end to end (the local stack has no Resend key).

5. Login screen: signup, guest accounts, forgot password

Backend calls are simple; the rules are not. Guest: warning dialog (Bitcoin-only, no support, back up credentials), show-the-id-once, blocked on Free, no guest → email conversion exists. Password reset destroys encrypted data (hardening warning) and needs the two-step code + client secret flow. Email verification: decide whether the desktop enforces the web's blocking modal and gates, and whether to add an enter-the-code UI. Decide what name signup sends (the web sends "ANON").

6. Billing completeness

Team seat checkout (2–100 seats as quantity), Bitcoin via Zaprite (guests are Bitcoin-only), API credit purchases with the web's rules (10k–1M credits, multiples of 1k, $1 = 1k), pending_plan_change display, auto-refresh after returning from checkout (needs 1), discount/promo, subscription-pass redemption. Local fixtures are not Stripe products, so this needs Stripe test mode on staging and a Zaprite sandbox.

7. Team management and seat-mismatch gating

Client for /v1/maple/team/*; a Team section shown on team plans with admin and member views (create, rename, members, invites, revoke, remove, leave, accept). Seat mismatch means usage is paused on the web: the agent must gate itself the same way, not just show a badge. Invite acceptance from an email link needs 1. Needs a team fixture on staging.

Suggested order

1 and 3 first: deep links unlock 4–7's return and link flows, and the auth coherence gap is the one most likely to bite someone using the CLI and desktop together.

Out of scope here: the backend POST /logout TODO (long-standing, tracked separately).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestplannedOn the roadmap

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions