Skip to content

feat(ui): migrate organization billing surface to Mosaic#9164

Draft
alexcarpenter wants to merge 10 commits into
mainfrom
migrate-controllers-machines
Draft

feat(ui): migrate organization billing surface to Mosaic#9164
alexcarpenter wants to merge 10 commits into
mainfrom
migrate-controllers-machines

Conversation

@alexcarpenter

@alexcarpenter alexcarpenter commented Jul 14, 2026

Copy link
Copy Markdown
Member

Description

Migrates the legacy Organization Billing surface into the Mosaic design system, following the machine → controller → view split. Landed incrementally; this PR accumulates the roadmap items.

Each piece ships a Clerk-facing controller (discriminated-union status), a Clerk-free unstyled native-HTML view (all strings/callbacks passed as props), a wrapper that returns null until ready, and controller + view tests. All are exposed via the OrganizationProfile compound namespace and wired into swingset (stories, MDX, registry, DocsViewer).

Per the migration steer, views are intentionally unstyled native HTML with zero localization (hardcoded English mirroring the en-US strings) — the focus is dialing in the controllers and machines, not the visual layer.

Done

  • Subscriptions section
  • Account Credits section
  • Statements list
  • Payment Attempts list
  • Billing panel shell
  • Statement & Payment Attempt detail screens
  • Payment Methods: list + remove + make-default (mutation machines)
  • Panel-level billing gating (org:sys_billing:read/:manage + billing-enabled). The whole panel self-gates and renders nothing for members who cannot view billing, matching the legacy route guard.
  • Remove-payment-method now routes through useReverification (step-up auth), matching the legacy RemoveResourceForm. make-default stays unreverified (legacy parity).

Parity & test confidence

A parity audit compared each Mosaic controller against the legacy behavior it replaced. Core controller/machine logic is at parity; the remaining differences are the intentional in-scope divergences (localization keys → hardcoded en-US, styled components → native HTML, dropped icons, loader → null). Two spots improve on legacy: a fixed non-transitive subscription sort, and a make-default in-flight disable. Coverage was extended with direct billing-format formatter tests and controller characterization tests for previously-uncovered branches (subscription caption lifecycle, subscriberType='user' gate, pending payment intent, empty statement groups, etc.). Suite: 324 mosaic-org tests passing.

Remaining

  • Add-payment-method (Stripe) flow. Deferred deliberately. It renders Stripe's PaymentElement inside a PaymentElementProvider and needs the Stripe appearance-theming bridge, so — unlike every other Mosaic billing view — its element-rendering sub-view cannot be reduced to a Clerk-free, prop-driven component. Until it lands, the Payment Methods section only lists/removes/re-defaults existing methods, matching the legacy RHC-disabled behavior (add button hidden). Documented in organization-billing-payment-methods-section.tsx and the changeset.

Backwards compatibility

Additive only. No existing public API is changed or removed, and the legacy organization billing page is untouched. New surface is exposed via OrganizationProfile.Billing* namespace entries.

Checklist

  • Changeset added (@clerk/ui minor)
  • Tests included (controller + view + machines per component)

Add Mosaic controller/view/wrapper trios for the organization billing
panel and its Subscriptions, Account Credits, Statements, and Payments
sections, plus the Statement and Payment Attempt detail screens. Each is
exposed via the OrganizationProfile compound namespace. Additive and
backwards-compatible; the legacy billing page is untouched.
Wire swingset stories, MDX docs, registry, and DocsViewer entries for the
migrated organization billing panel, its four sections, and the statement
and payment detail screens.
@changeset-bot

changeset-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2404c8a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@clerk/ui Minor
@clerk/chrome-extension Patch
@clerk/swingset Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swingset Ready Ready Preview, Comment Jul 15, 2026 5:12pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
clerk-js-sandbox Skipped Skipped Jul 15, 2026 5:12pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: f97076ca-329b-4d02-8010-599bdfe66b19

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

Add a Mosaic payment-methods section that lists saved methods and drives
the make-default and remove mutations through dedicated state machines.
Self-gates on org:sys_billing:manage and replaces the legacy
<PaymentMethods/> in the Mosaic billing panel. The Stripe-backed add flow
is not yet migrated. Exposed as OrganizationProfile.BillingPaymentMethodsSection.
The Mosaic payment-methods section lists, removes, and re-defaults
methods but does not yet migrate the Stripe PaymentElement add flow.
Document why (it cannot be a Clerk-free prop-driven view) in the section
and note it in the changeset.
Add an add-payment-method machine, controller wiring, and view entry point to the
Mosaic organization billing payment-methods section. The Clerk-side lifecycle
(open, submit, revalidate, error) is fully migrated and tested; the gateway's
remotely-hosted card element (Stripe) is not rendered here and stays on the legacy
surface, with add.onSubmit as the token seam. The add entry point is hidden in
no-RHC builds.
@pkg-pr-new

pkg-pr-new Bot commented Jul 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@9164

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@9164

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@9164

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@9164

@clerk/electron

npm i https://pkg.pr.new/@clerk/electron@9164

@clerk/electron-passkeys

npm i https://pkg.pr.new/@clerk/electron-passkeys@9164

@clerk/eslint-plugin

npm i https://pkg.pr.new/@clerk/eslint-plugin@9164

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@9164

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@9164

@clerk/express

npm i https://pkg.pr.new/@clerk/express@9164

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@9164

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@9164

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@9164

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@9164

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@9164

@clerk/react

npm i https://pkg.pr.new/@clerk/react@9164

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@9164

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@9164

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@9164

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@9164

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@9164

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@9164

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@9164

commit: 2404c8a

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant